GLSL学习 - 根据时间偏移量改变背景颜色

185 阅读1分钟

实现思路

  • 创建顶点着色器和片源作色器
  • 通过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 );

}

实现效果