使用模板缓冲区进行交叉点检测
Intersection detection with stencil buffer
为了实现延迟闪电,我将光源渲染为具有光半径的球体。
我只渲染了屏幕上光线的实际位置。结果如下。
所以我想也许如果我可以渲染这个球体的交点,那么我就可以摆脱延迟着色器中每个灯的 for 循环。
通过在 link https://kayru.org/articles/deferred-stencil/ 中使用以下文档
我实现了光球与我实际场景的交集,我把它保存到下面的纹理中。
问题是结果与我预期的有点不同。交集还包括其他领域。光体积不应相互交叉。如何实现正确的交集方法?
int k = 0;
for(GLXlight & glxlightdata : entitySystem->glxlights){
lBufferShader->uniform4f(lBufferShader->lightPos[k], &glxlightdata.lightPos[0]);
k++;
}
lBufferShader->uniformMatrix4(lBufferShader->ViewMatrix, &entitySystem->view[0][0]); //ViewMatrix
lBufferShader->uniform3f(lBufferShader->viewPos, &(*entitySystem->viewpos)[0]); //viewPos
lBufferShader->uniformMatrix4(lBufferShader->ProjectionMatrix, &entitySystem->projection[0][0]); //ProjectionMatrix
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lightObject->glxobject.elementBufferID);
glCullFace(GL_BACK); //Front (near) faces only
glColorMask(GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE); //Colour write is disabled
glDepthMask(GL_FALSE); //Z-write is disabled
glDepthFunc(GL_LEQUAL); //Z function is 'Less/Equal'//
glStencilFunc(GL_ALWAYS, 0, 0x00); //Stencil test result does not modify Stencil buffer
glStencilMask(0xFF);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); //Z-Fail writes non-zero value to Stencil buffer
glDrawElementsInstanced(GL_TRIANGLES, lightObject->glxobject.size, GL_UNSIGNED_SHORT, (void *) 0, lightObject->glxinstances.size());
glCullFace(GL_FRONT); //Back (far) faces only
glColorMask(GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE); //Colour write is enabled
glDepthMask(GL_FALSE); //Z-write is disabled
glDepthFunc(GL_GEQUAL); //Z function is 'Greater/Equal'
glStencilFunc(GL_EQUAL, 0, 0xFF); //Stencil test result does not modify Stencil buffer
glStencilMask(0xFF);
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP); //Z-Fail writes non-zero value to Stencil buffer
glDrawElementsInstanced(GL_TRIANGLES, lightObject->glxobject.size, GL_UNSIGNED_SHORT, (void *) 0, lightObject->glxinstances.size());
我解决了这个问题。
将几何体渲染到缓冲区后,我没有将四边形绘制到屏幕,而是在下面渲染了球体。
首先,使用以下状态在空通道中渲染光球。
glEnable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDepthFunc(GL_LESS);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 0, 0);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
glDepthMask(GL_FALSE);//disable writing to depth buffer
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);//!! disable writing to color buffer
现在使用以下状态再次渲染光球。
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
为了实现延迟闪电,我将光源渲染为具有光半径的球体。
我只渲染了屏幕上光线的实际位置。结果如下。
所以我想也许如果我可以渲染这个球体的交点,那么我就可以摆脱延迟着色器中每个灯的 for 循环。
通过在 link https://kayru.org/articles/deferred-stencil/ 中使用以下文档 我实现了光球与我实际场景的交集,我把它保存到下面的纹理中。
问题是结果与我预期的有点不同。交集还包括其他领域。光体积不应相互交叉。如何实现正确的交集方法?
int k = 0;
for(GLXlight & glxlightdata : entitySystem->glxlights){
lBufferShader->uniform4f(lBufferShader->lightPos[k], &glxlightdata.lightPos[0]);
k++;
}
lBufferShader->uniformMatrix4(lBufferShader->ViewMatrix, &entitySystem->view[0][0]); //ViewMatrix
lBufferShader->uniform3f(lBufferShader->viewPos, &(*entitySystem->viewpos)[0]); //viewPos
lBufferShader->uniformMatrix4(lBufferShader->ProjectionMatrix, &entitySystem->projection[0][0]); //ProjectionMatrix
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lightObject->glxobject.elementBufferID);
glCullFace(GL_BACK); //Front (near) faces only
glColorMask(GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE); //Colour write is disabled
glDepthMask(GL_FALSE); //Z-write is disabled
glDepthFunc(GL_LEQUAL); //Z function is 'Less/Equal'//
glStencilFunc(GL_ALWAYS, 0, 0x00); //Stencil test result does not modify Stencil buffer
glStencilMask(0xFF);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); //Z-Fail writes non-zero value to Stencil buffer
glDrawElementsInstanced(GL_TRIANGLES, lightObject->glxobject.size, GL_UNSIGNED_SHORT, (void *) 0, lightObject->glxinstances.size());
glCullFace(GL_FRONT); //Back (far) faces only
glColorMask(GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE); //Colour write is enabled
glDepthMask(GL_FALSE); //Z-write is disabled
glDepthFunc(GL_GEQUAL); //Z function is 'Greater/Equal'
glStencilFunc(GL_EQUAL, 0, 0xFF); //Stencil test result does not modify Stencil buffer
glStencilMask(0xFF);
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP); //Z-Fail writes non-zero value to Stencil buffer
glDrawElementsInstanced(GL_TRIANGLES, lightObject->glxobject.size, GL_UNSIGNED_SHORT, (void *) 0, lightObject->glxinstances.size());
我解决了这个问题。 将几何体渲染到缓冲区后,我没有将四边形绘制到屏幕,而是在下面渲染了球体。
首先,使用以下状态在空通道中渲染光球。
glEnable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDepthFunc(GL_LESS);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 0, 0);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
glDepthMask(GL_FALSE);//disable writing to depth buffer
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);//!! disable writing to color buffer
现在使用以下状态再次渲染光球。
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);