(所以我在我的准系统 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;
}
现在我认为我应该将其归一化为一个方向,但是,这不是我想要的,它没有考虑相机的旋转或视野,无论在哪里它看起来都是一样的当你转动它时,无论你将其调整到什么大小,它都会拉伸到窗口大小。
我尝试将方向转换为相机的视角
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 并与场景中渲染的其他内容完美对齐?)
成功了!我只需要翻转 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);