You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I use the outputStruct node to be able to store the result of several shaders with a renderTarget in textures. Everything works perfectly so far.
If you have several objects in the scene you have to render the relevant object that uses several shaders directly in the renderTarget if not all objects have several shaders.
renderer.setRenderTarget(renderTarget);
renderer.render( object, camera );
renderer.setRenderTarget( null );
The reason is because the renderTarget expects the same count of shaders from all objects in the scene as in the renderTarget count. As a rule, you only want to equip certain objects with multiple shaders.
So if you have an object in the scene that uses two shaders and one that only uses one, then there will be endless warnings in the console because the renderTarget also expects two shaders from the second object.
If you have a complex dynamic object hierarchy and use groups for it, unfortunately it doesn't work with direct rendering because groups aren't objects and it has to be the scene.
Solution: With a count > 1, the renderTarget must ignore objects with only one shader when processing count 2. Analogously with a count of 3 if an object only has 2 shaders
Reproduction steps
create an object with outputStruct material and use two very simple shaders.
create a second object with a simple material
use a renderTarget with count: 2 to store the output of both shaders of the first object.
Code
import * as THREE from "https://esm.sh/three";
import {MeshBasicNodeMaterial, wgslFn, vec4, texture, attribute, outputStruct } from "https://esm.sh/three/nodes";
import {OrbitControls} from "https://esm.sh/three/addons/controls/OrbitControls.js";
import Stats from "https://esm.sh/three/addons/libs/stats.module.js";
import WebGPURenderer from "https://esm.sh/three/addons/renderers/webgpu/WebGPURenderer.js";
import QuadMesh from "https://esm.sh/three/addons/objects/QuadMesh.js";
let scene = new THREE.Scene();
scene.background = new THREE.Color(0x00001f);
let renderer = new WebGPURenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
let camera = new THREE.PerspectiveCamera(50.0, window.innerWidth/window.innerHeight, 0.5, 10000);
camera.position.set(3, 3, 3);
let controls = new OrbitControls(camera, renderer.domElement);
let quad, renderTarget, material;
window.addEventListener("resize", onWindowResize, false);
init();
await render();
function init() {
renderTarget = new THREE.RenderTarget(512, 512, {count: 2});
const fragmentShader1 = wgslFn(`
fn main1(
) -> vec4<f32> {
return vec4<f32>(1, 0, 0, 1);
}
`);
const fragmentShader2 = wgslFn(`
fn main2(
) -> vec4<f32> {
return vec4<f32>(0, 1, 0, 1);
}
`);
const fragmentShader3 = wgslFn(`
fn main3(
) -> vec4<f32> {
return vec4<f32>(0, 0, 1, 1);
}
`);
material = new MeshBasicNodeMaterial();
material.outputNode = outputStruct(
fragmentShader1(),
fragmentShader2(),
fragmentShader3()
);
const geometry1 = new THREE.BoxGeometry(1, 1, 1);
const box1 = new THREE.Mesh(geometry1, material);
scene.add(box1);
//no errors without this box. The reason is that with count 2 in the renderTarget the renderTarget expects 2 outputs from all meshes in the scene.
const geometry2 = new THREE.BoxGeometry(1, 1, 1);
const material2 = new MeshBasicNodeMaterial();
material2.colorNode = vec4(0, 0, 1, 1);
const box2 = new THREE.Mesh(geometry2, material2);
box2.position.set(3, 0, -2);
scene.add(box2);
}
async function render() {
requestAnimationFrame(render);
await renderer.renderAsync(scene, camera);
renderer.setRenderTarget(renderTarget);
renderer.render( scene, camera );
renderer.setRenderTarget( null );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
When you configure in webgl2_multiple_rendertargets the render target with a count of 3, the following WebGL warning in the console appears:
GL_INVALID_OPERATION: Active draw buffers with missing fragment shader outputs.
The issue could be fixed by making sure the object's shader writes data to the new layout(location = 2). Or by not rendering the object at all.
I'm not sure if the engine should automatically handle this use case. It seems to me the the developer instead is responsible to configure its scene correctly. So if you have objects with different shader outputs in your scene, you could
a) create multiple scenes and render them separately with different render targets.
b) use Layers or Object3D.visible and configure the objects with a respective value that you want include/exclude from rendering.
The problem is that objects with non-matching outputs are some sort of invalid input for MRT in the first place. It must be defined how objects are treated if they write e.g. no normal or velocity values and that is an application specific thing.
I use different layers. But your comment is correct because that's exactly why I introduced the layers and I use 4 of them.
According to logic there should be no conflicts.
Yesterday I worked more intensively on the readRenderTargetPixels topic. To do this, I have to familiarize myself with webgl much more intensively. I actually only deal with WebGPU
Please take the issue out so I can examine it more intensively with the layers.
I'm juggling with a little too many topics at the moment and am becoming less attentive as a result. I'm usually very thorough with my analyses. I'll slow down a bit.
Description
I use the outputStruct node to be able to store the result of several shaders with a renderTarget in textures. Everything works perfectly so far.
If you have several objects in the scene you have to render the relevant object that uses several shaders directly in the renderTarget if not all objects have several shaders.
The reason is because the renderTarget expects the same count of shaders from all objects in the scene as in the renderTarget count. As a rule, you only want to equip certain objects with multiple shaders.
So if you have an object in the scene that uses two shaders and one that only uses one, then there will be endless warnings in the console because the renderTarget also expects two shaders from the second object.
If you have a complex dynamic object hierarchy and use groups for it, unfortunately it doesn't work with direct rendering because groups aren't objects and it has to be the scene.
Solution: With a count > 1, the renderTarget must ignore objects with only one shader when processing count 2. Analogously with a count of 3 if an object only has 2 shaders
Reproduction steps
Code
Live example
[* jsfiddle-latest-release
](https://codepen.io/Spiri0/pen/ExJdzpL)
Screenshots
No response
Version
r163
Device
No response
Browser
No response
OS
No response
The text was updated successfully, but these errors were encountered: