【问题标题】:WebGL shader attribute is not being passed accuratelyWebGL 着色器属性未准确传递
【发布时间】:2018-10-27 09:40:58
【问题描述】:

我正在尝试通过使用 WebGL 实例化的线框 (https://threejs.org/examples/?q=wire#webgl_materials_wireframe) 的 threejs 示例。

这个简单的复制代码笔 (https://codepen.io/ubermario/pen/gzByjP?editors=1000) 显示,当使用 THREE.BufferAttribute 将“中心”属性传递给顶点/片段着色器时,会呈现线框立方体。

但是,当“中心”属性通过 THREE.InstancedBufferAttribute 传递给相同的着色器时,它不会呈现为线框。

不会产生错误。想法?

<html lang="en">
    <head>
        <title>Adopted from three.js webgl - materials - wireframe</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 {
                margin: 0px;
                background-color: #000000;
                overflow: hidden;
            }
        </style>
    </head>
    <body>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>  

        <script type="x-shader/x-vertex" id="vertexShader"> 
            attribute vec3 center;
            varying vec3 vCenter;

            void main() {
                vCenter = center;
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); 
            }
        </script>

        <script type="x-shader/x-fragment" id="fragmentShader">
            varying vec3 vCenter;

            float edgeFactorTri() {
                vec3 d = fwidth( vCenter.xyz ); 
                vec3 a3 = smoothstep( vec3( 0.0 ), d * 1.5, vCenter.xyz );  
                return min( min( a3.x, a3.y ), a3.z );
            }

            void main() {           
                gl_FragColor.rgb = mix( vec3( 1.0 ), vec3( 0.0 ), edgeFactorTri() );                
                gl_FragColor.a = 1.0;   
            }
        </script>

        <script>

            var camera, scene, renderer;

            init();

            renderer.render( scene, camera );

            function init() {

                var bufferGeometry, material, mesh;
                camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 2000 );
                camera.position.z = 700;
                scene = new THREE.Scene();

                var geometry1 =  new THREE.BoxBufferGeometry( 100, 100,100 );
                geometry1.addAttribute( 'center', new THREE.BufferAttribute( fnGetFloat32ArrayCenters( geometry1 ), 3 ) );

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

                    } );
                material_1.extensions.derivatives = true;   

                mesh1 = new THREE.Mesh( geometry1, material_1 );
                mesh1.position.x = -100;
                scene.add( mesh1 );


                var  bufferGeometry = new THREE.BoxBufferGeometry( 100, 100,100 );
                var geometry2 = new THREE.InstancedBufferGeometry();
                    geometry2.index = bufferGeometry.index;
                    geometry2.attributes.position = bufferGeometry.attributes.position;   
                    geometry2.attributes.uv = bufferGeometry.attributes.uv;         

                //Now with instancing
                geometry2.addAttribute( 'center', new THREE.InstancedBufferAttribute(  fnGetFloat32ArrayCenters( geometry2 ), 3 ) );    


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

                    } );
                material_2.extensions.derivatives = true;   

                mesh2 = new THREE.Mesh( geometry2, material_2 );
                mesh2.position.x = 100;
                scene.add( mesh2 );


                // renderer

                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                document.body.appendChild( renderer.domElement );

                // events

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

                function fnGetFloat32ArrayCenters( geometry ) {


                    var vectors = [
                        new THREE.Vector3( 1, 0, 0 ),
                        new THREE.Vector3( 0, 1, 0 ),
                        new THREE.Vector3( 0, 0, 1 )
                    ];

                    var position = geometry.attributes.position;
                    var centers = new Float32Array( position.count * 3 );


                    for ( var i = 0, l = position.count; i < l; i ++ ) {

                        vectors[ i % 3 ].toArray( centers, i * 3 );

                    }

                    return centers;


                } //fnGetFloat32ArrayCenters                


            } //init




            function onWindowResize() {

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

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

            }



        </script>

    </body>
</html>

