OpenGL:在着色器中实现的 Blinn-Phong 模型给出了错误的结果
OpenGL: Blinn-Phong model implemented in shaders give wrong result
首先,我是计算机图形学和 openGL 方面的新手,并且具有 C++ 编码的基本知识。我在 openGL 项目上苦苦挣扎了一个月,到了必须使用 Blinn-Phong 模型实现着色的地步。我已经在顶点和片段着色器中实现了计算。 is/are 代码中可能存在一些小错误,因为没有着色一切正常,但在将着色部分添加到着色器后,任何事情都不会发生。我在片段着色器中计算表面法线,还使用纹理而不仅仅是颜色。我还为每个对象(总共 7 个对象)使用自己的着色器。
如果有人能立即看到我哪里做错了,我会很高兴。我不再收到错误,所以错误可能是在执行过程中。
这是一个对象顶点和片段着色器的代码。
顶点着色器:
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 out_Position;
void main(void)
{
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
out_Position = in_Position;
f_TexCoord0 = in_TexCoord0;
}
片段着色器:
#version 330 core
uniform sampler2D texture1;
in vec2 f_TexCoord0;
in vec3 out_Position;
layout (location=0) out vec4 fragColor;
uniform vec4 ambientMaterial2, diffuseMaterial2, specularMaterial2;
uniform vec4 ambientLight, diffuseLight, specularLight;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 lightPosition;
uniform float shininess;
void main(void)
{
vec4 ambientProduct = ambientLight * ambientMaterial2;
vec4 diffuseProduct = diffuseLight * diffuseMaterial2;
vec4 specularProduct = specularLight * specularMaterial2;
vec3 pos = out_Position.xyz;
vec3 nv = cross(dFdx(pos),dFdy(pos));
nv = nv * sign(nv.z);
vec3 L = normalize(lightPosition.xyz - nv);
vec3 E = normalize(-nv);
vec3 H = normalize(L + E);
vec3 N = nv;
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * diffuseProduct;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
if (Kd > 0.0f)
{
float Ks = dot(H, N);
if (Ks > 0.0f)
{
specular = pow(Ks, shininess) * specularProduct;
}
}
vec4 fragColor_lightning = (ambientProduct + diffuse + specular);
vec4 fragColor_texture = texture2D(texture1, vec2(f_TexCoord0.x, f_TexCoord0.y));
fragColor = fragColor_lightning + fragColor_texture;
}
编辑:
更改的着色器:
顶点着色器:
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
uniform mat4 modelMat;
// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 viewPos;
void main(void)
{
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
viewPos = (modelMat * vec4(in_Position, 1.0)).xyz;
f_TexCoord0 = in_TexCoord0;
}
片段着色器:
#version 330 core
uniform sampler2D texture1;
in vec2 f_TexCoord0;
in vec3 viewPos;
layout (location=0) out vec4 fragColor;
uniform vec4 ambientMaterial2, diffuseMaterial2, specularMaterial2;
uniform vec4 ambientLight, diffuseLight, specularLight;
uniform mat4 viewMat;
uniform vec4 lightPosition;
uniform float shininess;
void main(void)
{
vec4 ambientProduct = ambientLight * ambientMaterial2;
vec4 diffuseProduct = diffuseLight * diffuseMaterial2;
vec4 specularProduct = specularLight * specularMaterial2;
vec3 pos = viewPos;
vec3 nv = cross(dFdx(pos),dFdy(pos));
nv = nv * sign(nv.z);
vec3 L = normalize((viewMat*lightPosition).xyz - pos);
vec3 E = normalize(-pos);
vec3 H = normalize(L + E);
vec3 N = normalize(nv);
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * diffuseProduct;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
if (Kd > 0.0f)
{
float Ks = pow(max(dot(H, N),1.0),shininess);
specular = Ks * specularProduct;
}
vec4 fragColor_lightning = (ambientProduct + diffuse + specular);
vec4 fragColor_texture = texture2D(texture1, vec2(f_TexCoord0.x, f_TexCoord0.y));
fragColor = fragColor_lightning + fragColor_texture;
}
您必须将模型视图投影矩阵拆分为模型视图矩阵和投影矩阵。
使用模型视图矩阵,可以计算视图位置并将其传递给片段着色器。
使用投影矩阵可以计算剪辑 space 位置。
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
uniform mat4 modelview;
uniform mat4 projection;
out vec2 f_TexCoord0;
out vec3 viewPos;
void main(void)
{
vec4 pos = modelview * vec4(in_Position, 1.0);;
f_TexCoord0 = in_TexCoord0;
viewPos = pos.xyz;
gl_Position = projection * pos;
}
要计算 blinn phong 灯模型,另请参阅 GLSL fixed function fragment program replacement
像这样更改您的代码:
in vec3 viewPos;
uniform vec4 lightPosition; // this has to be a view space position
uniform float shininess;
void main()
{
....
vec3 N = cross(dFdx(viewPos.xyz),dFdy(viewPos.xyz));
N = normalize(N * sign(N.z));
vec3 L = normalize(lightPosition.xyz - viewPos.xyz);
vec3 E = normalize(-viewPos.xyz);
vec3 H = normalize(L + E);
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * diffuseProduct;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
if (Kd > 0.0f)
{
float Ks = max(0.0, dot(H, N));
specular = pow(Ks, shininess) * specularProduct;
}
.....
}
编辑:
当您执行 viewPos = (modelMat * vec4(in_Position, 1.0)).xyz;
时,viewPos
不是视图位置,而是模型位置。要计算视图位置,您必须通过模型矩阵和视图矩阵进行转换:viewPos = (viewMat * modelMat * vec4(in_Position, 1.0)).xyz;
.
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
uniform mat4 viewMat;
uniform mat4 modelMat;
// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 viewPos;
void main(void)
{
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
viewPos = (viewMat * modelMat * vec4(in_Position, 1.0)).xyz;
f_TexCoord0 = in_TexCoord0;
}
此外,我建议将纹理颜色乘以浅色:
fragColor = vec4(fragColor_lightning.rgb * fragColor_texture.rgb, fragColor_texture.a);
首先,我是计算机图形学和 openGL 方面的新手,并且具有 C++ 编码的基本知识。我在 openGL 项目上苦苦挣扎了一个月,到了必须使用 Blinn-Phong 模型实现着色的地步。我已经在顶点和片段着色器中实现了计算。 is/are 代码中可能存在一些小错误,因为没有着色一切正常,但在将着色部分添加到着色器后,任何事情都不会发生。我在片段着色器中计算表面法线,还使用纹理而不仅仅是颜色。我还为每个对象(总共 7 个对象)使用自己的着色器。
如果有人能立即看到我哪里做错了,我会很高兴。我不再收到错误,所以错误可能是在执行过程中。
这是一个对象顶点和片段着色器的代码。
顶点着色器:
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 out_Position;
void main(void)
{
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
out_Position = in_Position;
f_TexCoord0 = in_TexCoord0;
}
片段着色器:
#version 330 core
uniform sampler2D texture1;
in vec2 f_TexCoord0;
in vec3 out_Position;
layout (location=0) out vec4 fragColor;
uniform vec4 ambientMaterial2, diffuseMaterial2, specularMaterial2;
uniform vec4 ambientLight, diffuseLight, specularLight;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 lightPosition;
uniform float shininess;
void main(void)
{
vec4 ambientProduct = ambientLight * ambientMaterial2;
vec4 diffuseProduct = diffuseLight * diffuseMaterial2;
vec4 specularProduct = specularLight * specularMaterial2;
vec3 pos = out_Position.xyz;
vec3 nv = cross(dFdx(pos),dFdy(pos));
nv = nv * sign(nv.z);
vec3 L = normalize(lightPosition.xyz - nv);
vec3 E = normalize(-nv);
vec3 H = normalize(L + E);
vec3 N = nv;
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * diffuseProduct;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
if (Kd > 0.0f)
{
float Ks = dot(H, N);
if (Ks > 0.0f)
{
specular = pow(Ks, shininess) * specularProduct;
}
}
vec4 fragColor_lightning = (ambientProduct + diffuse + specular);
vec4 fragColor_texture = texture2D(texture1, vec2(f_TexCoord0.x, f_TexCoord0.y));
fragColor = fragColor_lightning + fragColor_texture;
}
编辑:
更改的着色器:
顶点着色器:
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
uniform mat4 modelMat;
// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 viewPos;
void main(void)
{
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
viewPos = (modelMat * vec4(in_Position, 1.0)).xyz;
f_TexCoord0 = in_TexCoord0;
}
片段着色器:
#version 330 core
uniform sampler2D texture1;
in vec2 f_TexCoord0;
in vec3 viewPos;
layout (location=0) out vec4 fragColor;
uniform vec4 ambientMaterial2, diffuseMaterial2, specularMaterial2;
uniform vec4 ambientLight, diffuseLight, specularLight;
uniform mat4 viewMat;
uniform vec4 lightPosition;
uniform float shininess;
void main(void)
{
vec4 ambientProduct = ambientLight * ambientMaterial2;
vec4 diffuseProduct = diffuseLight * diffuseMaterial2;
vec4 specularProduct = specularLight * specularMaterial2;
vec3 pos = viewPos;
vec3 nv = cross(dFdx(pos),dFdy(pos));
nv = nv * sign(nv.z);
vec3 L = normalize((viewMat*lightPosition).xyz - pos);
vec3 E = normalize(-pos);
vec3 H = normalize(L + E);
vec3 N = normalize(nv);
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * diffuseProduct;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
if (Kd > 0.0f)
{
float Ks = pow(max(dot(H, N),1.0),shininess);
specular = Ks * specularProduct;
}
vec4 fragColor_lightning = (ambientProduct + diffuse + specular);
vec4 fragColor_texture = texture2D(texture1, vec2(f_TexCoord0.x, f_TexCoord0.y));
fragColor = fragColor_lightning + fragColor_texture;
}
您必须将模型视图投影矩阵拆分为模型视图矩阵和投影矩阵。 使用模型视图矩阵,可以计算视图位置并将其传递给片段着色器。 使用投影矩阵可以计算剪辑 space 位置。
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
uniform mat4 modelview;
uniform mat4 projection;
out vec2 f_TexCoord0;
out vec3 viewPos;
void main(void)
{
vec4 pos = modelview * vec4(in_Position, 1.0);;
f_TexCoord0 = in_TexCoord0;
viewPos = pos.xyz;
gl_Position = projection * pos;
}
要计算 blinn phong 灯模型,另请参阅 GLSL fixed function fragment program replacement
像这样更改您的代码:
in vec3 viewPos;
uniform vec4 lightPosition; // this has to be a view space position
uniform float shininess;
void main()
{
....
vec3 N = cross(dFdx(viewPos.xyz),dFdy(viewPos.xyz));
N = normalize(N * sign(N.z));
vec3 L = normalize(lightPosition.xyz - viewPos.xyz);
vec3 E = normalize(-viewPos.xyz);
vec3 H = normalize(L + E);
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * diffuseProduct;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
if (Kd > 0.0f)
{
float Ks = max(0.0, dot(H, N));
specular = pow(Ks, shininess) * specularProduct;
}
.....
}
编辑:
当您执行 viewPos = (modelMat * vec4(in_Position, 1.0)).xyz;
时,viewPos
不是视图位置,而是模型位置。要计算视图位置,您必须通过模型矩阵和视图矩阵进行转换:viewPos = (viewMat * modelMat * vec4(in_Position, 1.0)).xyz;
.
#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;
// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
uniform mat4 viewMat;
uniform mat4 modelMat;
// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 viewPos;
void main(void)
{
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
viewPos = (viewMat * modelMat * vec4(in_Position, 1.0)).xyz;
f_TexCoord0 = in_TexCoord0;
}
此外,我建议将纹理颜色乘以浅色:
fragColor = vec4(fragColor_lightning.rgb * fragColor_texture.rgb, fragColor_texture.a);