2

現在のプロジェクトでは、1 つのレンダー パスで複数のシェーダーを使用したいと考えています。これは、画面への最後のパスのみをレンダリングし、それ以前のすべてのパスを 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 に答える