我一直致力于将贴花投影到贴花边界框封装的任何东西上。在阅读并尝试了大量代码片段(通常在 HLSL 中)之后,我在 GLSL 中找到了一些用于投影贴花的工作方法。
让我首先尝试解释一下我在做什么以及它是如何工作的(到目前为止)。
下面的代码现已修复并可以运行!
这一切都是在透视 View 模式下进行的。
我将 2 个制服发送到片段着色器“tr”和“bl”。这些是边界框的两个角。我可以并且将会用硬编码尺寸替换它们,因为它们是贴花原始边界框的尺寸。 tr = vec3(.5, .5, .5) 和 br = vec3(-.5, -.5, -.5)。我更愿意找到一种在贴花转换状态下进行位置测试的方法。 (最后有更多相关信息)。
为了清楚起见添加此内容。从顶点程序发出的顶点是边界框乘以贴花矩阵,然后乘以模型 View 投影矩阵。我将其用于下一步:
通过该顶点,我从深度纹理中获取深度值,并使用它使用投影矩阵的逆来计算世界空间中的位置。
接下来,我使用贴花矩阵的逆来平移该位置。 (缩放、旋转和平移 1,1,1 立方体到其世界位置的矩阵。我认为通过使用贴花变换矩阵的逆,可以正确处理屏幕点的正确大小和旋转,但它是不是。
顶点程序:
//Decals color pass.
#version 330 compatibility
out mat4 matPrjInv;
out vec4 positionSS;
out vec4 positionWS;
out mat4 invd_mat;
uniform mat4 decal_matrix;
void main(void)
{
gl_Position = decal_matrix * gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
positionWS = (decal_matrix * gl_Vertex);;
positionSS = gl_Position;
matPrjInv = inverse(gl_ModelViewProjectionMatrix);
invd_mat = inverse(decal_matrix);
}
片段程序:
#version 330 compatibility
layout (location = 0) out vec4 gPosition;
layout (location = 1) out vec4 gNormal;
layout (location = 2) out vec4 gColor;
uniform sampler2D depthMap;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform mat4 matrix;
uniform vec3 tr;
uniform vec3 bl;
in vec2 TexCoords;
in vec4 positionSS; // screen space
in vec4 positionWS; // world space
in mat4 invd_mat; // inverse decal matrix
in mat4 matPrjInv; // inverse projection matrix
void clip(vec3 v){
if (v.x > tr.x || v.x < bl.x ) { discard; }
if (v.y > tr.y || v.y < bl.y ) { discard; }
if (v.z > tr.z || v.z < bl.z ) { discard; }
}
vec2 postProjToScreen(vec4 position)
{
vec2 screenPos = position.xy / position.w;
return 0.5 * (vec2(screenPos.x, screenPos.y) + 1);
}
void main(){
// Calculate UVs
vec2 UV = postProjToScreen(positionSS);
// sample the Depth from the Depthsampler
float Depth = texture2D(depthMap, UV).x * 2.0 - 1.0;
// Calculate Worldposition by recreating it out of the coordinates and depth-sample
vec4 ScreenPosition;
ScreenPosition.xy = UV * 2.0 - 1.0;
ScreenPosition.z = (Depth);
ScreenPosition.w = 1.0f;
// Transform position from screen space to world space
vec4 WorldPosition = matPrjInv * ScreenPosition ;
WorldPosition.xyz /= WorldPosition.w;
WorldPosition.w = 1.0f;
// transform to decal original position and size.
// 1 x 1 x 1
WorldPosition = invd_mat * WorldPosition;
clip (WorldPosition.xyz);
// Get UV for textures;
WorldPosition.xy += 0.5;
WorldPosition.y *= -1.0;
vec4 bump = texture2D(normalMap, WorldPosition.xy);
gColor = texture2D(colorMap, WorldPosition.xy);
//Going to have to do decals in 2 passes..
//Blend doesn't work with GBUFFER.
//Lots more to sort out.
gNormal.xyz = bump;
gPosition = positionWS;
}
我尝试使用贴花和投影矩阵创建一个新的矩阵,以构造一种“观看”矩阵,并将屏幕位置转换为贴花后转换状态。我无法使其正常工作。有些地方我遗漏了一些东西,但在哪里?我认为使用贴花矩阵的逆进行翻译可以处理变换并将屏幕位置置于正确的变换状态。有想法吗?
更新了纹理 UV 的代码。您可能需要摆弄 y 和 x,具体取决于您的纹理是在 x 还是 y 上翻转。我还修复了剪辑子,使其正常工作。事实上,这段代码现在可以工作了。如果需要的话,我会对此进行更多更新,这样其他人就不必经历我为使其正常工作而经历的痛苦。
需要解决的一些问题是贴花相互重叠。上面的写了下面的。我想我必须将颜色和法线累积到默认的 FBO 中,然后在照明 channel 之前或期间将它们混合(添加)到 GBUFFER 纹理中。添加更多屏幕尺寸的纹理并不是一个好主意,因此我需要发挥创意并尽可能回收任何纹理。
我找到了贴花相互重叠的解决方案。
绘制贴花时关闭深度 mask ,然后重新打开 int:
glDepthMask(GL_FALSE)
最佳答案
好吧..我很兴奋。我发现了这个问题。 我再次更新了上面的代码。 我在发送 tr 和 bl 着色器时犯了一个错误: 以下是对剪辑的更改:
void clip(vec3 v){
if (v.x > tr.x || v.x < bl.x ) { discard; }
if (v.y > tr.y || v.y < bl.y ) { discard; }
if (v.z > tr.z || v.z < bl.z ) { discard; }
}
关于opengl - GBUFFER 贴花投影和缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43455546/