2

在我当前的项目中,我想在一个渲染过程中使用多个着色器。我认为这可以通过仅将最后一次传递到屏幕并将所有先前传递到 renderTarget 然后将此 renderTarget 作为纹理传递给下一个着色器来实现。

在我的情况下,问题似乎出在以下代码中的渲染循环中:

// something is going wrong here:    
viewer.renderer.render(viewer.scene, viewer.camera, viewer.renderTarget);

viewer.uniforms.tDiffuse.value = viewer.renderTarget;
viewer.uniforms.fragmentShader = viewer.fragment2;

viewer.renderer.render(viewer.scene, viewer.camera);

为了让事情更清楚,我建立了这个片段

var viewer = {
    width: 512,
    height: 512
};

initViewer = function() {
    viewer.vertex     = $('#vertexShader').text();
    viewer.fragment1  = $('#fragmentShader1').text();
    viewer.fragment2  = $('#fragmentShader2').text();    

    
    viewer.camera = new THREE.OrthographicCamera(viewer.width / -2, viewer.width / 2, viewer.height / 2, viewer.height / -2, -1000, 1000);

    viewer.camera.position.z = 100;

    viewer.renderer = new THREE.WebGLRenderer();
    viewer.scene = new THREE.Scene();

    viewer.uniforms = {
        alpha: {
            type: 'f',
            value: '1.0'
        }, tDiffuse: {
            type: 't',
            value: ''
        }
    };
    
    viewer.initialMaterial = new THREE.ShaderMaterial({
        uniforms: viewer.uniforms,
        vertexShader: viewer.vertex,
        fragmentShader: viewer.fragment1
    });
    
    viewer.plane = new THREE.Mesh(new THREE.PlaneGeometry(viewer.width, viewer.height), viewer.initialMaterial);

    viewer.scene.add(viewer.plane);
    
    $('body').append(viewer.renderer.domElement);
    
    viewer.renderTarget = new THREE.WebGLRenderTarget( 512, 512 );
    
    render();
};

render = function() {
    
    // commenting out the next line makes everything work
    viewer.renderer.render(viewer.scene, viewer.camera, viewer.renderTarget);
    
    viewer.uniforms.tDiffuse.value = viewer.renderTarget;
    viewer.uniforms.fragmentShader = viewer.fragment2;

    
    viewer.renderer.render(viewer.scene, viewer.camera);

    requestAnimationFrame(render);
};

initViewer();
canvas 
{
    border: 1px solid lime;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">

precision mediump float;

varying vec2 v_texCoord;
varying vec4 vertexPosition;

void main()
{
    v_texCoord = uv;
    vec3 p = position;
    vec4 mvPosition = modelViewMatrix * vec4(p, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
    vertexPosition = gl_Position;
}
</script>

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

precision mediump float;

void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 0.2);
}
</script>

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

precision mediump float;
uniform sampler2D tDiffuse;
varying vec2 v_texCoord;

void main()
{
    gl_FragColor = texture2D( tDiffuse, v_texCoord) * vec4(0.0, 1.0, 1.0, 0.2);
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>

关于我做错了什么的任何想法?

4

2 回答 2

1

通过从块中构建我需要的着色器来解决它(像这样:https ://github.com/mrdoob/three.js/blob/r50/src/renderers/WebGLShaders.js )

于 2012-11-23T17:44:20.820 回答
0

最简单的方法:将所有通道渲染到单独的纹理,然后将它们应用到将它们与着色器混合的全屏四边形。或者在单独的全屏四边形上并设置混合添加。您也可以仅使用具有不同着色方法的相同对象的混合和乘法渲染(阅读此内容),如果您只需要简单的合成,它将为您节省 GPU 内存和纹理填充率。

于 2012-11-22T15:24:52.177 回答