计算片段着色器中像素的方向以用于程序天空着色器?

问题描述 投票:0回答:1

(所以我在我的准系统 C++ Vulkan 游戏引擎中,我想制作一个像 Godot 4 中那样的程序天空着色器,到目前为止它非常简单,它不是一个天空盒,而是一个足够大以覆盖整个屏幕在相机前面正交渲染,但始终在所有内容后面渲染。在 Godot 4 中,程序天空着色器有一个非常重要的 3D 矢量,称为 EYEDIR,它是片段着色器中当前像素的方向,我还没有完全弄清楚。如何计算这个。)

我尝试了本文中的非优化代码从窗口空间转换为眼睛空间https://www.khronos.org/opengl/wiki/Compute_eye_space_from_window_space 我的代码如下所示:

vec4 calcEyeFromWindow()
{
    vec4 ndcPos;
    ndcPos.xy = (2.0 * gl_FragCoord.xy) / (vec2(screenWidth, screenHeight)) - 1;
    ndcPos.z = (2.0 * gl_FragCoord.z - near - far) / (far - near);
    ndcPos.w = 1.0;

    vec4 clipPos = ndcPos / gl_FragCoord.w;
    vec4 eyePos = invPers * clipPos;

    return eyePos;
}

现在我认为我应该将其归一化为一个方向,但是,这不是我想要的,它没有考虑相机的旋转或视野,无论在哪里它看起来都是一样的当你转动它时,无论你将其调整到什么大小,它都会拉伸到窗口大小。 eye space visualization in procedural sky shader

我尝试将方向转换为相机的视角

vec3 transformDirection(vec4 p){

    vec3 u1 = right * p.x;
    vec3 u2 = forward * p.y;
    vec3 u3 = up * p.z;
    return normalize(u1 + u2 + u3);// the transformed direction in world space
}

但这不仅没有考虑到视野,而且根本不起作用,当你用相机环顾四周时,天空似乎在扭曲和翻转。 (是的,Z 向上)

所以基本上我问的是,Godot 4 天空着色器中的 EYEDIR 是如何计算的? (计算片段着色器中每个像素的方向的数学是什么,假设考虑了 FOV 并与场景中渲染的其他内容完美对齐?)

glsl shader skybox
1个回答
0
投票

成功了!我只需要翻转 y 和 z,因为 z 在我的引擎中是向上的,并且通常是向前的,然后我也需要反转向右和向上的方向,如下所示:

vec4 calcEyeFromWindow()
{
    vec4 ndcPos;
    ndcPos.xy = (2.0 * gl_FragCoord.xy) / (vec2(screenWidth, screenHeight)) - 1;
    ndcPos.z = (2.0 * gl_FragCoord.z - near - far) / (far - near);
    ndcPos.w = 1.0;

    vec4 clipPos = ndcPos / gl_FragCoord.w;
    vec4 eyePos = invPers * clipPos;

    float y = eyePos.y;
    eyePos.y = eyePos.z;
    eyePos.z = y;

    return eyePos;
}

vec3 transformDirection(vec4 p){

    vec3 u1 = -right * p.x;
    vec3 u2 = forward * p.y;
    vec3 u3 = -up * p.z;
    return (u1 + u2 + u3);// the transformed direction in world space
}

...

outColor = vec4(transformDirection(calcEyeFromWindow()), 1);

© www.soinside.com 2019 - 2024. All rights reserved.