纯shader实现圆圈内缓缓上升的波浪线
1. demo效果
小球波浪效果
2. RawShaderMaterial介绍
我们之前在three.js中使用着色器,大多时候都是通过ShaderMaterial着色器材质传入着色器程序,使用这个着色器材质比较方便,因为three.js已经内置了很多常用的变量如position、color、normal、uv等,其实three.js还提供了另外一个着色器材质RawShaderMaterial,与ShaderMaterial相比唯一的区别就是去掉了上面提到的内置变量,需要什么变量完全自己定义,这一次就使用这个材质完全定义自己需要的变量编写着色器程序
3. demo代码
demo代码量较少,就不一一说明了,请直接查阅代码
<body>
<div id="container"></div>
<script type="text/javascript" src="../three/build/three.js"></script>
<script>
var container;
var camera, scene, planeMesh, renderer;
var uniforms = {
u_resolution: {
type: "v2",
value: new THREE.Vector2()
},
radius: {
type: "f",
value: 0.5
},
u_time: {
type: "f",
value: 0.5
}
};
var vertexShader = `
attribute vec3 position;
void main() {
gl_Position = vec4( position, 1.0 );
}
`
var fragmentShader = `
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
uniform float radius;
void main( void ) {
vec2 uv = (gl_FragCoord.xy * 2. - u_resolution) / u_resolution.y;
vec2 center = vec2(.0,.0);
float dist = distance(center,uv);
float angularVelocity = 12.0;//角速度
float frequency = 12.0;//频率
float amplitude = 0.05;//振幅
float offset = -0.5;//偏距
float initialPhase = frequency * u_time;//初相位
float y = amplitude * sin((angularVelocity*uv.x)+initialPhase)+offset;//波浪函数
if(y < 1.0){
y += u_time/10.0;
}
if(dist < radius){//在圆内
if(uv.y < y){//波浪以下部分着色
gl_FragColor = vec4(0.1,0.6,0.9,1.0);
}else{
gl_FragColor = vec4(0.1,0.2,0.3,.6);
}
}
}
`
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.Camera();
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(2, 2);
var material = new THREE.RawShaderMaterial({
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader
});
planeMesh = new THREE.Mesh(geometry, material);
scene.add(planeMesh);
renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 800); //设置窗口大小800px*800px
container.appendChild(renderer.domElement);
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
}
function animate() {
requestAnimationFrame(animate);
planeMesh.material.uniforms.u_time.value += 0.02;
if (planeMesh.material.uniforms.u_time.value > 10.0) {
planeMesh.material.uniforms.u_time.value = 0.0
}
renderer.render(scene, camera);
}
</script>
</body>