实现思路
- 创建顶点着色器和片源作色器
- 通过ThreeJS的 ShaderMaterial手写在ThreeJS场景中展示的作色器
- 通过uniforms向片源作色器传递 要混合的颜色信息
- 通过Three.Clock时钟偏移量的改变我们来改变颜色的信息。
代码实现
const vshader = `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
const fshader = `
uniform vec3 u_color_a;
uniform vec3 u_color_b;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
uniform float u_time;
void main (void)
{
float delta = (sin(u_time)+1.0)/2.0;
vec3 color = mix(u_color_a, u_color_b, delta);
gl_FragColor = vec4(color, 1.0);
}
`
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0.1, 10 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const clock = new THREE.Clock();
const geometry = new THREE.PlaneGeometry( 2, 2 );
const uniforms = {
u_color_a: { value: new THREE.Color(0xff0000) },
u_color_b: { value: new THREE.Color(0x0000ff) },
u_time: { value: 0.0 },
u_mouse: { value:{ x:0.0, y:0.0 }},
u_resolution: { value:{ x:0, y:0 }}
}
const material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: vshader,
fragmentShader: fshader
} );
const plane = new THREE.Mesh( geometry, material );
scene.add( plane );
camera.position.z = 1;
onWindowResize();
if ('ontouchstart' in window){
document.addEventListener('touchmove', move);
}else{
window.addEventListener( 'resize', onWindowResize, false );
document.addEventListener('mousemove', move);
}
function move(evt){
uniforms.u_mouse.value.x = (evt.touches) ? evt.touches[0].clientX : evt.clientX;
uniforms.u_mouse.value.y = (evt.touches) ? evt.touches[0].clientY : evt.clientY;
}
animate();
function onWindowResize( event ) {
const aspectRatio = window.innerWidth/window.innerHeight;
let width, height;
if (aspectRatio>=1){
width = 1;
height = (window.innerHeight/window.innerWidth) * width;
}else{
width = aspectRatio;
height = 1;
}
camera.left = -width;
camera.right = width;
camera.top = height;
camera.bottom = -height;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
uniforms.u_resolution.value.x = window.innerWidth;
uniforms.u_resolution.value.y = window.innerHeight;
}
function animate() {
requestAnimationFrame( animate );
uniforms.u_time.value += clock.getDelta();
renderer.render( scene, camera );
}
实现效果
