Javascript 如何使用three.js中的深度缓冲区屏蔽对象?
我正在用three.js编写一个2D游戏。首先,我想渲染背景风景。然后,我想渲染一个透明的四元(Javascript 如何使用three.js中的深度缓冲区屏蔽对象?,javascript,three.js,webgl,Javascript,Three.js,Webgl,我正在用three.js编写一个2D游戏。首先,我想渲染背景风景。然后,我想渲染一个透明的四元(不透明度===0),即使您看不到它,它仍然会将值写入深度缓冲区。然后,我想渲染后面有z的对象,该z将其碎片放置在透明四边形后面,这样,由于深度测试失败,任何与透明四边形具有相同屏幕空间位置的碎片都会被丢弃 根据我对OpenGL的理解,这是可能的,但当我的透明四边形的片段着色器的输出具有gl\u FragColor.a==0时,three.js似乎没有为我的透明四边形写入深度值 我已经设置了render
不透明度===0
),即使您看不到它,它仍然会将值写入深度缓冲区。然后,我想渲染后面有z的对象,该z将其碎片放置在透明四边形后面,这样,由于深度测试失败,任何与透明四边形具有相同屏幕空间位置的碎片都会被丢弃
根据我对OpenGL的理解,这是可能的,但当我的透明四边形的片段着色器的输出具有gl\u FragColor.a==0
时,three.js似乎没有为我的透明四边形写入深度值
我已经设置了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)
let制服={
颜色:{
键入:“v4”,
值:新的三个矢量4(0.2,0.8,0.8,1),
},
不透明度:{
类型:“f”,
价值:1,
},
左区:{
类型:“f”,
值:-1,
},
地区(右):{
类型:“f”,
值:-1,
},
地区(顶部):{
类型:“f”,
值:-1,
},
地区(下):{
类型:“f”,
值:-1,
},
}
让顶点着色=
`改变vec2屏幕空间位置;
void main()
{
vec4 mvPosition=modelViewMatrix*vec4(位置,1.0);
屏幕空间位置=mvPosition.xy;
gl_位置=投影矩阵*mvPosition;
}`
让我们来看看这个着色器=
`vec4颜色均匀;
均匀浮动不透明度;
均匀浮动区域_左;
均匀浮动区域_右;
均匀浮动区_顶;
底部均匀浮动区域;
改变vec2屏幕空间位置;
void main()
{
//下面只检查我在“屏幕空间”中定义的2D框
//(实际上,这是相机空间,但我使用的是正交相机
//是像素)并将不透明度设置为零(如果碎片在内部)
//它。
浮动最终不透明度=不透明度;
vec2位置=屏幕空间位置;
如果(position.x>=region\u left&&position.x=region\u top&&position.y以下操作从r73
起生效。仔细控制三个.Mesh
渲染器
和位置
属性是解决方案
首先,我通过删除renderer.sortObjects=false
行重新启用排序。其次,我确保要遮罩的对象的z
位置将它们放置在透明四边形后面
最后,我设置mesh.renderOrder=1
(即使用renderOrder<1
在任何其他网格之后渲染此网格)对于我想要遮罩的每个场景对象的三个.Mesh
对象,以及透明四边形的Mesh.renderder=0.5
。renderder
的默认值是0
,因此在透明四边形和遮罩之前,任何网格的renderder
我没有显式地将渲染设置为正常d对象
请注意,必须为每个网格设置renderOrder
。此属性不会传播到子Object3D
对象。也许三个.js的默认autoClearDepth=true是由零alpha触发的?文档中不清楚从深度缓冲区中删除对象的测试是什么。