GLSL Three.js 顶点和片段着色器不工作

GLSL Three.js vertex and fragment shader is not working

我是 Three.js and GLSL 的新手,我正在尝试以 HTML 格式加载我的顶点和片段着色器。但是,它没有用,我遇到了错误

Uncaught TypeError: Cannot read properties of null (reading 'textContent')

发生这种情况有什么原因吗?我该如何解决?

我尝试将我的顶点和片段着色器与 HTML 文档内联。

文件index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>OBJ loader</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #FFF;
                color: #FFF;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                color: #FFF;
                position: absolute;
                top: 10px;
                width: 100%;
                text-align: center;
                z-index: 100;
                display: block;
            }
            #info a, .button {
                color: #F00;
                font-weight: bold;
                text-decoration:
                underline;
                cursor: pointer
            }
        </style>
    </head>

    <body>
        <script src="http://threejs.org/build/three.min.js"></script>
        <script src="http://threejs.org/examples/js/loaders/OBJLoader.js"></script>
        <script src="http://threejs.org/examples/js/libs/stats.min.js"></script>

        <script id="vertex_shader" type="x-shader/x-vertex">
            layout (location = 0) in vec2 pos;

            void main() {
                gl_Position = vec4(pos, 0.0f, 1);
            }

        </script>

        <script id="fragment_shader" type="x-shader/x-fragment">

            uniform vec2 uResolution;
            uniform float uTime;

            out vec4 outColor;

            precision highp float;

            uniform sampler2D tex;

            void main()
            {
                vec2 uv = gl_FragCoord.xy/uResolution;
                float time = uTime * 0.4;

                // Apply pixelate effect
                //vec2 uv_pixel = uv;
                vec2 uv_pixel = floor(uv * (uResolution/4)) / (uResolution/4);

                vec4 col1 = vec4(0.510, 0.776, 0.486, 1.0);
                vec4 col2 = vec4(0.200, 0.604, 0.318, 1.0);
                vec4 col3 = vec4(0.145, 0.490, 0.278, 1.0);
                vec4 col4 = vec4(0.059, 0.255, 0.251, 1.0);

                // Displacement on top of y
                vec3 displace = texture(tex, vec2(uv_pixel.x, (uv_pixel.y + time) * 0.05)).xyz;
                displace *= 0.5;
                displace.x -= 1.0;
                displace.y -= 1.0;
                displace.y *= 0.5;

                // Color
                vec2 uv_tmp = uv_pixel;
                uv_tmp.y *= 0.2;
                uv_tmp.y += time;
                vec4 color = texture(tex, uv_tmp + displace.xy);

                // Match to colors
                vec4 noise = floor(color * 10.0) / 5.0;
                vec4 dark   = mix(col1, col2, uv.y);
                vec4 bright = mix(col3, col4, uv.y);
                color = mix(dark, bright, noise);

                // Add gradients (top dark and transparent, bottom bright)
                float inv_uv = 1.0 - uv_pixel.y;
                color.xyz -= 0.45 * pow(uv_pixel.y, 8.0);
                color.a -= 0.2 * pow(uv_pixel.y, 8.0);
                color += pow(inv_uv, 8.0);

                // Make the waterfall transparent
                color.a -= 0.2;

                outColor = vec4(color);
            }
        </script>

        <script>
            var clock = new THREE.Clock();
            var delta = clock.getDelta(); // Seconds.
            var rotateAngle = Math.PI / 2 * delta; // pi/2 radians (90 degrees) per second
            var container, stats;

            var camera, scene, renderer, texture;

            var mouseX = 0, mouseY = 0;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;

            const customMaterial = new THREE.ShaderMaterial({
                uniforms: {
                    time: { value: 1.0 },
                    map: { value: texture },
                    resolution: { value: new THREE.Vector2() }
                },
                vertexShader:  document.getElementById('vertexshader').textContent,
                fragmentShader:  document.getElementById('fragmentshader').textContent,
            });

            init();
            animate();
            //var texture = new THREE.Texture();
            new THREE.OBJLoader().load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/39255/ladybug.gltf', function (object) {

                object.traverse(function (child) {

                    if (child instanceof THREE.Mesh) {

                        child.material = customMaterial;
                    }
                });

                scene.add(object);
            });

            function init() {

                container = document.createElement('div');
                document.body.appendChild(container);

                camera = new THREE.PerspectiveCamera(15, window.innerWidth / window.innerHeight, 1, 2000);
                camera.position.z = 100;

                // Scene

                scene = new THREE.Scene();

                var ambient = new THREE.AmbientLight(0x111130);
                scene.add(ambient);

                var directionalLight = new THREE.DirectionalLight(0xFFEEFF);
                directionalLight.position.set(1, 1, 0.5);
                scene.add(directionalLight);

                renderer = new THREE.WebGLRenderer();
                renderer.setSize(window.innerWidth, window.innerHeight);
                container.appendChild(renderer.domElement);

                document.addEventListener('mousemove', onDocumentMouseMove, false);

                window.addEventListener('resize', onWindowResize, false);
            }

            function onWindowResize() {
                windowHalfX = window.innerWidth / 2;
                windowHalfY = window.innerHeight / 2;

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize(window.innerWidth, window.innerHeight);
            }

            function onDocumentMouseMove(event) {
                mouseX = (event.clientX - windowHalfX) / 2;
                mouseY = (event.clientY - windowHalfY) / 2;
            }

            function animate() {
                requestAnimationFrame(animate);
                render();
            }

            function render() {
                camera.position.x += (mouseX - camera.position.x) * .05;
                camera.position.y += (- mouseY - camera.position.y) * .05;

                camera.lookAt(scene.position);

                renderer.render(scene, camera);
            }
        </script>
    </body>
</html>

您的代码中有拼写错误。您的着色器脚本标签的 ID 是 vertex_shaderfragment_shader,但您在 JavaScript 代码中使用了 vertexshaderfragmentshader。您缺少下划线。