使用延迟屏幕空间贴花系统的边界检查问题

2024-09-28 01:26:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用OpenGL实现一个延迟屏幕空间贴花系统,这篇文章名为“使用延迟屏幕空间贴花在其他东西上绘制东西”,链接:http://martindevans.me/game-development/2015/02/27/Drawing-Stuff-On-Other-Stuff-With-Deferred-Screenspace-Decals/。你知道吗

将在场景顶部绘制一个红色着色的立方体,该立方体与depthmask设置为false的墙一致。 图像链接(无边界立方体):https://gyazo.com/8487947bd4afb08d8d0431551057ad6f

来自墙的depthbuffer和一些vertexshader输出用于计算墙在墙的尺寸内的objectspace位置立方体。立方体绑定检查确保在墙的objectspace位置之外的立方体的每个pixle都被丢弃。你知道吗

问题是边界没有正常工作,立方体完全消失了。你知道吗

潜在故障

我已经通过在lighitingpass中可视化depthbuffer来检查它是否工作正常,它似乎工作正常。depthbuffer存储在gbuffer中的颜色附件中,floatsize为GL\u RGB32F。 图像链接(liggingpass depthbuffer faraway wall可视化):https://gyazo.com/69920a532ca27aa9f57478cb57e0c84c

贴花明暗器代码

顶点着色器

// Vertex positions    
vec4 InputPosition = vec4(aPos, 1);   

// Viewspace Position    
PositionVS = view* model* InputPosition;    

// Clipspace Position    
PositionCS = projection*PositionVS;

gl_Position = PositionCS;    

碎片着色器

// Position on the screen    
vec2 screenPos = PositionCS.xy / PositionCS.w;

// Convert into a texture coordinate   
vec2 texCoord = vec2((1 + screenPos.x) / 2 + (0.5 / resolution.x), (1 - 
screenPos.y) / 2 + (0.5 / resolution.y));

// Sampled value from depth buffer   
vec4 sampledDepth = texture(gDepth, texCoord);

// View-direction   
vec3 viewRay = PositionVS.xyz * (farClip / -PositionVS.z);

// Wallposition in view-space   
vec3 viewPosition = viewRay*sampledDepth.z;

// Transformation from view-space to world-space   
vec3 WorldPos = (invView*vec4(viewPosition, 1)).xyz;

// Transformation from world-space to object-space   
vec3 objectPosition = (invModel*vec4(WorldPos, 1)).xyz;

// Bounds check, discard pixels outside the wall in object-space    
if (abs(objectPosition.x) > 0.5) discard;    
else if (abs(objectPosition.y) > 0.5) discard;    
else if (abs(objectPosition.z) > 0.5) discard;    

// Color to Gbuffer    
gAlbedoSpec = vec4(1, 0, 0, 1);

代码说明

invView和invModel分别与view和model marices相反。矩阵求逆运算在CPU中完成,并作为统一格式发送到fragmentshader。farClip是到摄影机远平面的距离(此处设置为3000)。gDepth是Gbuffer的深度纹理。你知道吗

问题

与立方体一致的墙部分应为红色阴影,如下图所示。你知道吗

图像链接(有边界的立方体):https://gyazo.com/ab6d0db2483a969db932d2480a5acd08

我猜问题是如何将viewspace位置转换为objectspace位置,但我想不出来!你知道吗


Tags: https图像view链接positionspacediscard边界
1条回答
网友
1楼 · 发布于 2024-09-28 01:26:34

你把粉笔和奶酪搞混了。PositionCS是剪辑空间位置,可以通过Perspective divide转换为规范化的设备空间位置:

vec2 ndcPos = PositionCS.xyz / PositionCS.w;

sampledDepth是一个深度值(默认范围为[0,1]),可以通过从深度缓冲区纹理读取“红色”颜色通道(.r.x)获得。深度可以通过depth*2.0-1.0转换为标准化设备空间Z坐标:

vec2 texCoord = ndcPos.xy * 0.5 + 0.5; 
   // (+ 0.5/resolution.xy;) is not necessary if texture filter is GL_NEAREST

float sampledDepth = texture(gDepth, texCoord).x;

float sampleNdcZ = sampledDepth * 2.0 - 1.0;

在透视投影和标准化设备空间中,具有相同x和y坐标的所有点都位于从视图位置开始的相同光线上。你知道吗

这意味着,如果深度缓冲区gDepth是使用与ndcPosPositionCS)相同的视图矩阵和投影矩阵生成的,则可以用深度缓冲区(sampleNdcZ)中相应的NDC z坐标替换ndcPos.z,并且该点仍然位于同一视图光线上。
ndcPos.zsampleNdcZ是同一参考系中的可比较值。你知道吗

vec3 ndcSample = vec3(ndcPos.xy, sampleNdcZ);

该坐标可以通过逆投影矩阵和透视分割转换为视图空间坐标。
如果将同一视图光线上的NDC点转换为视图空间,则XY坐标将不同。注意,转换不是线性的,因为(* 1/.w)。另见OpenGL - Mouse coordinates to Space coordinates。你知道吗

uniform mat4 invProj; // = inverse(projection)
vec4 hViewPos     = invProj * vec4(ndcSample, 1.0);
vec3 viewPosition = hViewPos.xyz / hViewPos.w;

这可以通过逆视图矩阵到世界空间和逆模型矩阵到对象空间进一步转换:

vec3 WorldPos       = (invView * vec4(viewPosition, 1.0)).xyz;
vec3 objectPosition = (invModel * vec4(WorldPos, 1.0)).xyz;

相关问题 更多 >

    热门问题