没看过的朋友建议从一开始看。
基础代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
}
canvas {
width: 100%;
height: 100%
}
</style>
</head>
<body>
</body>
<script src="./three.js">
</script>
<script src="./OrbitControls.js">
</script>
<script>
const vshader = `
uniform float u_time;
uniform float u_radius;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
const fshader = `
void main()
{
vec3 color = vec3(0.5);
gl_FragColor = vec4(color, 1.0);
}
`
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
1000
);
camera.position.z = 100;
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.BoxGeometry(30, 30, 30, 10, 10, 10);
const uniforms = {};
uniforms.u_time = { value: 0.0 };
uniforms.u_radius = { value: 20.0 };
const material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vshader,
fragmentShader: fshader,
wireframe: true
});
const ball = new THREE.Mesh(geometry, material);
scene.add(ball);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
animate();
function onWindowResize(event) {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
uniforms.u_time.value += clock.getDelta();
renderer.render(scene, camera);
}
</script>
</html>
接下来我们让正方形变成圆。
const vshader = `
uniform float u_time;
uniform float u_radius;
void main() {
// float delta = (sin(u_time)+1.0)/2.0;
vec3 v= normalize(position)* u_radius;
// vec3 pos= mix(v,position,delta);
// gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );
gl_Position = projectionMatrix * modelViewMatrix * vec4( v, 1.0 );
}
`
normalize 得到长度为1的向量;
顶点着色器:用于定位几何体的顶点,改变gl_Position的值,图形即可发生变化。 那么projectionMatrix和modelViewMatrix又是什么哪。这里讲起来有一点复杂,所以为了更好的让大家理解,我这里转用其他人写的文章。
const vshader = `
uniform float u_time;
uniform float u_radius;
void main() {
gl_PointSize=5.0;
float delta = (sin(u_time)+1.0)/2.0;
vec3 v= normalize(position)* u_radius;
vec3 pos= mix(v,position,delta);
gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );
}
`
const material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vshader,
fragmentShader: fshader,
// wireframe: true
});
const ball = new THREE.Points(geometry, material);
转换成点粒子。
gl_PointSize 控制点的大小,点模式生效。
接下来让点的数量少一点,给每个点贴图。
const vshader = `
uniform float u_time;
uniform float u_radius;
void main() {
gl_PointSize=50.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
const fshader = `
uniform sampler2D u_tex;
void main()
{
vec3 color = texture2D(u_tex,gl_PointCoord ).rgb;
gl_FragColor = vec4(color, 1.0);
}
` `
uniforms.u_tex={value:new THREE.TextureLoader().load("./target.png")}
const geometry = new THREE.BoxGeometry(30, 30, 30, 1, 1, 1);
gl_PointCoord 点渲染模式会把点渲染成一个正方形,在这个正方形中左上角为(0,0)右下角为(1,1) gl_PointCoord。所以得到的图像是上下反转的。
glsl的函数有点多,到时候不会的去查就行了,跟着以前的课程敲一遍,应该都能写shader了,之后就不再讲解函数内置变量的用法了。