
- OIT需要对模型进行分类
- 透明mesh transparentObjects
- 非透明mesh opaqueObjects
- 多层材质的透明与非透明
- 有一层为不透明,则为非透明mesh
- 全是透明,则为透明mesh
- 透明mesh与非透明mesh区别不大
- 非透明物体很多属性都不会去动,而透明物体很多属性都会去动
- 非透明物体和透明物体transparent在oit中都是为false (即不blend)
- 所有物体的premultipliedAlpha都应该为false
- 透明mesh设置了opacity属性(rgba的a)
- 多层材质的时候,最后一层不blend,其他层的透明blend
- 在compositeScene,剥离后的贴图,a通道会预乘颜色,blend功能也被打开
- 渲染管线
- 没有透明: three画家排序
- 有透明: oit管线
- 把不透明的进行隐藏 然后SSAO后处理
- 进行oit处理 这个时候透明和非透明的都在这里drawcall
- drawcall完毕 最后drawcall背景
- renderTarget 设为null 背景和地板设为隐藏
- 其他后处理
- 关于visible
- 虽然所有都被分类为透明/非透明的mesh,但我个人觉得visible为false就不要加在oit里面
- 射线与高亮的问题
- 透明物体很多物体是否需要复原物体材质的属性,因为设置了很多属性
- 新物体需要归进透明类/非透明类
- 全局shader的声明与设置 作用于深度材质和每一个Mesh中
- 变量意义
- uLayer 作为depthOnbeforeCompile是否启用的开关
- uPrevDepthTexture 用来深度对比与剥离
- uScreenSize 搭配gl_FragCoord.xy用来生成UV的
- 整体意义
var globalPeelUniforms = {
uLayer: { value: 0 },
uPrevDepthTexture: { value: null },
uScreenSize: { value: new THREE.Vector2(1, 1) },
};
function depthOnbeforeCompile(shader) {
shader.uniforms.uScreenSize = globalPeelUniforms.uScreenSize;
shader.uniforms.uPrevDepthTexture =
globalPeelUniforms.uPrevDepthTexture;
shader.uniforms.uLayer = globalPeelUniforms.uLayer;
shader.fragmentShader = `
uniform vec2 uScreenSize;
uniform sampler2D uPrevDepthTexture;
uniform int uLayer;
${shader.fragmentShader}
`;
shader.fragmentShader = shader.fragmentShader.replace(
/}$/gm,
`
if(uLayer != 0 ){
vec2 screenPos = gl_FragCoord.xy * uScreenSize; //uv
float prevDepth = unpackRGBAToDepth(texture2D(uPrevDepthTexture,screenPos)); //获取贴图深度
if(prevDepth - gl_FragCoord.z >= 0. ){ //只保留后面部分
discard;
}
}
}
`
);
}
depthMaterial = new THREE.MeshDepthMaterial();
depthMaterial.side = getSide();
depthMaterial.depthPacking = THREE.RGBADepthPacking;
depthMaterial.onBeforeCompile = depthOnbeforeCompile;
- 两个Scene
- scene 一个scene用来存储所有物体的
- compositeScene 一个scene用来展示剥离后的rendertarget贴图的
- compositeScene的展示结果平面

- 左边是贴图,右边是乘以a之后的结果
- 需要乘个a 不然颜色会完全一样
var compositeScene = new THREE.Scene();
compositeMaterial = new THREE.ShaderMaterial({
uniforms: {
uTextureA: { value: null },
uBlit: { value: 0 },
uStencil: { value: 0 }
},
vertexShader: `
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = vec4(position.xy,0.,1.); //全屏
}
`,
fragmentShader: `
varying vec2 vUv;
uniform sampler2D uTextureA;
uniform int uBlit;
uniform int uStencil;
void main(){
vec4 src = texture2D(uTextureA,vUv);
if(uBlit == 0 )
{
gl_FragColor = src;
}
else {
gl_FragColor = src;
gl_FragColor.xyz *= gl_FragColor.a;
}
}
`,
transparent: true,
depthTest: false,
depthWrite: false,
blending: THREE.CustomBlending,
blendEquation: THREE.AddEquation,
blendSrc: THREE.OneMinusDstAlphaFactor,
blendDst: THREE.OneFactor,
blendDstAlpha: null,
blendSrcAlpha: null
});
const planeGeometry = new THREE.PlaneBufferGeometry(2, 2, 1, 1);
const compositePlane = new THREE.Mesh(planeGeometry, compositeMaterial);
compositePlane.frustumCulled = false;
compositeScene.add(compositePlane);
renderer.setRenderTarget();
renderer.setClearColor(0x888888, 1);
renderer.clear();
renderer.setRenderTarget(targets[2]);
renderer.setClearColor(0, 0);
renderer.clear();
renderer.setRenderTarget(targets[1]);
renderer.setClearColor(0xffffff, 1);
renderer.clear();
renderer.setRenderTarget(targets[0]);
renderer.setClearColor(0, 0);
renderer.clear();
renderer.render(scene, camera, targets[0]);
opaqueObjects.forEach((o) => (o.visible = false));
transparentObjects.forEach((o) => (o.visible = true));
scene.overrideMaterial = depthMaterial;
renderer.render(scene, camera, targets[1], false);
scene.overrideMaterial = null;
renderer.setRenderTarget(targets[0]);
renderer.render(scene, camera, targets[0], false);
compositeMaterial.blendSrc = THREE.OneMinusDstAlphaFactor;
compositeMaterial.blendDst = THREE.OneFactor;
compositeMaterial.uniforms.uTextureA.value = targets[0];
compositeMaterial.uniforms.uBlit.value = 1;
renderer.render(compositeScene, camera, targets[2]);
- 不断剥离的过程
- 一般layers是4
- 由于renderer没在targets[2]做clear,所有过去的图像在叠加
- renderTarget:1,切换缓冲区;2,获取截图(在bindFramework为null的时候,生成texture)
for (let i = 0; i < options.layers; i++) {
const flip = i % 2;
const flop = (i + 1) % 2;
globalPeelUniforms.uPrevDepthTexture.value = targets[flop];
renderer.setRenderTarget(targets[flip]);
renderer.setClearColor(0, 0);
renderer.clear(true, true, false);
renderer.render(scene, camera, targets[flip], false);
compositeMaterial.uniforms.uTextureA.value = targets[flip];
renderer.render(compositeScene, camera, targets[2]);
renderer.setRenderTarget(targets[flip]);
renderer.setClearColor(0xffffff, 1);
renderer.clear(true, true, false);
scene.overrideMaterial = depthMaterial;
renderer.render(scene, camera, targets[flip], false);
scene.overrideMaterial = null;
}
- 跑完深度剥离的shader
- 透明物体隐藏,如果不隐藏颜色会加深
globalPeelUniforms.uLayer.value = 0;
transparentObjects.forEach((o) => (o.visible = false));
renderer.render(scene, camera);
compositeMaterial.uniforms.uBlit.value = 0;
compositeMaterial.blendSrc = THREE.OneFactor;
compositeMaterial.blendDst = THREE.OneMinusSrcAlphaFactor;
compositeMaterial.blendSrcAlpha = null;
compositeMaterial.blendDstAlpha = null;
compositeMaterial.uniforms.uTextureA.value = targets[2];
renderer.render(compositeScene, camera);