OpenGL 延迟着色照明无法正常工作
OpenGL Deferred Shading lighting not working properly
所以这是我第一次使用延迟着色,它非常快速和简单。直到我开始没有得到预期的结果。光的行为很奇怪,就像位置纹理不对一样。
(从上到下顺时针:(1)正常,(2)位置,(3)反照率,(4)Roughness/Fresnel,(中心)最终)
请注意光线(在最终渲染中)的行为很奇怪。
这是我的着色器代码:
GBuffer.vert
#version 330 core
// I didn't have time to change this into layout (location = ...) ...
attribute vec3 pos;
attribute vec3 norm;
attribute vec3 tangent;
attribute vec2 uv;
out DATA {
vec3 position;
vec3 normal;
vec2 texCoord;
mat3 tbn;
} VS_OUT;
void main() {
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0);
VS_OUT.position = (gl_ModelViewMatrix * vec4(pos, 1.0)).xyz;
VS_OUT.normal = gl_NormalMatrix * norm;
vec3 n = normalize(VS_OUT.normal);
vec3 t = normalize(gl_NormalMatrix * tangent);
t = normalize(t - dot(t, n) * n);
vec3 b = cross(t, n);
VS_OUT.tbn = mat3(t, b, n);
VS_OUT.texCoord = uv;
}
GBuffer.frag
#version 330 core
layout (location = 0) out vec3 g_position;
layout (location = 1) out vec3 g_normal;
layout (location = 2) out vec4 g_diffuse;
layout (location = 3) out vec4 g_material;
struct TSlot {
int active;
int type;
vec2 scale;
float intensity;
int blendMode;
};
struct TMaterial {
vec4 albedo;
float roughness;
float fresnel;
};
struct TScene {
vec3 ambient;
vec3 viewPosition;
};
// Textures
uniform sampler2D textures[8];
uniform TSlot textureSlots[8];
// Scene
uniform TScene scene;
// Material
uniform TMaterial material;
// Object
in DATA {
vec3 position;
vec3 normal;
vec2 texCoord;
mat3 tbn;
} FS_IN;
[... blending functions ...]
void main() {
vec3 N = FS_IN.normal;
vec4 texs = vec4(1.0);
vec4 tex0 = vec4(0.0);
for (int i = 0; i < 8; i++) {
if (textureSlots[i].active == 0) { continue; }
vec2 uv = textureSlots[i].scale * FS_IN.texCoord;
int type = textureSlots[i].type;
if (type == 0) { // Diffuse
vec4 diff = texture2D(textures[i], uv);
texs = blend(texs, diff, textureSlots[i].intensity * diff.a, textureSlots[i].blendMode);
} if (type == 1) { // Normal
vec3 encNorm = texture2D(textures[i], uv).xyz;
vec3 localCoords = normalize(vec3(2.0, 2.0, 1.0) * encNorm - vec3(1.0, 1.0, 0.0));
N *= normalize(FS_IN.tbn * localCoords);
} else if (type == 2) { // Sphere Reflection
vec3 E = normalize(scene.viewPosition - FS_IN.position);
vec3 R = normalize(reflect(E, N));
float m = 2.0 * sqrt(
pow(R.x, 2.0) +
pow(R.y, 2.0) +
pow(R.z + 1.0, 2.0)
);
vec2 tex = R.xy / m + 0.5;
vec4 diff = texture2D(textures[i], tex * textureSlots[i].scale);
texs = blend(texs, diff, textureSlots[i].intensity * diff.a, textureSlots[i].blendMode);
} else if (type == 3) { // Roughness Map
tex0.r = blendNormalFloat(tex0.r, texture2D(textures[i], uv).x, textureSlots[i].intensity);
} else if (type == 4) { // Fresnel Map
tex0.g = blendNormalFloat(tex0.g, texture2D(textures[i], uv).x, textureSlots[i].intensity);
}
}
// Outputs
g_position = FS_IN.position;
g_normal = N;
g_diffuse.rgb = texs.rgb * material.albedo.rgb;
g_diffuse.a = 1.0;
g_material = vec4(material.roughness + tex0.r, material.fresnel + tex0.g, 0.0, 0.0);
}
Lighting.vert
#version 330 core
void main() {
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Lighting.frag
#version 330 core
layout (location = 0) out vec4 fragColor;
struct TLight {
vec3 position;
float intensity;
vec3 color;
float radius;
float cutoff;
float spotCutoff;
vec3 direction;
int type;
};
struct TScene {
vec3 ambient;
vec3 viewPosition;
};
// Textures from GBuffer
uniform sampler2D t_position;
uniform sampler2D t_normal;
uniform sampler2D t_diffuse;
uniform sampler2D t_material;
uniform TLight light;
uniform TScene scene;
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec3 P = texture2D(t_position, uv).xyz;
vec3 N = normalize(texture2D(t_normal, uv).xyz);
vec4 D = texture2D(t_diffuse, uv);
vec4 M = texture2D(t_material, uv);
vec3 lighting = D.rgb * 0.1;
vec3 V = normalize(scene.viewPosition - P);
vec3 lightDir = normalize(light.position - P);
vec3 diffuse = max(dot(N, lightDir), 0.0) * D.rgb * light.color * light.intensity;
lighting += diffuse;
fragColor = vec4(lighting, 1.0);
}
我正在学习这些教程:http://www.codinglabs.net/tutorial_simple_def_rendering.aspx
http://learnopengl.com/#!Advanced-Lighting/Deferred-Shading
编辑:事实证明我只需要为法线和位置使用浮动纹理
两个想法:
您必须使用浮点纹理,否则您的值将被限制在 [0;1] 范围内,或者对于您的法线,您可以将它们缩放并偏置到该范围(并使用小于 32F/ 16F)
除非您将 CPU 一侧的灯光位置更改为在视图坐标中,否则您将使用视图位置(从您的位置 g 缓冲区)和世界坐标(您的灯光位置)进行计算lighting.frag 中的同一时间,这肯定会弄乱输出。
希望对您有所帮助!
所以这是我第一次使用延迟着色,它非常快速和简单。直到我开始没有得到预期的结果。光的行为很奇怪,就像位置纹理不对一样。
请注意光线(在最终渲染中)的行为很奇怪。
这是我的着色器代码: GBuffer.vert
#version 330 core
// I didn't have time to change this into layout (location = ...) ...
attribute vec3 pos;
attribute vec3 norm;
attribute vec3 tangent;
attribute vec2 uv;
out DATA {
vec3 position;
vec3 normal;
vec2 texCoord;
mat3 tbn;
} VS_OUT;
void main() {
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0);
VS_OUT.position = (gl_ModelViewMatrix * vec4(pos, 1.0)).xyz;
VS_OUT.normal = gl_NormalMatrix * norm;
vec3 n = normalize(VS_OUT.normal);
vec3 t = normalize(gl_NormalMatrix * tangent);
t = normalize(t - dot(t, n) * n);
vec3 b = cross(t, n);
VS_OUT.tbn = mat3(t, b, n);
VS_OUT.texCoord = uv;
}
GBuffer.frag
#version 330 core
layout (location = 0) out vec3 g_position;
layout (location = 1) out vec3 g_normal;
layout (location = 2) out vec4 g_diffuse;
layout (location = 3) out vec4 g_material;
struct TSlot {
int active;
int type;
vec2 scale;
float intensity;
int blendMode;
};
struct TMaterial {
vec4 albedo;
float roughness;
float fresnel;
};
struct TScene {
vec3 ambient;
vec3 viewPosition;
};
// Textures
uniform sampler2D textures[8];
uniform TSlot textureSlots[8];
// Scene
uniform TScene scene;
// Material
uniform TMaterial material;
// Object
in DATA {
vec3 position;
vec3 normal;
vec2 texCoord;
mat3 tbn;
} FS_IN;
[... blending functions ...]
void main() {
vec3 N = FS_IN.normal;
vec4 texs = vec4(1.0);
vec4 tex0 = vec4(0.0);
for (int i = 0; i < 8; i++) {
if (textureSlots[i].active == 0) { continue; }
vec2 uv = textureSlots[i].scale * FS_IN.texCoord;
int type = textureSlots[i].type;
if (type == 0) { // Diffuse
vec4 diff = texture2D(textures[i], uv);
texs = blend(texs, diff, textureSlots[i].intensity * diff.a, textureSlots[i].blendMode);
} if (type == 1) { // Normal
vec3 encNorm = texture2D(textures[i], uv).xyz;
vec3 localCoords = normalize(vec3(2.0, 2.0, 1.0) * encNorm - vec3(1.0, 1.0, 0.0));
N *= normalize(FS_IN.tbn * localCoords);
} else if (type == 2) { // Sphere Reflection
vec3 E = normalize(scene.viewPosition - FS_IN.position);
vec3 R = normalize(reflect(E, N));
float m = 2.0 * sqrt(
pow(R.x, 2.0) +
pow(R.y, 2.0) +
pow(R.z + 1.0, 2.0)
);
vec2 tex = R.xy / m + 0.5;
vec4 diff = texture2D(textures[i], tex * textureSlots[i].scale);
texs = blend(texs, diff, textureSlots[i].intensity * diff.a, textureSlots[i].blendMode);
} else if (type == 3) { // Roughness Map
tex0.r = blendNormalFloat(tex0.r, texture2D(textures[i], uv).x, textureSlots[i].intensity);
} else if (type == 4) { // Fresnel Map
tex0.g = blendNormalFloat(tex0.g, texture2D(textures[i], uv).x, textureSlots[i].intensity);
}
}
// Outputs
g_position = FS_IN.position;
g_normal = N;
g_diffuse.rgb = texs.rgb * material.albedo.rgb;
g_diffuse.a = 1.0;
g_material = vec4(material.roughness + tex0.r, material.fresnel + tex0.g, 0.0, 0.0);
}
Lighting.vert
#version 330 core
void main() {
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Lighting.frag
#version 330 core
layout (location = 0) out vec4 fragColor;
struct TLight {
vec3 position;
float intensity;
vec3 color;
float radius;
float cutoff;
float spotCutoff;
vec3 direction;
int type;
};
struct TScene {
vec3 ambient;
vec3 viewPosition;
};
// Textures from GBuffer
uniform sampler2D t_position;
uniform sampler2D t_normal;
uniform sampler2D t_diffuse;
uniform sampler2D t_material;
uniform TLight light;
uniform TScene scene;
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec3 P = texture2D(t_position, uv).xyz;
vec3 N = normalize(texture2D(t_normal, uv).xyz);
vec4 D = texture2D(t_diffuse, uv);
vec4 M = texture2D(t_material, uv);
vec3 lighting = D.rgb * 0.1;
vec3 V = normalize(scene.viewPosition - P);
vec3 lightDir = normalize(light.position - P);
vec3 diffuse = max(dot(N, lightDir), 0.0) * D.rgb * light.color * light.intensity;
lighting += diffuse;
fragColor = vec4(lighting, 1.0);
}
我正在学习这些教程:http://www.codinglabs.net/tutorial_simple_def_rendering.aspx http://learnopengl.com/#!Advanced-Lighting/Deferred-Shading
编辑:事实证明我只需要为法线和位置使用浮动纹理
两个想法:
您必须使用浮点纹理,否则您的值将被限制在 [0;1] 范围内,或者对于您的法线,您可以将它们缩放并偏置到该范围(并使用小于 32F/ 16F)
除非您将 CPU 一侧的灯光位置更改为在视图坐标中,否则您将使用视图位置(从您的位置 g 缓冲区)和世界坐标(您的灯光位置)进行计算lighting.frag 中的同一时间,这肯定会弄乱输出。
希望对您有所帮助!