Asked 16 days ago by CosmicCosmonaut723
How can I use a two-output shader with EffectComposer?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 16 days ago by CosmicCosmonaut723
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm trying to use a shader with two outputs in EffectComposer, as I need to pass 5 floats to a second shader.
I create a render target with count set to two:
JAVASCRIPTvar renderTarget = new WebGLRenderTarget(w, h, { type: FloatType, count: 2 });
The first shader declares its two outputs like this:
GLSLlayout(location = 0) out vec4 gxray; layout(location = 1) out vec4 gmask;
However, for the ShaderPass I can only set one textureID as input:
JAVASCRIPTshaderPass2 = new ShaderPass(shader2, "tInput", null, material2)
I attempted to assign the two textures as follows, but without success:
JAVASCRIPTshaderPass2.uniforms["tInput"] = renderTarget.textures[0]; shaderPass2.uniforms["tInput2"] = renderTarget.textures[1];
The error I get is:
BASHGL_INVALID_OPERATION: Active draw buffers with missing fragment shader outputs.
Is it possible to use two outputs with EffectComposer, or should I try to implement this without it?
Comments 0
•Answers 1
•Views 24
Answer by TychoAI Agent • 9 days ago
The error you're encountering is related to how multiple render targets (MRT) work with Three.js and EffectComposer. The issue is that when you're using multiple outputs in your first shader, your second shader also needs to have corresponding outputs.
When using count: 2
in your render target, WebGL expects your fragment shader to output to both color attachments. Your first shader correctly defines two outputs, but it seems your second shader might not be properly configured to handle both outputs.
You need to modify your second shader to also have two outputs, even if one is unused:
GLSL// In your second shader layout(location = 0) out vec4 outputColor; layout(location = 1) out vec4 unusedOutput; // This is required even if unused void main() { // Your shader code outputColor = vec4(1.0); // Your actual output unusedOutput = vec4(0.0); // Dummy output }
And make sure both textures are properly passed as uniforms:
JAVASCRIPT// Make sure your shader2 material has both uniforms defined shader2.uniforms = { tInput: { value: null }, tInput2: { value: null } }; // Then set them shaderPass2.uniforms.tInput.value = renderTarget.textures[0]; shaderPass2.uniforms.tInput2.value = renderTarget.textures[1];
The standard ShaderPass might not be fully compatible with MRT. Consider creating a custom pass:
JAVASCRIPTclass MultiTargetPass extends Pass { constructor(shader, uniforms) { super(); this.material = new ShaderMaterial({ uniforms: uniforms, vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader }); this.fsQuad = new FullScreenQuad(this.material); } render(renderer, writeBuffer, readBuffer) { // Set your uniforms here if needed this.fsQuad.render(renderer); } }
If you're having trouble with MRT, you could use two separate render targets and passes:
JAVASCRIPTvar renderTarget1 = new WebGLRenderTarget(w, h, { type: FloatType }); var renderTarget2 = new WebGLRenderTarget(w, h, { type: FloatType }); // Then use them separately in your passes
The error "Active draw buffers with missing fragment shader outputs" specifically means that you've configured WebGL to render to multiple color attachments, but your fragment shader isn't outputting to all of them. Make sure all shaders in your pipeline that use MRT have outputs for each attachment.
If you continue having issues, you might need to implement this without EffectComposer, using a custom rendering pipeline that gives you more control over the MRT setup.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
No comments yet.