shadertoy案例:
准备
const onSceneReady = (scene: Scene) => {const light = new HemisphericLight('light', new Vector3(0, 1, 0), scene);light.intensity = 0.7;Effect.ShadersStore['planeMatVertexShader'] = `precision highp float;attribute vec3 position;attribute vec3 normal;attribute vec2 uv;varying vec3 vPosition;varying vec2 vUV;varying vec3 vNormal;uniform mat4 worldViewProjection;void main(){gl_Position =worldViewProjection * vec4(position, 1.0);vPosition = position;vUV = uv;vNormal = normal;}`;Effect.ShadersStore['planeMatFragmentShader'] = `precision highp float;`const plane = MeshBuilder.CreateGround('plane', { width: 10, height: 5 }, scene);const shaderMat = new ShaderMaterial('shaderMat', scene, 'planeMat', {attributes: ['position', 'normal', 'uv'],uniforms: ['world', 'worldView', 'worldViewProjection', 'view', 'projection']});plane.material = shaderMat;// 获取渲染画布宽高const { width, height } = scene.getEngine().getRenderingCanvas()!;shaderMat.onBindObservable.add(() => {shaderMat.setVector2('iResolution', new Vector2(width, height));shaderMat.setFloat('iTime', time);});let time = 0;scene.registerBeforeRender(() => {time += 0.005;});}
复制片元着色器
Effect.ShadersStore['planeMatFragmentShader'] = `precision highp float;//#define FAST_DESCENT//#define BLACK_AND_WHITEuniform float iTime;uniform vec2 iResolution;varying vec2 vUV;#ifdef FAST_DESCENTconst vec3 cameraDir = normalize(vec3(-2.0, -1.0, -4.0));const float cameraDist = 5.0;const float speed = 3.0;const float zoom = 2.5;const vec3 windowColorA = vec3(0.0, 0.0, 1.5);const vec3 windowColorB = vec3(0.5, 1.5, 2.0);const float fogOffset = 2.5;const float fogDensity = 0.6;const vec3 fogColor = vec3(0.25, 0.0, 0.3);const float lightHeight = 0.5;const float lightSpeed = 0.2;const vec3 lightColorA = vec3(0.6, 0.3, 0.1);const vec3 lightColorB = vec3(0.8, 0.6, 0.4);const vec3 signColorA = vec3(0.0, 0.0, 1.5);const vec3 signColorB = vec3(3.0, 3.0, 3.0);#elseconst vec3 cameraDir = normalize(vec3(-2.0, -1.0, -2.0));const float cameraDist = 9.0;const float speed = 1.0;const float zoom = 3.5;const vec3 windowColorA = vec3(0.0, 0.0, 1.5);const vec3 windowColorB = vec3(0.5, 1.5, 2.0);const float fogOffset = 7.0;const float fogDensity = 0.7;const vec3 fogColor = vec3(0.25, 0.0, 0.3);const float lightHeight = 0.0;const float lightSpeed = 0.15;const vec3 lightColorA = vec3(0.6, 0.3, 0.1);const vec3 lightColorB = vec3(0.8, 0.6, 0.4);const vec3 signColorA = vec3(0.0, 0.0, 1.5);const vec3 signColorB = vec3(3.0, 3.0, 3.0);#endifconst float tau = 6.283185;float hash1(float p) {vec3 p3 = fract(p * vec3(5.3983, 5.4427, 6.9371));p3 += dot(p3, p3.yzx + 19.19);return fract((p3.x + p3.y) * p3.z);}float hash1(vec2 p2) {p2 = fract(p2 * vec2(5.3983, 5.4427));p2 += dot(p2.yx, p2.xy + vec2(21.5351, 14.3137));return fract(p2.x * p2.y * 95.4337);}float hash1(vec2 p2, float p) {vec3 p3 = fract(vec3(5.3983 * p2.x, 5.4427 * p2.y, 6.9371 * p));p3 += dot(p3, p3.yzx + 19.19);return fract((p3.x + p3.y) * p3.z);}vec2 hash2(vec2 p2, float p) {vec3 p3 = fract(vec3(5.3983 * p2.x, 5.4427 * p2.y, 6.9371 * p));p3 += dot(p3, p3.yzx + 19.19);return fract((p3.xx + p3.yz) * p3.zy);}vec3 hash3(vec2 p2) {vec3 p3 = fract(vec3(p2.xyx) * vec3(5.3983, 5.4427, 6.9371));p3 += dot(p3, p3.yxz + 19.19);return fract((p3.xxy + p3.yzz) * p3.zyx);}vec4 hash4(vec2 p2) {vec4 p4 = fract(p2.xyxy * vec4(5.3983, 5.4427, 6.9371, 7.1283));p4 += dot(p4, p4.yxwz + 19.19);return fract((p4.xxxy + p4.yyzz + p4.zwww) * p4.wzyx);}float noise(vec2 p) {vec2 i = floor(p);vec2 f = fract(p);vec2 u = f * f * (3.0 - 2.0 * f);return mix(mix(hash1(i + vec2(0.0, 0.0)),hash1(i + vec2(1.0, 0.0)), u.x),mix(hash1(i + vec2(0.0, 1.0)),hash1(i + vec2(1.0, 1.0)), u.x), u.y);}vec4 castRay(vec3 eye, vec3 ray, vec2 center) {vec2 block = floor(eye.xy);vec3 ri = 1.0 / ray;vec3 rs = sign(ray);vec3 side = 0.5 + 0.5 * rs;vec2 ris = ri.xy * rs.xy;vec2 dis = (block - eye.xy + 0.5 + rs.xy * 0.5) * ri.xy;for (int i = 0; i < 16; ++i) {float d = dot(block - center, cameraDir.xy);float height = 3.0 * hash1(block) - 1.0 + 1.5 * d - 0.1 * d * d;vec2 lo0 = vec2(block);vec2 loX = vec2(0.45, 0.45);vec2 hi0 = vec2(block + 0.55);vec2 hiX = vec2(0.45, 0.45);float dist = 500.0;float face = 0.0;{vec4 signHash = hash4(block);vec2 center = vec2(0.2, -0.4) + vec2(0.6, -0.8) * signHash.xy;float width = 0.06 + 0.1 * signHash.w;vec3 lo = vec3(center.x - width, 0.55, -100.0);vec3 hi = vec3(center.x + width, 0.99, center.y + width + height);float s = step(0.5, signHash.z);lo = vec3(block, 0.0) + mix(lo, lo.yxz, s);hi = vec3(block, 0.0) + mix(hi, hi.yxz, s);vec3 wall = mix(hi, lo, side);vec3 t = (wall - eye) * ri;vec3 dim = step(t.zxy, t) * step(t.yzx, t);float maxT = dot(dim, t);float maxFace = dim.x - dim.y;vec3 p = eye + maxT * ray;dim += step(lo, p) * step(p, hi);if (dim.x * dim.y * dim.z > 0.5) {dist = maxT;face = maxFace;}}for (int j = 0; j < 5; ++j) {float top = height - 0.4 * float(j);vec3 lo = vec3(lo0 + loX * hash2(block, float(j)), -100.0);vec3 hi = vec3(hi0 + hiX * hash2(block, float(j) + 0.5), top);vec3 wall = mix(hi, lo, side);vec3 t = (wall - eye) * ri;vec3 dim = step(t.zxy, t) * step(t.yzx, t);float maxT = dot(dim, t);float maxFace = dim.x - dim.y;vec3 p = eye + maxT * ray;dim += step(lo, p) * step(p, hi);if (dim.x * dim.y * dim.z > 0.5 && maxT < dist) {dist = maxT;face = maxFace;}}if (dist < 400.0) {return vec4(dist, height, face, 1.0);}float t = eye.z * ri.z;vec3 p = eye - t * ray;vec2 g = p.xy - block;vec2 dim = step(dis.xy, dis.yx);dis += dim * ris;block += dim * rs.xy;}return vec4(100.0, 0.0, 0.0, 1.0);}vec3 window(float z, vec2 pos, vec2 id) {float windowSize = 0.03 + 0.12 * hash1(id + 0.1);float windowProb = 0.3 + 0.8 * hash1(id + 0.2);float depth = z / windowSize;float level = floor(depth);vec3 colorA = mix(windowColorA, windowColorB, hash3(id));vec3 colorB = mix(windowColorA, windowColorB, hash3(id + 0.1));vec3 color = mix(colorA, colorB, hash1(id, level));color *= 0.3 + 0.7 * smoothstep(0.1, 0.5, noise(20.0 * pos + 100.0 * hash1(level)));color *= smoothstep(windowProb - 0.2, windowProb + 0.2, hash1(id, level + 0.1));return color * (0.5 - 0.5 * cos(tau * depth));}vec3 addLight(vec3 eye, vec3 ray, float res, float time, float height) {vec2 q = eye.xy + ((height - eye.z) / ray.z) * ray.xy;float row = floor(q.x + 0.5);time += hash1(row);float col = floor(0.125 * q.y - time);float pos = 0.4 + 0.4 * cos(time + tau * hash1(vec2(row, col)));vec3 lightPos = vec3(row, 8.0 * (col + time + pos), height);vec3 lightDir = vec3(0.0, 1.0, 0.0);// http://geomalgorithms.com/a07-_distance.htmlvec3 w = eye - lightPos;float a = dot(ray, ray);float b = dot(ray, lightDir);float c = dot(lightDir, lightDir);float d = dot(ray, w);float e = dot(lightDir, w);float D = a * c - b * b;float s = (b*e - c*d) / D;float t = (a*e - b*d) / D;t = max(t, 0.0);float dist = distance(eye + s * ray, lightPos + t * lightDir);float mask = smoothstep(res + 0.1, res, s);float light = min(1.0 / pow(200.0 * dist * dist / t + 20.0 * t * t, 0.8), 2.0);float fog = exp(-fogDensity * max(s - fogOffset, 0.0));vec3 color = mix(lightColorA, lightColorB, hash3(vec2(row, col)));return mask * light * fog * color;}vec3 addSign(vec3 color, vec3 pos, float side, vec2 id) {vec4 signHash = hash4(id);float s = step(0.5, signHash.z);if ((s - 0.5) * side < 0.1)return color;vec2 center = vec2(0.2, -0.4) + vec2(0.6, -0.8) * signHash.xy;vec2 p = mix(pos.xz, pos.yz, s);float halfWidth = 0.04 + 0.06 * signHash.w;float charCount = floor(1.0 + 8.0 * hash1(id + 0.5));if (center.y - p.y > 2.0 * halfWidth * (charCount + 1.0)) {center.y -= 2.0 * halfWidth * (charCount + 1.5 + 5.0 * hash1(id + 0.6));charCount = floor(2.0 + 12.0 * hash1(id + 0.7));id += 0.05;}vec3 signColor = mix(signColorA, signColorB, hash3(id + 0.5));vec3 outlineColor = mix(signColorA, signColorB, hash3(id + 0.6));float flash = 6.0 - 24.0 * hash1(id + 0.8);flash *= step(3.0, flash);flash = smoothstep(0.1, 0.5, 0.5 + 0.5 * cos(flash * iTime));vec2 halfSize = vec2(halfWidth, halfWidth * charCount);center.y -= halfSize.y;float outline = length(max(abs(p - center) - halfSize, 0.0)) / halfWidth;color *= smoothstep(0.1, 0.4, outline);vec2 charPos = 0.5 * (p - center + halfSize) / halfWidth;vec2 charId = id + 0.05 + 0.1 * floor(charPos);float flicker = hash1(charId);flicker = step(0.93, flicker);flicker = 1.0 - flicker * step(0.96, hash1(charId, iTime));float char = -3.5 + 8.0 * noise(id + 6.0 * charPos);charPos = fract(charPos);char *= smoothstep(0.0, 0.4, charPos.x) * smoothstep(1.0, 0.6, charPos.x);char *= smoothstep(0.0, 0.4, charPos.y) * smoothstep(1.0, 0.6, charPos.y);color = mix(color, signColor, flash * flicker * step(outline, 0.01) * clamp(char, 0.0, 1.0));outline = smoothstep(0.0, 0.2, outline) * smoothstep(0.5, 0.3, outline);return mix(color, outlineColor, flash * outline);}void main() {vec2 center = -speed * iTime * cameraDir.xy;vec3 eye = vec3(center, 0.0) - cameraDist * cameraDir;vec3 forward = normalize(cameraDir);vec3 right = normalize(cross(forward, vec3(0.0, 0.0, 1.0)));vec3 up = cross(right, forward);// vec2 xy = 2.0 * gl_FragCoord.xy - iResolution.xy;vec2 xy = vUV;xy.x *= iResolution.x / iResolution.y;xy -= 0.5;vec3 ray = normalize(xy.x * right + xy.y * up + zoom * forward * 0.4 );vec4 res = castRay(eye, ray, center);vec3 p = eye + res.x * ray;vec2 block = floor(p.xy);vec3 color = window(p.z - res.y, p.xy, block);color = addSign(color, vec3(p.xy - block, p.z - res.y), res.z, block);color = mix(vec3(0.0), color, abs(res.z));float fog = exp(-fogDensity * max(res.x - fogOffset, 0.0));color = mix(fogColor, color, fog);float time = lightSpeed * iTime;color += addLight(eye.xyz, ray.xyz, res.x, time, lightHeight - 0.6);color += addLight(eye.yxz, ray.yxz, res.x, time, lightHeight - 0.4);color += addLight(vec3(-eye.xy, eye.z), vec3(-ray.xy, ray.z), res.x, time, lightHeight - 0.2);color += addLight(vec3(-eye.yx, eye.z), vec3(-ray.yx, ray.z), res.x, time, lightHeight);#ifdef BLACK_AND_WHITEfloat c = clamp(dot(vec3(0.4, 0.3, 0.4), color), 0.0, 1.0);c = 1.0 - pow(1.0 - pow(c, 2.0), 4.0);color = vec3(c);#endifgl_FragColor = vec4(color, 1.0);}
修改
- 在片元着色器顶部添加精度
-
precision highp float;
-
-
添加uniform
-
uniform float iTime;
-
uniform vec2 iResolution;
-
-
添加varying
-
varying vec2 vUV;
-
-
修改main函数
-
将mainImage改成main
-
去掉参数 out vec4 fragColor, in vec2 fragCoord
-
修改变量fragColor成gl_FragColor、修改fragCoord成gl_FragCoord
-
-
修改uv获取
// 将下面代码注释,并替换 //vec2 xy = 2.0 * fragCoord - iResolution.xy;vec2 xy = vUV;xy.x *= iResolution.x / iResolution.y;xy -= 0.5;