threejs shader 入门(五)

143 阅读1分钟

没看过的朋友建议从一开始看。

基础代码

<!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>

1.png

接下来我们让正方形变成圆。

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 );
    }
    `

2.png

normalize 得到长度为1的向量;

顶点着色器:用于定位几何体的顶点,改变gl_Position的值,图形即可发生变化。 那么projectionMatrix和modelViewMatrix又是什么哪。这里讲起来有一点复杂,所以为了更好的让大家理解,我这里转用其他人写的文章。

3.png

直接到文章的五、粒子系统 有详细解释。

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);   
 

转换成点粒子。

2.gif

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);

5.png

gl_PointCoord 点渲染模式会把点渲染成一个正方形,在这个正方形中左上角为(0,0)右下角为(1,1) gl_PointCoord。所以得到的图像是上下反转的。

glsl的函数有点多,到时候不会的去查就行了,跟着以前的课程敲一遍,应该都能写shader了,之后就不再讲解函数内置变量的用法了。