我正在用three.js写2D游戏。首先,我想渲染背景风景。然后,我想渲染一个透明的四边形(opacity === 0
),即使您看不到它,它仍会将值写入深度缓冲区。然后,我想渲染具有z的片段,将它们的片段放置在透明四边形后面,以便由于未通过深度测试而丢弃与透明四边形相同的屏幕空间位置的片段。如何使用three.js中的深度缓冲区遮罩对象?
基于我对OpenGL的理解,这是可能的,但似乎three.js没有为透明四边形写入深度值,当我的透明四边形片段着色器的输出有gl_FragColor.a === 0
时。
我已设置renderer.sortObjects = false
。我有z = 0
的背景,z = 1
处的透明四边形以及深度缓冲区将在z = 0.5
处遮挡的对象。
对于透明四边形,我设置了material.transparent = false
,但不是在透明四边形上显示背景,而是显示清晰的颜色。
下面是我如何创建我的透明四:
let uniforms = {
color: {
type: 'v4',
value: new three.Vector4(0.2, 0.8, 0.8, 1),
},
opacity: {
type: 'f',
value: 1,
},
region_left: {
type: 'f',
value: -1,
},
region_right: {
type: 'f',
value: -1,
},
region_top: {
type: 'f',
value: -1,
},
region_bottom: {
type: 'f',
value: -1,
},
}
let vertex_shader =
`varying vec2 screen_space_position;
void main()
{
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
screen_space_position = mvPosition.xy;
gl_Position = projectionMatrix * mvPosition;
}`
let fragment_shader =
`uniform vec4 color;
uniform float opacity;
uniform float region_left;
uniform float region_right;
uniform float region_top;
uniform float region_bottom;
varying vec2 screen_space_position;
void main()
{
// The following just checks a 2D box I've defined in 'screen space'
// (really it's camera space, but I'm using an ortho camera where units
// are pixels) and sets the opacity to zero if the fragment is inside
// it.
float final_opacity = opacity;
vec2 position = screen_space_position;
if (position.x >= region_left && position.x <= region_right &&
position.y >= region_top && position.y <= region_bottom)
{
final_opacity = 0.0;
}
gl_FragColor = vec4(color.rgb, color.a * final_opacity);
// I also tried just bypassing the above code and rendering 0 alpha
// across the entire quad
//gl_FragColor = vec4(1, 1, 1, 0);
}`
// Create geometry that represents a quad
let geometry = new three.PlaneGeometry(1, 1)
// PlaneGeometry assumes the lower left corner is (0, 0). This makes it
// so the upper left corner is (0, 0).
geometry.scale(1, -1, 1)
let material = new three.ShaderMaterial({
uniforms,
vertexShader: vertex_shader,
fragmentShader: fragment_shader,
transparent: true,
})
let mesh = new three.Mesh(geometry, material)
// Center the mesh
mesh.position.set(0.5, 0.5, 0)
let root = new three.Object3D()
root.add(mesh)
也许three.js的默认autoClearDepth = true是由零alpha触发?从文档中不清楚测试是从深度缓冲区中移除一个对象的。 http://threejs.org/docs/#Reference/Renderers/WebGLRenderer – Radio