【问题讨论】:

    标签: three.js webgl


    【解决方案1】:

    解决方案:问题似乎是 three.js r83 中的一个错误,在 BoxBufferGeometry 与 InstancedBufferGeometry 上创建了网格;请参阅更新的codepen,它在 cmets 中说明了这一点。

    material_1 的线框属性在其值为 false 时不应用。它似乎“卡在”“真实”上;强制它为“假”对第一个立方体没有影响。

    这导致了一种误解,即基于material_2的立方体一直是正确的却是错误的;因为它尊重“false”的默认线框属性值。当设置为“true”时,它将显示为线框立方体。

    <html lang="en">
        <head>
            <title>Adopted from three.js webgl - materials - wireframe</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 {
                    margin: 0px;
                    background-color: #000000;
                    overflow: hidden;
                }
            </style>
        </head>
        <body>
    
      <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>  
    
            <script type="x-shader/x-vertex" id="vertexShader"> 
                attribute vec3 center;
                varying vec3 vCenter;
    
                void main() {
                    vCenter = center;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); 
                }
            </script>
    
            <script type="x-shader/x-fragment" id="fragmentShader">
                varying vec3 vCenter;
    
                float edgeFactorTri() {
                    vec3 d = fwidth( vCenter.xyz ); 
                    vec3 a3 = smoothstep( vec3( 0.0 ), d * 1.5, vCenter.xyz );  
                    return min( min( a3.x, a3.y ), a3.z );
                }
    
                void main() {           
                    gl_FragColor.rgb = mix( vec3( 1.0 ), vec3( 0.0 ), edgeFactorTri() );                
                    gl_FragColor.a = 1.0;   
                }
            </script>
    
            <script>
    
                var camera, scene, renderer;
    
                init();
    
                renderer.render( scene, camera );
    
                function init() {
    
                    var bufferGeometry, material, mesh;
                    camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 2000 );
                    camera.position.z = 700;
                    scene = new THREE.Scene();
    
                    var geometry1 =  new THREE.BoxBufferGeometry( 100, 100,100 );
                    geometry1.addAttribute( 'center', new THREE.BufferAttribute( fnGetFloat32ArrayCenters( geometry1 ), 3 ) );
    
                    var material_1 = new THREE.ShaderMaterial( {
                            uniforms: {},                             
                            vertexShader: document.getElementById( 'vertexShader' ).textContent,
                            fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
                wireframe: false //bug:For r83/three.js, property is not applied when the THREE.Mesh constructor is invoked. https://threejs.org/docs/index.html#api/materials/ShaderMaterial.wireframe
    
                        } );
                    material_1.extensions.derivatives = true;   
    
                    mesh1 = new THREE.Mesh( geometry1, material_1 );  //bug: material_1's wireframe:false property is not applied for r83/three.js
                    mesh1.position.x = -100;
                    scene.add( mesh1 );
    
    
                    var  bufferGeometry = new THREE.BoxBufferGeometry( 100, 100,100 );
                    var geometry2 = new THREE.InstancedBufferGeometry();
                        geometry2.index = bufferGeometry.index;
                        geometry2.attributes.position = bufferGeometry.attributes.position;   
                        geometry2.attributes.uv = bufferGeometry.attributes.uv;         
    
                    //Now with instancing
                    geometry2.addAttribute( 'center', new THREE.InstancedBufferAttribute(  fnGetFloat32ArrayCenters( geometry2 ), 3 ) );    
    
    
                    var material_2 = new THREE.ShaderMaterial( {
                            uniforms: {},                             
                            vertexShader: document.getElementById( 'vertexShader' ).textContent,
                            fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
                wireframe:true  //See: documentation: https://threejs.org/docs/index.html#api/materials/ShaderMaterial.wireframe
    
                        } );
                    material_2.extensions.derivatives = true;   
    
                    mesh2 = new THREE.Mesh( geometry2, material_2 );
                    mesh2.position.x = 100;
                    scene.add( mesh2 );
    
    
                    // renderer
    
                    renderer = new THREE.WebGLRenderer( { antialias: true } );
                    renderer.setPixelRatio( window.devicePixelRatio );
                    renderer.setSize( window.innerWidth, window.innerHeight );
                    document.body.appendChild( renderer.domElement );
    
                    // events
    
                    window.addEventListener( 'resize', onWindowResize, false );
    
                    function fnGetFloat32ArrayCenters( geometry ) {
    
    
                        var vectors = [
                            new THREE.Vector3( 1, 0, 0 ),
                            new THREE.Vector3( 0, 1, 0 ),
                            new THREE.Vector3( 0, 0, 1 )
                        ];
    
                        var position = geometry.attributes.position;
                        var centers = new Float32Array( position.count * 3 );
    
    
                        for ( var i = 0, l = position.count; i < l; i ++ ) {
    
                            vectors[ i % 3 ].toArray( centers, i * 3 );
    
                        }
    
                        return centers;
    
    
                    } //fnGetFloat32ArrayCenters                
    
    
                } //init
    
    
    
    
                function onWindowResize() {
    
                    camera.aspect = window.innerWidth / window.innerHeight;
                    camera.updateProjectionMatrix();
    
                    renderer.setSize( window.innerWidth, window.innerHeight );
    
                }
    
    
    
            </script>
    
        </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      相关资源
      最近更新 更多