You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plasma Shader移植到Spark AR后渲染异常(画面压缩至角落)求助

解决Spark AR中Plasma Shader画面压缩至角落的问题

问题背景

将ShaderToy中的Plasma Shader适配到Spark AR的sca格式后,画面被压缩至角落,且对输入参数direction vec2的作用不明确。

转换后的sca代码:

precision highp float;

vec4 main( in vec2 direction, in float time, in vec2 touch, in vec2 screen )
{
    vec2 uv = fragment(std::getVertexTexCoord());
    float t = time/.1 + touch.x;
    vec2  R =  uv.xy, S = screen * 0.01,
          p = ( direction+direction - R ) / R * S,
          q = vec2(cos(-t / 165.), cos( t / 45.))  * S - p;
    t = 1. + cos( length( vec2(cos( t / 98.),  sin( t / 178.)) * S - p ) / 30.) 
           + cos( length( vec2(sin(-t / 124.), cos( t / 104.)) * S - p ) / 20.) 
           + sin( length(q) / 25. ) * sin(q.x / 20.) * sin(q.y / 15.);
    return .5 + .5* cos( (time+touch.y) / vec4(63,78,45,1) + ( t + vec4(0,1,-.5,0) ) *3.14 );
}

原ShaderToy代码:

void mainImage( out vec4 O, vec2 U )
{
    float t = iTime/.1 + iMouse.x;
    vec2  R =  iResolution.xy, S = vec2(160,100),
          p = ( U+U - R ) / R * S,
          q = vec2(cos(-t / 165.), cos( t / 45.))  * S - p;
    t = 1. + cos( length( vec2(cos( t / 98.),  sin( t / 178.)) * S - p ) / 30.) 
           + cos( length( vec2(sin(-t / 124.), cos( t / 104.)) * S - p ) / 20.) 
           + sin( length(q) / 25. ) * sin(q.x / 20.) * sin(q.y / 15.);
    O = .5 + .5* cos( (iTime+iMouse.y) / vec4(63,78,45,1) + ( t + vec4(0,1,-.5,0) ) *3.14 );
}

解决思路

  • 修正坐标系统映射错误
    ShaderToy中U是当前像素的像素坐标,iResolution.xy是屏幕分辨率;而Spark AR中fragment(std::getVertexTexCoord())和direction都是归一化UV坐标(范围0-1),不是像素坐标。你错误地将归一化UV赋值给了代表分辨率的R,这直接导致了画面压缩。

    正确的映射逻辑:

    • 用screen对应原代码的iResolution.xy(即R)
    • 将归一化UV转换为像素坐标:vec2 U = direction * screen;
  • 明确direction参数的作用
    在Spark AR的sca shader入口函数中,direction就是当前片段的归一化UV坐标,和fragment(std::getVertexTexCoord())返回值完全一致,无需重复获取。

  • 还原原代码的缩放参数S
    原代码中S是固定的vec2(160,100),你改成了screen * 0.01,这会导致缩放比例随屏幕尺寸变化,破坏原效果的比例,需要改回固定值。

调整后的完整代码

precision highp float;

vec4 main( in vec2 direction, in float time, in vec2 touch, in vec2 screen )
{
    float t = time / 0.1 + touch.x;
    vec2 R = screen;
    vec2 S = vec2(160, 100);
    vec2 U = direction * R; // 归一化UV转像素坐标
    vec2 p = (U + U - R) / R * S;
    vec2 q = vec2(cos(-t / 165.), cos(t / 45.)) * S - p;
    
    t = 1.0 + cos(length(vec2(cos(t / 98.), sin(t / 178.)) * S - p) / 30.0)
           + cos(length(vec2(sin(-t / 124.), cos(t / 104.)) * S - p) / 20.0)
           + sin(length(q) / 25.0) * sin(q.x / 20.0) * sin(q.y / 15.0);
    
    return 0.5 + 0.5 * cos((time + touch.y) / vec4(63.0, 78.0, 45.0, 1.0) + (t + vec4(0.0, 1.0, -0.5, 0.0)) * 3.14159);
}

内容的提问来源于stack exchange,提问作者Lee Probert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:20:55