gpt4 book ai didi

android - 将 ShaderToy 转换为 fragment 着色器

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:03:21 67 4
gpt4 key购买 nike

我在 ShaderToy 上遇到了几个着色器,但我没有成功地将它们转换成可在移动设备上使用的格式,例如 .fsh

我有this Shader,我希望能够在移动设备上使用它。

我知道我需要修改 iXXXX 变量并将 mainImage 更改为 main()。

有人知道我该怎么做吗?我无法找到有关如何执行此操作的任何资源,而且我自己也从未遇到过。

float noise(vec2 p)
{
float sample = texture2D(iChannel1,vec2(1.,2.*cos(iGlobalTime))*iGlobalTime*8. + p*1.).x;
sample *= sample;
return sample;
}

float onOff(float a, float b, float c)
{
return step(c, sin(iGlobalTime + a*cos(iGlobalTime*b)));
}

float ramp(float y, float start, float end)
{
float inside = step(start,y) - step(end,y);
float fact = (y-start)/(end-start)*inside;
return (1.-fact) * inside;

}

float stripes(vec2 uv)
{

float noi = noise(uv*vec2(0.5,1.) + vec2(1.,3.));
return ramp(mod(uv.y*4. + iGlobalTime/2.+sin(iGlobalTime + sin(iGlobalTime*0.63)),1.),0.5,0.6)*noi;
}

vec3 getVideo(vec2 uv)
{
vec2 look = uv;
float window = 1./(1.+20.*(look.y-mod(iGlobalTime/4.,1.))*(look.y-mod(iGlobalTime/4.,1.)));
look.x = look.x + sin(look.y*10. + iGlobalTime)/50.*onOff(4.,4.,.3)*(1.+cos(iGlobalTime*80.))*window;
float vShift = 0.4*onOff(2.,3.,.9)*(sin(iGlobalTime)*sin(iGlobalTime*20.) +
(0.5 + 0.1*sin(iGlobalTime*200.)*cos(iGlobalTime)));
look.y = mod(look.y + vShift, 1.);
vec3 video = vec3(texture2D(iChannel0,look));
return video;
}

vec2 screenDistort(vec2 uv)
{
uv -= vec2(.5,.5);
uv = uv*1.2*(1./1.2+2.*uv.x*uv.x*uv.y*uv.y);
uv += vec2(.5,.5);
return uv;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
uv = screenDistort(uv);
vec3 video = getVideo(uv);
float vigAmt = 3.+.3*sin(iGlobalTime + 5.*cos(iGlobalTime*5.));
float vignette = (1.-vigAmt*(uv.y-.5)*(uv.y-.5))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5));

video += stripes(uv);
video += noise(uv*2.)/2.;
video *= vignette;
video *= (12.+mod(uv.y*30.+iGlobalTime,1.))/13.;

fragColor = vec4(video,1.0);
}

最佳答案

我编写了 main() 并在答案底部包含了 ShaderToys 变量的 Sprite 等效变量。

设置

要将着色器应用到您的节点,您需要告诉 SpriteKit 将着色器附加到 .fsh 文件中的 SKSpriteNode。

  1. 为着色器代码创建以 .fsh 结尾的空文本文件。

调酒🌀

shader1.fsh

void main() {

vec4 val = texture2D(_texture, v_tex_coord);
vec4 grad = texture2D(u_gradient, v_tex_coord);

if (val.a < 0.1 && grad.r < 1.0 && grad.a > 0.8) {
vec2 uv = gl_FragCoord.xy / u_sprite_size.xy;
uv = screenDistort(uv);
vec3 video = getVideo(uv);
float vigAmt = 3.+.3*sin(u_time + 5.*cos(u_time*5.));
float vignette = (1.-vigAmt*(uv.y-5)*(uv.y-5.))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5));

video += stripes(uv);
video += noise(uv*2.)/2.;
video *= vignette;
video *= (12.+mod(uv.y*30.+u_time,1.))/13.;

gl_FragColor = vec4(video,1.0);

} else {
gl_FragColor = val;
}

} // end of main()
  1. 接下来,在 SpriteKit 中附加着色器。

shader1.swift

let sprite = self.childNodeWithName("targetSprite") as! SKSpriteNode
let shader = SKShader(fileNamed: "shader1.fsh")
sprite.shader = shader

解释

  • 着色器将每个像素变成效果的颜色 (screenDistort(uv))。
  • main() 是入口点。
  • gl_FragColor 是返回。
  • 针对图像的每个像素执行此代码。
  • 当代码执行时,它会告诉每个像素颜色应该是效果的颜色。 vec4() 调用具有 r、g、b、a 值。

ShaderToys 变量名 -> SpriteKit 变量名

iGlobalTime -> u_time

iResolution -> u_sprite_size

fragCoord.xy -> gl_FragCoord.xy

iChannelX -> 名称为“iChannelX”的 SKUniform 包含 SKTexture

fragColor -> gl_FragColor

由于您拥有 Sprite 等效变量,您现在可以轻松转换 main() 之上的这些剩余方法。

float 噪声{}

float onOff {}

float 坡道{}

float 条纹{}

vec3 getVideo {}

vec2 screenDistort {}

理论

问。为什么 main() 包含 texture2Du_gradient, v_tex_coord

一个。 SpriteKit 使用纹理和 uv 坐标。

紫外线映射

UV 映射是将 2D 图像投影到 3D 模型表面以进行纹理映射的 3D 建模过程。

紫外线坐标

在为网格创建纹理时,您需要一种方法来告诉 OpenGL 图像的哪一部分必须用于每个三角形。这是通过 UV 坐标完成的。每个顶点在其位置之上可以有几个 float U 和 V。这些坐标用于访问和扭曲纹理。

SKShader Class Reference

OpenGL ES for iOS

Best Practices for Shaders

WWDC Session 606 - What's New in SpriteKit - Shaders, Lighters, Shadows

关于android - 将 ShaderToy 转换为 fragment 着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38216285/

67 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com