代码之家  ›  专栏  ›  技术社区  ›  d4rty

将WebGLrenderer与shaderMaterial一起使用,并将对数深度缓冲集选项设置为true

  •  1
  • d4rty  · 技术社区  · 6 年前

    我用下面的 ShaderMaterial 为我在现场的物品。下面的代码正在工作。但是,如果我设置webglrenderer选项 logarithmicDepthBuffer true ,下面定义的材料没有正确显示。

    new THREE.ShaderMaterial({
        uniforms: {
          color1: {
            value: new THREE.Color('#3a0000')
          },
          color2: {
            value: new THREE.Color('#ffa9b0')
          }
        },
        vertexShader: `
        varying vec3 vNormal;
        void main(void){
          vNormal      = normalMatrix * normalize(normal);
          gl_Position  = projectionMatrix * modelViewMatrix * vec4(position,1.0);
        }`,
    
        fragmentShader: `
        uniform vec3 color1;
        uniform vec3 color2;
        varying vec3 vNormal;
        void main(void){
          vec3 view_nv  = normalize(vNormal);
          vec3 nv_color = view_nv * 0.5 + 0.5;
          vec3 c = mix(color1, color2, nv_color.r);
          gl_FragColor  = vec4(c, 1.0);
        }`,
        side: THREE.DoubleSide,
      });
    

    在寻找这个问题的解决方案后,我发现 SO answer . 总的来说,解决方案是将4段代码添加到 vertexShader fragmentShader .

    我究竟需要在哪里集成所提供的代码片段,即顶点着色体和片段着色体?

    我尝试过各种各样的“职位”,但我总是有WebGL错误。

    THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:63: 'EPSILON' : undeclared identifier 
    

    更新 增加操场: https://codepen.io/anon/pen/gQoaye

    如果您添加 对数深度缓冲区 对于构造函数,您将看到 着色材料 不会再起作用了。

    var renderer = new THREE.WebGLRenderer(logarithmicDepthBuffer:true);
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Rabbid76    6 年前

    我究竟需要在哪里集成所提供的代码片段,即顶点着色体和片段着色体?

    在顶点着色中,必须定义 EPSILON .
    添加代码截图后 logdepthbuf_pars_vertex.glsl logdepthbuf_vertex.glsl ,最后一个顶点明暗器是:

    #ifdef USE_LOGDEPTHBUF
    #define EPSILON 1e-6
    #ifdef USE_LOGDEPTHBUF_EXT
    varying float vFragDepth;
    #endif
    uniform float logDepthBufFC;
    #endif
    
    varying vec3 vNormal;
    
    void main(void){
        vNormal      = normalMatrix * normalize(normal);
        gl_Position  = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    
    #ifdef USE_LOGDEPTHBUF
        gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
    #ifdef USE_LOGDEPTHBUF_EXT
        vFragDepth = 1.0 + gl_Position.w;
    #else
        gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
    #endif
    #endif
    }
    

    添加代码段后,最终的片段明暗器是:

    #ifdef USE_LOGDEPTHBUF
    uniform float logDepthBufFC;
    #ifdef USE_LOGDEPTHBUF_EXT
    #extension GL_EXT_frag_depth : enable
    varying float vFragDepth;
    #endif
    #endif
    
    uniform vec3 color1;
    uniform vec3 color2;
    varying vec3 vNormal;
    void main(void){
        vec3 view_nv  = normalize(vNormal);
        vec3 nv_color = view_nv * 0.5 + 0.5;
        vec3 c = mix(color1, color2, nv_color.r);
        gl_FragColor  = vec4(c, 1.0);
    
    #if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
        gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
    #endif
    } 
    

    参见示例:

    (function onLoad() {
      var container, camera, scene, renderer, orbitControls;
      
      function createModel() {
    
        var material = new THREE.ShaderMaterial({
        uniforms: {
          color1: {
            value: new THREE.Color('#3a0000')
          },
          color2: {
            value: new THREE.Color('#ffa9b0')
          }
        },
        vertexShader: `
        #ifdef USE_LOGDEPTHBUF
        #define EPSILON 1e-6
        #ifdef USE_LOGDEPTHBUF_EXT
        varying float vFragDepth;
        #endif
        uniform float logDepthBufFC;
        #endif
    
        varying vec3 vNormal;
        
        void main(void){
            vNormal      = normalMatrix * normalize(normal);
            gl_Position  = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    
        #ifdef USE_LOGDEPTHBUF
            gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
        #ifdef USE_LOGDEPTHBUF_EXT
            vFragDepth = 1.0 + gl_Position.w;
        #else
            gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
        #endif
        #endif
        }`,
    
        fragmentShader: `
        #ifdef USE_LOGDEPTHBUF
        #ifdef USE_LOGDEPTHBUF_EXT
        #extension GL_EXT_frag_depth : enable
        varying float vFragDepth;
        #endif
        uniform float logDepthBufFC;
        #endif
    
        uniform vec3 color1;
        uniform vec3 color2;
        varying vec3 vNormal;
        void main(void){
            vec3 view_nv  = normalize(vNormal);
            vec3 nv_color = view_nv * 0.5 + 0.5;
            vec3 c = mix(color1, color2, nv_color.r);
            gl_FragColor  = vec4(c, 1.0);
            
        #if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
            gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
        #endif
        }`,
        side: THREE.DoubleSide,
      });
    
        //var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        var mesh = new THREE.Mesh(geometry, material);
    
        scene.add(mesh);
      }
    
      function init() {
        container = document.getElementById('container');
        
        renderer = new THREE.WebGLRenderer({
          antialias: true,
          logarithmicDepthBuffer: true
        });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMap.enabled = true;
        container.appendChild(renderer.domElement);
    
        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
        camera.position.set(0, 1, -2);
    
        scene = new THREE.Scene();
        scene.background = new THREE.Color(0xffffff);
        scene.add(camera);
        window.onresize = resize;
    
        orbitControls = new THREE.OrbitControls(camera);
        
        var helper = new THREE.GridHelper(100, 100);
        helper.material.opacity = 0.25;
        helper.material.transparent = true;
        scene.add(helper);
    
        var axis = new THREE.AxesHelper(1000);
        scene.add(axis);
    
        createModel();
      }
    
      function resize() {  
        var aspect = window.innerWidth / window.innerHeight;
        renderer.setSize(window.innerWidth, window.innerHeight);
        camera.aspect = aspect;
        camera.updateProjectionMatrix();
      }
    
      function animate() {
        requestAnimationFrame(animate);
        orbitControls.update();
        render();
      }
    
      function render() {
        renderer.render(scene, camera);
      }
      
      init();
      animate();
    })();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
    <div id="container"></div>
        2
  •  0
  •   Berthur Sercan    6 年前

    我假设您已经尝试在两个着色器中插入该代码了?据我所知,这应该是正确的。

    由于引用了 EPSILON 在顶点着色体中,尽管 ε 从未被宣布。

    尝试定义 ε 例如,在材质球本身中使用宏:

    #define EPSILON 1e-6
    

    或者将其作为统一体传递给明暗器。(请注意,这只是一个示例值;您可能需要研究什么是合适的值 ε 可能在您的特定情况下。)