如何在 three.js 中实现这个 shadertoy?
How to implement this shadertoy in three.js?
https://www.shadertoy.com/view/4tfXzl
片段着色器有细微的变化:
uniform sampler2D u_texture;
uniform float u_time;
float noise( in vec2 x ) {
vec2 p = floor(x);
vec2 f = fract(x);
vec2 uv = p.xy + f.xy*f.xy*(3.0-2.0*f.xy);
return texture( u_texture, (uv+118.4)/256.0, -100.0 ).x;
}
float fbm( vec2 x) {
float h = 0.0;
for (float i=1.0;i<10.0;i++) {
h+=noise(x*pow(1.6, i))*0.9*pow(0.6, i);
}
return h;
}
float warp(vec2 p, float mm) {
float m = 4.0;
vec2 q = vec2(fbm(vec2(p)), fbm(p+vec2(5.12*u_time*0.01, 1.08)));
vec2 r = vec2(fbm((p+q*m)+vec2(0.1, 4.741)), fbm((p+q*m)+vec2(1.952, 7.845)));
m /= mm;
return fbm(p+r*m);
}
void main() {
vec2 fragCoord = gl_FragCoord.xy;
fragCoord+=vec2(u_time*100.0, 0.0);
float col = warp(fragCoord*0.004, 12.0+fbm(fragCoord*0.005)*16.0);
gl_FragColor = mix(vec4(0.2, 0.4, 1.0, 1.0), vec4(1.0), smoothstep(0.0, 1.0, col));
}
然后我在three.js中创建简单平面并在tick
函数中更新u_time
,但结果只是蓝屏。我做错了什么?
试试看:
let camera, scene, renderer;
let uniforms;
init();
animate();
function init() {
camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
scene = new THREE.Scene();
const geometry = new THREE.PlaneGeometry(2, 2);
uniforms = {
u_time: {
value: 1.0
},
u_texture: {
value: new THREE.TextureLoader().load('https://i.imgur.com/BwLDhLB.png')
}
};
const material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
uniforms['u_time'].value = performance.now() / 1000;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.130.1/build/three.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D u_texture;
uniform float u_time;
float noise( in vec2 x ) {
vec2 p = floor(x);
vec2 f = fract(x);
vec2 uv = p.xy + f.xy*f.xy*(3.0-2.0*f.xy);
return texture( u_texture, (uv+118.4)/256.0, -100.0 ).x;
}
float fbm( vec2 x) {
float h = 0.0;
for (float i=1.0;i<10.0;i++) {
h+=noise(x*pow(1.6, i))*0.9*pow(0.6, i);
}
return h;
}
float warp(vec2 p, float mm) {
float m = 4.0;
vec2 q = vec2(fbm(vec2(p)), fbm(p+vec2(5.12*u_time*0.01, 1.08)));
vec2 r = vec2(fbm((p+q*m)+vec2(0.1, 4.741)), fbm((p+q*m)+vec2(1.952, 7.845)));
m /= mm;
return fbm(p+r*m);
}
void main() {
vec2 fragCoord = gl_FragCoord.xy;
fragCoord+=vec2(u_time*100.0, 0.0);
float col = warp(fragCoord*0.004, 12.0+fbm(fragCoord*0.005)*16.0);
gl_FragColor = mix(vec4(0.2, 0.4, 1.0, 1.0), vec4(1.0), smoothstep(0.0, 1.0, col));
}
</script>
https://www.shadertoy.com/view/4tfXzl
片段着色器有细微的变化:
uniform sampler2D u_texture;
uniform float u_time;
float noise( in vec2 x ) {
vec2 p = floor(x);
vec2 f = fract(x);
vec2 uv = p.xy + f.xy*f.xy*(3.0-2.0*f.xy);
return texture( u_texture, (uv+118.4)/256.0, -100.0 ).x;
}
float fbm( vec2 x) {
float h = 0.0;
for (float i=1.0;i<10.0;i++) {
h+=noise(x*pow(1.6, i))*0.9*pow(0.6, i);
}
return h;
}
float warp(vec2 p, float mm) {
float m = 4.0;
vec2 q = vec2(fbm(vec2(p)), fbm(p+vec2(5.12*u_time*0.01, 1.08)));
vec2 r = vec2(fbm((p+q*m)+vec2(0.1, 4.741)), fbm((p+q*m)+vec2(1.952, 7.845)));
m /= mm;
return fbm(p+r*m);
}
void main() {
vec2 fragCoord = gl_FragCoord.xy;
fragCoord+=vec2(u_time*100.0, 0.0);
float col = warp(fragCoord*0.004, 12.0+fbm(fragCoord*0.005)*16.0);
gl_FragColor = mix(vec4(0.2, 0.4, 1.0, 1.0), vec4(1.0), smoothstep(0.0, 1.0, col));
}
然后我在three.js中创建简单平面并在tick
函数中更新u_time
,但结果只是蓝屏。我做错了什么?
试试看:
let camera, scene, renderer;
let uniforms;
init();
animate();
function init() {
camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
scene = new THREE.Scene();
const geometry = new THREE.PlaneGeometry(2, 2);
uniforms = {
u_time: {
value: 1.0
},
u_texture: {
value: new THREE.TextureLoader().load('https://i.imgur.com/BwLDhLB.png')
}
};
const material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
uniforms['u_time'].value = performance.now() / 1000;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.130.1/build/three.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D u_texture;
uniform float u_time;
float noise( in vec2 x ) {
vec2 p = floor(x);
vec2 f = fract(x);
vec2 uv = p.xy + f.xy*f.xy*(3.0-2.0*f.xy);
return texture( u_texture, (uv+118.4)/256.0, -100.0 ).x;
}
float fbm( vec2 x) {
float h = 0.0;
for (float i=1.0;i<10.0;i++) {
h+=noise(x*pow(1.6, i))*0.9*pow(0.6, i);
}
return h;
}
float warp(vec2 p, float mm) {
float m = 4.0;
vec2 q = vec2(fbm(vec2(p)), fbm(p+vec2(5.12*u_time*0.01, 1.08)));
vec2 r = vec2(fbm((p+q*m)+vec2(0.1, 4.741)), fbm((p+q*m)+vec2(1.952, 7.845)));
m /= mm;
return fbm(p+r*m);
}
void main() {
vec2 fragCoord = gl_FragCoord.xy;
fragCoord+=vec2(u_time*100.0, 0.0);
float col = warp(fragCoord*0.004, 12.0+fbm(fragCoord*0.005)*16.0);
gl_FragColor = mix(vec4(0.2, 0.4, 1.0, 1.0), vec4(1.0), smoothstep(0.0, 1.0, col));
}
</script>