Reputation: 419
i have a question about render layers. I now have a large app. That's why I'm trying to explain my main problem here only with the part of the code where I have difficulties. The special thing here is that I use a different camera for the depth texture for the post-processing with exactly the same positions and other values as the texture camera. I only use a floating value in the near range because of the accuracy. it all works great.
my problem is that my postprocessing affects everything in the scene and of course it looks bad. my postprocessing should only affect certain objects in the scene. my problem is that all objects are part of the scene. almost every object can spawn or disappear (triggered in other modules to keep code clean). it all works great. I just don't know how to limit (encapsulate) the postprocessing effect to objects of my choice. as a very simple example, how would you add a box or all other objects here so that they would not be affected by the postprocessing.
import {THREE, OrbitControls, RenderPass, ShaderPass, EffectComposer, CopyShader, FXAAShader} from './three-defs.js';
import {entity} from "./entity.js";
const vertexShad = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShad = `
varying vec2 vUv;
uniform sampler2D tDiffuse;
void main() {
vec3 color = texture2D(tDiffuse, vUv).rgb;
gl_FragColor = vec4(color, 1.);
}
`;
export const threejs_component = (() => {
class ThreeJSController extends entity.Component {
constructor() {
super();
}
InitEntity() {
this.threejs_ = new THREE.WebGLRenderer({antialias: true, logarithmicDepthBuffer: true});
this.threejs_.outputEncoding = THREE.sRGBEncoding;
this.threejs_.setPixelRatio(window.devicePixelRatio);
this.threejs_.shadowMap.enabled = true;
this.threejs_.shadowMap.type = THREE.PCFSoftShadowMap;
this.threejs_.domElement.id = 'threejs';
this.container = document.getElementById('container');
this.threejs_.setSize(this.container.clientWidth, this.container.clientHeight);
this.container.appendChild( this.threejs_.domElement );
const aspect = this.container.clientWidth / this.container.clientHeight;
const fov = 60;
const near = 1e-6;
const far = 1E27;
this.camera_ = new THREE.PerspectiveCamera(fov, aspect, near, far);
this.scene_ = new THREE.Scene();
this.scene_.background = new THREE.Color( 0x111111 );
this.depthCameraNear_ = 100000;
this.depthCamera_ = new THREE.PerspectiveCamera(fov, aspect, this.depthCameraNear_, far);
this.postCamera_ = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
this.postScene_ = new THREE.Scene();
/*
this.composer_ = new EffectComposer(this.threejs_);
const renderPass = new RenderPass(this.scene_, this.camera_);
const fxaaPass = new ShaderPass(FXAAShader);
this.composer_.addPass(renderPass);
this.composer_.addPass(fxaaPass);
*/
this.resolution_ = new THREE.Vector2();
this.threejs_.getDrawingBufferSize(this.resolution_);
this.target1_ = new THREE.WebGLRenderTarget(this.resolution_.x, this.resolution_.y);
this.target1_.texture.format = THREE.RGBFormat;
this.target1_.texture.minFilter = THREE.NearestFilter;
this.target1_.texture.magFilter = THREE.NearestFilter;
this.target1_.texture.generateMipmaps = false;
this.target1_.stencilBuffer = false;
this.target2_ = new THREE.WebGLRenderTarget(this.resolution_.x, this.resolution_.y);
this.target2_.stencilBuffer = false;
this.target2_.depthBuffer = true;
this.target2_.depthTexture = new THREE.DepthTexture();
this.target2_.depthTexture.format = THREE.DepthFormat;
this.target2_.depthTexture.type = THREE.FloatType;
this.depthPass_ = new THREE.ShaderMaterial({
vertexShader: vertexShad,
fragmentShader: fragmentShad,
uniforms: {
tDiffuse: { value: null },
tDepth: { value: null },
},
});
var postPlane = new THREE.PlaneBufferGeometry( 2, 2 );
this.postScreen_ = new THREE.Mesh( postPlane, this.depthPass_ );
this.postScene_.add( this.postScreen_ );
}
Render() {
this.threejs_.setRenderTarget(this.target1_);
this.threejs_.clear();
this.threejs_.render(this.scene_, this.camera_);
this.threejs_.setRenderTarget( null );
this.threejs_.setRenderTarget(this.target2_);
this.threejs_.clear();
this.threejs_.render(this.scene_, this.depthCamera_);
this.threejs_.setRenderTarget( null );
this.depthPass_.uniforms.tDiffuse.value = this.target1_.texture;
this.depthPass_.uniforms.tDepth.value = this.target2_.depthTexture;
this.depthPass_.uniformsNeedUpdate = true;
this.threejs_.render(this.postScene_, this.postCamera_);
}
Update(timeElapsed) {
const player = this.FindEntity('player');
if (!player) {
return;
}
const pos = player._position;
}
}//end class
return {
ThreeJSController: ThreeJSController,
};
})();
maybe my postprocessing plane is a bad idea and the composer with layers is the solution? or i need both?
Upvotes: 0
Views: 199
Reputation: 419
Programming can be frustrating at times. after half a day i have the solution. I use the composer because it makes the code shorter and cleaner.
export const threejs_component = (() => {
class ThreeJSController extends entity.Component {
constructor() {
super();
}
InitEntity() {
this.threejs_ = new THREE.WebGLRenderer({antialias: true, logarithmicDepthBuffer: true});
this.threejs_.outputEncoding = THREE.sRGBEncoding;
this.threejs_.setPixelRatio(window.devicePixelRatio);
this.threejs_.shadowMap.enabled = true;
this.threejs_.shadowMap.type = THREE.PCFSoftShadowMap;
this.threejs_.domElement.id = 'threejs';
this.container = document.getElementById('container');
this.threejs_.setSize(this.container.clientWidth, this.container.clientHeight);
this.container.appendChild( this.threejs_.domElement );
const aspect = this.container.clientWidth / this.container.clientHeight;
const fov = 60;
const near = 1e-6;
const far = 1E27;
this.camera_ = new THREE.PerspectiveCamera(fov, aspect, near, far);
this.scene_ = new THREE.Scene();
//this.scene_.background = new THREE.Color( 0x111111 );
this.threejs_.setClearColor( 0x000000 );
this.depthCameraNear_ = 100000;
this.depthCamera_ = new THREE.PerspectiveCamera(fov, aspect, this.depthCameraNear_, far);
this.composer_ = new EffectComposer(this.threejs_);
const renderPass = new RenderPass(this.scene_, this.camera_);
const fxaaPass = new ShaderPass(FXAAShader);
this.composer_.addPass(renderPass);
this.composer_.addPass(fxaaPass);
this.resolution_ = new THREE.Vector2();
this.threejs_.getDrawingBufferSize(this.resolution_);
this.target_ = new THREE.WebGLRenderTarget(this.resolution_.x, this.resolution_.y);
this.target_.stencilBuffer = false;
this.target_.depthBuffer = true;
this.target_.depthTexture = new THREE.DepthTexture();
this.target_.depthTexture.format = THREE.DepthFormat;
this.target_.depthTexture.type = THREE.FloatType;
}
Render() {
this.threejs_.autoClear = true;
this.threejs_.setRenderTarget(this.target_);
this.threejs_.render(this.scene_, this.depthCamera_);
this.threejs_.setRenderTarget( null );
this.threejs_.clear();
this.camera_.layers.set(0);
this.threejs_.render(this.scene_, this.camera_);
this.composer_.render();
this.threejs_.autoClear = false;
this.threejs_.clearDepth();
this.camera_.layers.set(1);
this.threejs_.render(this.scene_, this.camera_);
}
Update(timeElapsed) {
const player = this.FindEntity('player');
if (!player) {
return;
}
const pos = player._position;
}
}//end class
return {
ThreeJSController: ThreeJSController,
};
})();
submodules access the composer to set postprocessing shaders, like this
composer_.addPass(new ShaderPass(customShader));
for groups i use this to set the models and groups to the preferred layer
model.traverse( function( child ) { child.layers.set(1); });
I almost never drink beer, but now I could use one to celebrate the day 🥳
Upvotes: 0