javascript - Threejs着色器实现

标签 javascript opengl-es three.js fragment-shader

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

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

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

我正在尝试将其添加到可在以下链接中找到的 3D 模型中:

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

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

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

noise shader

完整源代码(我也在 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>

关于javascript - Threejs着色器实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30028815/

相关文章:

javascript - 删除 Google Maps API Premier 使用条款/ Logo /等。链接?

javascript - 如何在 Socket.IO 中重新连接后监听升级事件

javascript - 关于 Ajax 便捷方法和错误处理的 jQuery 最佳实践是什么?

opengl-es - 渲染到深度纹理 - 关于 GL_OES_depth_texture 用法的不清楚

Android:在 GLSurfaceView 中创建纹理会从标准硬件加速 View 元素中删除纹理

three.js - 如何使用three.js编写正确的重复纹理

html - 将三个 js Canvas 移动到 div 标签内

javascript - 带有多个选项卡的 Node.js 和 Socket.io

OpenGL ES 纹理的图像大小

3d - 我正在尝试以编程方式为角色的头发设置动画。最好的方法是什么?