我不确定你是否已经回答了你的问题,但其他人可能知道 shadertoys 到 THREEJS 的集成步骤。
首先,你需要知道shadertoys是一个片段着色器。话虽如此,您必须设置一个“通用”顶点着色器,它应该适用于所有着色器(片段着色器)。
第 1 步
创建一个“通用”的顶点着色器
varying vec2 vUv;
void main()
{
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
这个顶点着色器非常基础。请注意,我们定义了一个可变变量 vUv 来告诉片段着色器纹理映射在哪里。这很重要,因为我们不会使用屏幕分辨率 (iResolution) 进行基本渲染。我们将改为使用纹理坐标。我们这样做是为了在同一个 THREEJS 场景中的不同对象上集成多个着色器玩具。
第 2 步
选择我们想要的着色器并创建片段着色器。 (我选择了一个简单但性能不错的玩具:Simple tunnel 2D by niklashuss)。
这是这个玩具的给定代码:
void main(void)
{
vec2 p = gl_FragCoord.xy / iResolution.xy;
vec2 q = p - vec2(0.5, 0.5);
q.x += sin(iGlobalTime* 0.6) * 0.2;
q.y += cos(iGlobalTime* 0.4) * 0.3;
float len = length(q);
float a = atan(q.y, q.x) + iGlobalTime * 0.3;
float b = atan(q.y, q.x) + iGlobalTime * 0.3;
float r1 = 0.3 / len + iGlobalTime * 0.5;
float r2 = 0.2 / len + iGlobalTime * 0.5;
float m = (1.0 + sin(iGlobalTime * 0.5)) / 2.0;
vec4 tex1 = texture2D(iChannel0, vec2(a + 0.1 / len, r1 ));
vec4 tex2 = texture2D(iChannel1, vec2(b + 0.1 / len, r2 ));
vec3 col = vec3(mix(tex1, tex2, m));
gl_FragColor = vec4(col * len * 1.5, 1.0);
}
第 3 步
自定义 shadertoy 原始代码以获得完整的 GLSL 片段着色器。
缺少代码的第一件事是制服和变量声明。将它们添加到片段着色器文件的顶部(只需复制并粘贴以下内容):
uniform float iGlobalTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
varying vec2 vUv;
请注意,仅声明了用于该示例的 shadertoys 变量,以及之前在我们的顶点着色器中声明的可变 vUv。
我们必须调整的最后一件事是正确的 UV 映射,因为我们决定不使用屏幕分辨率。为此,只需替换使用 IResolution 制服的行,即:
vec2 p = gl_FragCoord.xy / iResolution.xy;
与:
vec2 p = -1.0 + 2.0 *vUv;
就是这样,您的着色器现在可以在您的 THREEJS 场景中使用了。
第 4 步
您的 THREEJS 代码:
设置制服:
var tuniform = {
iGlobalTime: { type: 'f', value: 0.1 },
iChannel0: { type: 't', value: THREE.ImageUtils.loadTexture( 'textures/tex07.jpg') },
iChannel1: { type: 't', value: THREE.ImageUtils.loadTexture( 'textures/infi.jpg' ) },
};
确保纹理是环绕的:
tuniform.iChannel0.value.wrapS = tuniform.iChannel0.value.wrapT = THREE.RepeatWrapping;
tuniform.iChannel1.value.wrapS = tuniform.iChannel1.value.wrapT = THREE.RepeatWrapping;
使用着色器创建材质并将其添加到平面几何。 planegeometry() 将模拟 shadertoys 700x394 的屏幕分辨率,换句话说,它将最好地转移艺术家打算分享的作品。
var mat = new THREE.ShaderMaterial( {
uniforms: tuniform,
vertexShader: vshader,
fragmentShader: fshader,
side:THREE.DoubleSide
} );
var tobject = new THREE.Mesh( new THREE.PlaneGeometry(700, 394,1,1), mat);
最后,将THREE.Clock() 的增量添加到 iGlobalTime 值,而不是更新函数中的总时间。
tuniform.iGlobalTime.value += clock.getDelta();
就是这样,您现在可以使用此设置运行大多数着色玩具...