【问题标题】:Incorrect tracing with SSLR (Screen Space Local Reflections)使用 SSLR(屏幕空间局部反射)的不正确跟踪
【发布时间】:2019-04-08 06:43:51
【问题描述】:

在实现 SSLR 时,我遇到了对象显示不正确的问题:它们被无限地“向下”投影并且根本无法在镜子中显示。下面我给出代码和截图。

片段 SSLR 着色器:

#version 330 core

uniform sampler2D normalMap; // in view space
uniform sampler2D depthMap; // in view space
uniform sampler2D colorMap;
uniform sampler2D reflectionStrengthMap;
uniform mat4 projection;
uniform mat4 inv_projection;

in vec2 texCoord;

layout (location = 0) out vec4 fragColor;

vec3 calcViewPosition(in vec2 texCoord) {
    // Combine UV & depth into XY & Z (NDC)
    vec3 rawPosition = vec3(texCoord, texture(depthMap, texCoord).r);

    // Convert from (0, 1) range to (-1, 1)
    vec4 ScreenSpacePosition = vec4(rawPosition * 2 - 1, 1);

    // Undo Perspective transformation to bring into view space
    vec4 ViewPosition = inv_projection * ScreenSpacePosition;

    // Perform perspective divide and return
    return ViewPosition.xyz / ViewPosition.w;
}

vec2 rayCast(vec3 dir, inout vec3 hitCoord, out float dDepth) {
    dir *= 0.25f;  

    for (int i = 0; i < 20; i++) {
        hitCoord += dir; 

        vec4 projectedCoord = projection * vec4(hitCoord, 1.0);
        projectedCoord.xy /= projectedCoord.w;
        projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; 

        float depth = calcViewPosition(projectedCoord.xy).z;
        dDepth = hitCoord.z - depth; 

        if(dDepth < 0.0) return projectedCoord.xy;
    }

    return vec2(-1.0);
}

void main() {
    vec3 normal = texture(normalMap, texCoord).xyz * 2.0 - 1.0;
    vec3 viewPos = calcViewPosition(texCoord);

    // Reflection vector
    vec3 reflected = normalize(reflect(normalize(viewPos), normalize(normal)));

    // Ray cast
    vec3 hitPos = viewPos;
    float dDepth; 
    float minRayStep = 0.1f;
    vec2 coords = rayCast(reflected * max(minRayStep, -viewPos.z), hitPos, dDepth);
    if (coords != vec2(-1.0)) fragColor = mix(texture(colorMap, texCoord), texture(colorMap, coords), texture(reflectionStrengthMap, texCoord).r);
    else fragColor = texture(colorMap, texCoord);
}

截图:

另外,灯完全没有反射

我会很感激你的帮助

更新:

colorMap:

normalMap:

depthMap:

更新:我用错误的反射解决了问题,但仍然存在问题。

我是这样解决的:ViewPosition.y *= -1

现在,正如您在屏幕截图中看到的那样,由于某种原因,对象的下部没有被反射。

问题仍然悬而未决。

【问题讨论】:

  • 这个问题远没有提供MCVE,所以只能猜测。什么 ius colorMap,你的渲染架构是什么(尤其是你在做什么)。此外max(minRayStep, -viewPos.z) 似乎有点奇怪,如果镜子距离几个单位,这将导致巨大的步长。
  • @derhass 我更新了问题

标签: opengl glsl raytracing raycasting post-processing


【解决方案1】:

我也在努力获得一个好的 ssr。我发现了两件事可以提供帮助。

  1. 要获得视图空间法线,您必须只保留相机的旋转并移除平移,因为如果不这样做,您将获得法线拉伸到相机移动的相反方向并且不再具有正确的即使您再次对它们进行规范化,对于 mat4 列,您也可以这样做:

    mat4 viewNoTranslation = view; viewNoTranslation[3] = vec4(0.0, 0.0, 0.0, 1.0);

  2. 深度图像的深度采样是对数的,如果将其线性化,您确实会得到从 0 到 1 的值,但它们对于所需的精度会不准确。我试图直接从顶点着色器获取深度值:

    gl_Position = ubo.projection * ubo.view * ubo.model * inPos; 深度 = gl_Position.z;

我不知道它是否正确,但现在的深度更准确。

如果你有进步,请更新:)

【讨论】:

  • 感谢您的回答,但不幸的是,您提出的解决方案对我没有帮助。如果你成功实现了SSR,可以分享一下代码吗?
  • 是的,我终于做到了,它需要更多变量来处理边缘和一些视觉错误,但它有效:D Btw 计算适用于 Vulkan NDC,但如果需要,您可以轻松转换它们。这是着色器github.com/christoskaramou/VulkanMonkey3D/blob/master/…
  • 我传递了 2 个缓冲区,法线和世界空​​间中的位置,其中 w 分量是在 gBuffer 着色器中进行投影计算之前从顶点着色器到视图空间的深度。 vec4 viewPos = ubo.view * ubo.model * inPos;深度 = viewPos.z;您必须使用被认为可以获得正确结果的值
  • 非常感谢,你给了我一个好主意。问题已解决,我稍后会发布解决方案
  • @PeGinnOS 问题出在depthMap。现在我只使用positionMap。正确shader
猜你喜欢
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 2022-01-14
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多