OpenGL 简单着色,工件
OpenGL Simple Shading, Artifacts
我一直在尝试实现一个简单的光照/着色系统,一个简单的 Phong 照明系统,准确地说是没有镜面光。它基本上可以工作,除了它有一些(在我看来)讨厌的人工制品。
我的第一个想法是,这可能是纹理贴图的问题,但禁用它们没有用。我的下一个最佳猜测是着色器问题,但我似乎找不到错误。
有没有人遇到过类似的问题或关于如何解决这个问题的想法?
顶点着色器:
#version 330 core
// Vertex shader
layout(location = 0) in vec3 vpos;
layout(location = 1) in vec2 vuv;
layout(location = 2) in vec3 vnormal;
out vec2 uv; // UV coordinates
out vec3 normal; // Normal in camera space
out vec3 pos; // Position in camera space
out vec3 light[3]; // Vertex -> light vector in camera space
uniform mat4 mv; // View * model matrix
uniform mat4 mvp; // Proj * View * Model matrix
uniform mat3 nm; // Normal matrix for transforming normals into c-space
void main() {
// Pass uv coordinates
uv = vuv;
// Adjust normals
normal = nm * vnormal;
// Calculation of vertex in camera space
pos = (mv * vec4(vpos, 1.0)).xyz;
// Vector vertex -> light in camera space
light[0] = (mv * vec4(0.0,0.3,0.0,1.0)).xyz - pos;
light[1] = (mv * vec4(-6.0,0.3,0.0,1.0)).xyz - pos;
light[2] = (mv * vec4(0.0,0.3,4.8,1.0)).xyz - pos;
// Pass position after projection transformation
gl_Position = mvp * vec4(vpos, 1.0);
}
片段着色器:
#version 330 core
// Fragment shader
layout(location = 0) out vec3 color;
in vec2 uv; // UV coordinates
in vec3 normal; // Normal in camera space
in vec3 pos; // Position in camera space
in vec3 light[3]; // Vertex -> light vector in camera space
uniform sampler2D tex;
uniform float flicker;
void main() {
vec3 n = normalize(normal);
// Ambient
color = 0.05 * texture(tex, uv).rgb;
// Diffuse lights
for (int i = 0; i < 3; i++) {
l = normalize(light[i]);
cos = clamp(dot(n,l), 0.0, 1.0);
length = length(light[i]);
color += 0.6 * texture(tex, uv).rgb * cos / pow(length, 2);
}
}
正如第一条评论所说,您的颜色计算似乎使用的精度不够。尝试使用 mediump 或 highp 浮点数。
此外,length = length(light[i]); pow(length,2)
表达式效率很低,也可能是观察到的条带的来源;您应该改用 dot(light[i],light[i])
。
所以我发现关于我的问题的信息描述为 "gradient banding",也讨论了 here。问题似乎出在我的纹理的性质上,因为只有 "white" 纹理和真实纹理大部分都是 grey/white 并且当每个颜色通道使用 8 位时实际上有 256 级灰度。
解决方案是实施 post 处理抖动或使用更好的纹理。
我一直在尝试实现一个简单的光照/着色系统,一个简单的 Phong 照明系统,准确地说是没有镜面光。它基本上可以工作,除了它有一些(在我看来)讨厌的人工制品。
我的第一个想法是,这可能是纹理贴图的问题,但禁用它们没有用。我的下一个最佳猜测是着色器问题,但我似乎找不到错误。
有没有人遇到过类似的问题或关于如何解决这个问题的想法?
顶点着色器:
#version 330 core
// Vertex shader
layout(location = 0) in vec3 vpos;
layout(location = 1) in vec2 vuv;
layout(location = 2) in vec3 vnormal;
out vec2 uv; // UV coordinates
out vec3 normal; // Normal in camera space
out vec3 pos; // Position in camera space
out vec3 light[3]; // Vertex -> light vector in camera space
uniform mat4 mv; // View * model matrix
uniform mat4 mvp; // Proj * View * Model matrix
uniform mat3 nm; // Normal matrix for transforming normals into c-space
void main() {
// Pass uv coordinates
uv = vuv;
// Adjust normals
normal = nm * vnormal;
// Calculation of vertex in camera space
pos = (mv * vec4(vpos, 1.0)).xyz;
// Vector vertex -> light in camera space
light[0] = (mv * vec4(0.0,0.3,0.0,1.0)).xyz - pos;
light[1] = (mv * vec4(-6.0,0.3,0.0,1.0)).xyz - pos;
light[2] = (mv * vec4(0.0,0.3,4.8,1.0)).xyz - pos;
// Pass position after projection transformation
gl_Position = mvp * vec4(vpos, 1.0);
}
片段着色器:
#version 330 core
// Fragment shader
layout(location = 0) out vec3 color;
in vec2 uv; // UV coordinates
in vec3 normal; // Normal in camera space
in vec3 pos; // Position in camera space
in vec3 light[3]; // Vertex -> light vector in camera space
uniform sampler2D tex;
uniform float flicker;
void main() {
vec3 n = normalize(normal);
// Ambient
color = 0.05 * texture(tex, uv).rgb;
// Diffuse lights
for (int i = 0; i < 3; i++) {
l = normalize(light[i]);
cos = clamp(dot(n,l), 0.0, 1.0);
length = length(light[i]);
color += 0.6 * texture(tex, uv).rgb * cos / pow(length, 2);
}
}
正如第一条评论所说,您的颜色计算似乎使用的精度不够。尝试使用 mediump 或 highp 浮点数。
此外,length = length(light[i]); pow(length,2)
表达式效率很低,也可能是观察到的条带的来源;您应该改用 dot(light[i],light[i])
。
所以我发现关于我的问题的信息描述为 "gradient banding",也讨论了 here。问题似乎出在我的纹理的性质上,因为只有 "white" 纹理和真实纹理大部分都是 grey/white 并且当每个颜色通道使用 8 位时实际上有 256 级灰度。
解决方案是实施 post 处理抖动或使用更好的纹理。