Threejs着色器实现

Threejs shader implementation

过去几周我一直在试验 three.js 库和着色器,但我一直坚持在我的模型上实现着色器。我在 pixelshaders.com 上发现了这个有趣的例子,我想在 threejs 模型上实现它。

http://pixelshaders.com/examples/noise.html

这是页面底部的最后一个示例,我正在尝试实现。

我正在尝试将它添加到 3D 模型中,可以在下面的 link 中找到:

http://martinr.nl/lab/Speeltuin/webgl_shader2.html

困难的是当我添加示例代码时 3D 模型消失了。这使得调试和查找错误变得非常困难。

这是有效的着色器代码,但不适用于正确的着色器:

<script id="fragmentShader" type="x-shader/x-fragment">
    varying vec2 vUv;

    uniform float time;
    uniform vec2 resolution;
    precision mediump float;

    void main( void ) {

        vec2 position = 2.0 + 2.0 * vUv;

        float red = abs( sin( position.x / position.y + time / 5.0 ) );
        float green = abs( sin( position.x / position.y + time / 4.0 ) );
        float blue = abs( sin( position.x / position.y + time / 3.0 ) );
        gl_FragColor = vec4( red, green, blue, 1.0 );
    }

</script>

<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;

    void main()
    {
        vUv = uv;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0);
        gl_Position = projectionMatrix * mvPosition;
    }

</script>

当我尝试实现上述示例的着色器时,3D 模型消失了。

有谁知道如何将 pixelshader.com 示例的着色器应用到我示例中的模型上?

或者有没有人有任何提示我可以尝试使其工作?

我用 pixelshaders.com 中的代码替换了您的片段着色器。控制台报告以下错误:

> THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false
> gl.getPRogramInfoLog Varyings with the same name but different type,
> or statically used varyings in fragment shader are not declared in
> vertex shader: position

可变变量本质上是顶点着色器和片段着色器之间的接口。这个错误告诉我们 position 是在片段着色器中声明的,但不是在顶点着色器中声明的。

您实际上在顶点着色器中有所需的变量...除了它被命名为 vUv。我所要做的就是使变量名称保持一致。

完整源代码(我也在 render() 函数中取消了 time 的缩放):

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - materials - shaders [custom]</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 {
                color: #ffffff;
                font-family:Monospace;
                font-size:13px;
                text-align:center;
                font-weight: bold;

                background-color: #050505;
                margin: 0px;
                overflow: hidden;
            }
            a {
                color: #ffffff;
            }
            #oldie a { color:#da0 }
        </style>
    </head>
    <body>

        <div id="container"></div>
        <div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - shader material demo. featuring <a href="http://www.pouet.net/prod.php?which=52761" target="_blank">Monjori by Mic</a></div>


    <link rel="stylesheet" href="css/skeleton.css">
    <link rel="stylesheet" href="css/normalize.css">
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="css/codemirror.css">
    <script src="js/lib/three.min.js"></script>
    <script src="js/lib/Detector.js"></script>
    <script src="js/geo.js"></script>

        <script id="fragmentShader" type="x-shader/x-fragment">
            precision mediump float;

            varying vec2 vUv;
            uniform float time;

            float random(float p) {
              return fract(sin(p)*10000.);
            }

            float noise(vec2 p) {
              return random(p.x + p.y*10000.);
            }

            vec2 sw(vec2 p) {return vec2( floor(p.x) , floor(p.y) );}
            vec2 se(vec2 p) {return vec2( ceil(p.x)  , floor(p.y) );}
            vec2 nw(vec2 p) {return vec2( floor(p.x) , ceil(p.y)  );}
            vec2 ne(vec2 p) {return vec2( ceil(p.x)  , ceil(p.y)  );}

            float smoothNoise(vec2 p) {
              vec2 inter = smoothstep(0., 1., fract(p));
              float s = mix(noise(sw(p)), noise(se(p)), inter.x);
              float n = mix(noise(nw(p)), noise(ne(p)), inter.x);
              return mix(s, n, inter.y);
              return noise(nw(p));
            }

            float movingNoise(vec2 p) {
              float total = 0.0;
              total += smoothNoise(p     - time);
              total += smoothNoise(p*2.  + time) / 2.;
              total += smoothNoise(p*4.  - time) / 4.;
              total += smoothNoise(p*8.  + time) / 8.;
              total += smoothNoise(p*16. - time) / 16.;
              total /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
              return total;
            }

            float nestedNoise(vec2 p) {
              float x = movingNoise(p);
              float y = movingNoise(p + 100.);
              return movingNoise(p + vec2(x, y));
            }

            void main() {
              vec2 p = vUv * 6.;
              float brightness = nestedNoise(p);
              gl_FragColor.rgb = vec3(brightness);
              gl_FragColor.a = 1.;
            }

        </script>



        <script id="vertexShader" type="x-shader/x-vertex">
        varying vec2 vUv;

            void main()
            {
                vUv = uv;
                vec4 mvPosition = modelViewMatrix * vec4( position, 1.0);
                gl_Position = projectionMatrix * mvPosition;
            }

        </script>

        <script>

            if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

            var container;
            var camera, controls, scene, renderer;
            var uniforms;
            var clock = new THREE.Clock();

            init();
            animate();

            function init() {

                container = document.getElementById( 'container' );

                camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 3000 );
                camera.position.z = 2;

                scene = new THREE.Scene();

                var geometry = new THREE.BoxGeometry( 0.5, 0.5, 0.5 );

                uniforms = {
                    time: { type: "f", value: 1.0 },
                    resolution: { type: "v2", value: new THREE.Vector3() }
                };              

                var material = new THREE.ShaderMaterial({
                    uniforms: uniforms,
                    vertexShader: document.getElementById( 'vertexShader' ).textContent,
                    fragmentShader: document.getElementById( 'fragmentShader').textContent
                });

                var mesh = new THREE.Mesh( geometry, material );
                scene.add( mesh );


                renderer = new THREE.WebGLRenderer();
                renderer.setPixelRatio( window.devicePixelRatio );
                container.appendChild( renderer.domElement );


                onWindowResize();

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

            }

            function onWindowResize( event ) {

                uniforms.resolution.value.x = window.innerWidth;
                uniforms.resolution.value.y = window.innerHeight;

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

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

            }

            //

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

            function render() {

                var delta = clock.getDelta();

                uniforms.time.value += delta;

//              for ( var i = 0; i < scene.children.length; i ++ ) {
//
//                  var object = scene.children[ i ];
//
//                  object.rotation.y += delta * 0.5 * ( i % 2 ? 1 : -1 );
//                  object.rotation.x += delta * 0.5 * ( i % 2 ? -1 : 1 );
//
//              }

                renderer.render( scene, camera );

            }

        </script>

    </body>
</html>