顶点着色器glsl qt中的纹理映射
Texture mapping in vertex shader glsl qt
我正在尝试使用 QOpenGLWindow 在 opengl 中通过纹理映射实现逐顶点照明。但是渲染的对象有黑色。如果我在片段着色器中做相同的纹理映射,它工作正常。
//Vertex Shader
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 tangent;
layout (location = 3) in vec3 bitangent;
layout (location = 4) in vec2 texCoords;
out vec4 afragColor;
vec3 fragPos;
out vec2 fragTexCoords;
mat3 TBN;
uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2D bumpMap;
vec3 calcAmbientLight(int idx, vec3 color, float ambient) {
return ambient * color * vec3(ambientLight[idx].color);
}
vec3 calcDirectionalLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
vec3 lightDir = normalize(-vec3(directionalLight[idx].direction));
vec3 viewDir = normalize(vec3(viewPos) - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
vec3 result = vec3(0.0f);
result += diff * color * max(dot(normal, lightDir), 0.0f);
result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
return result * vec3(directionalLight[idx].color);
}
vec3 calcPointLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
vec3 lightDir = normalize(vec3(pointLight[idx].pos) - fragPos);
vec3 viewDir = normalize(vec3(viewPos) - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float dis = length(vec3(pointLight[idx].pos) - fragPos);
vec3 result = vec3(0.0f);
result += diff * color * max(dot(normal, lightDir), 0.0f);
result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
float attenuation = 1.0f / (pointLight[idx].attenuation[3]
+ pointLight[idx].attenuation[2] * dis
+ pointLight[idx].attenuation[1] * dis * dis);
result *= attenuation * pointLight[idx].attenuation[0] + (1.0f - pointLight[idx].attenuation[0]);
return result * vec3(pointLight[idx].color);
}
vec3 calcSpotLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
vec3 lightDir = normalize(vec3(spotLight[idx].pos) - fragPos);
vec3 viewDir = normalize(vec3(viewPos) - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float dis = length(vec3(spotLight[idx].pos) - fragPos);
float theta = dot(lightDir, normalize(-vec3(spotLight[idx].direction)));
float intensity = (theta - spotLight[idx].cutOff[1]) / (spotLight[idx].cutOff[0] - spotLight[idx].cutOff[1]);
vec3 result = vec3(0.0f);
result += diff * color * max(dot(normal, lightDir), 0.0f);
result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
float attenuation = 1.0f / (spotLight[idx].attenuation[3]
+ spotLight[idx].attenuation[2] * dis
+ spotLight[idx].attenuation[1] * dis * dis);
result *= attenuation * spotLight[idx].attenuation[0] + (1.0f - spotLight[idx].attenuation[0]);
return result * vec3(spotLight[idx].color) * clamp(intensity, 0.0f, 1.0f);
}
void main() {
vec3 T = normalize(mat3(modelMat) * tangent);
vec3 B = normalize(mat3(modelMat) * bitangent);
vec3 N = normalize(mat3(normalMat) * normal);
fragPos = vec3(modelMat * vec4(position, 1.0f));
fragTexCoords = texCoords;
TBN = mat3(T, B, N);
mat4 MVP = projMat * viewMat * modelMat;
vec3 color = material.useDiffuseMap == 1 ? texture(diffuseMap, fragTexCoords).rgb : vec3(material.color);
float spec = material.useSpecularMap == 1 ? texture(specularMap, fragTexCoords).r : material.specular;
vec3 normal = material.useBumpMap == 1 ? texture(bumpMap, fragTexCoords).rgb * 2 - 1 : vec3(0, 0, 1);
normal = normalize(TBN * normalize(normal));
afragColor = vec4(0, 0, 0, 1);
for (int i = 0; i < ambientLightNum; i++)
afragColor += vec4(calcAmbientLight(i, color, material.ambient), 1);
for (int i = 0; i < directionalLightNum; i++)
afragColor += vec4(calcDirectionalLight(i, normal, color, material.diffuse, spec), 1);
for (int i = 0; i < pointLightNum; i++)
afragColor += vec4(calcPointLight(i, normal, color, material.diffuse, spec), 1);
for (int i = 0; i < spotLightNum; i++)
afragColor += vec4(calcSpotLight(i, normal, color, material.diffuse, spec), 1);
if (highlighted == 1)
afragColor += vec4(0.2, 0.2, 0.2, 0);
if (selected == 1)
afragColor += vec4(0, 0, 0.4, 0);
gl_Position = MVP * vec4(position, 1.0f);
if (sizeFixed == 1) {
float w = (MVP * vec4(0.0f, 0.0f, 0.0f, 1.0f)).w / 100;
gl_Position = MVP * vec4(position * w, 1.0f);
}
}
//Fragment Shader
out vec4 fragColor;
in vec4 afragColor;
void main() {
fragColor = afragColor;
}
我感觉vertex shader returns 颜色很深而且不做纹理贴图。
谢谢
顶点着色器只是按顶点执行。因此,只查找图元的顶点(角)纹理。顶点着色器的输出沿片段进行插值。您不能在顶点着色器中执行此算法。您需要在片段着色器中按片段执行此操作。
“Per Vertex Lighting”仅对恒定的漫射光有意义。在镜面高光和纹理贴图的情况下,光分布不是线性的,不能用线性插值法计算。 Per-vertex lighting只用于非常简单的光照模型,现在一般不用了。
我正在尝试使用 QOpenGLWindow 在 opengl 中通过纹理映射实现逐顶点照明。但是渲染的对象有黑色。如果我在片段着色器中做相同的纹理映射,它工作正常。
//Vertex Shader
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 tangent;
layout (location = 3) in vec3 bitangent;
layout (location = 4) in vec2 texCoords;
out vec4 afragColor;
vec3 fragPos;
out vec2 fragTexCoords;
mat3 TBN;
uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2D bumpMap;
vec3 calcAmbientLight(int idx, vec3 color, float ambient) {
return ambient * color * vec3(ambientLight[idx].color);
}
vec3 calcDirectionalLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
vec3 lightDir = normalize(-vec3(directionalLight[idx].direction));
vec3 viewDir = normalize(vec3(viewPos) - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
vec3 result = vec3(0.0f);
result += diff * color * max(dot(normal, lightDir), 0.0f);
result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
return result * vec3(directionalLight[idx].color);
}
vec3 calcPointLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
vec3 lightDir = normalize(vec3(pointLight[idx].pos) - fragPos);
vec3 viewDir = normalize(vec3(viewPos) - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float dis = length(vec3(pointLight[idx].pos) - fragPos);
vec3 result = vec3(0.0f);
result += diff * color * max(dot(normal, lightDir), 0.0f);
result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
float attenuation = 1.0f / (pointLight[idx].attenuation[3]
+ pointLight[idx].attenuation[2] * dis
+ pointLight[idx].attenuation[1] * dis * dis);
result *= attenuation * pointLight[idx].attenuation[0] + (1.0f - pointLight[idx].attenuation[0]);
return result * vec3(pointLight[idx].color);
}
vec3 calcSpotLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
vec3 lightDir = normalize(vec3(spotLight[idx].pos) - fragPos);
vec3 viewDir = normalize(vec3(viewPos) - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float dis = length(vec3(spotLight[idx].pos) - fragPos);
float theta = dot(lightDir, normalize(-vec3(spotLight[idx].direction)));
float intensity = (theta - spotLight[idx].cutOff[1]) / (spotLight[idx].cutOff[0] - spotLight[idx].cutOff[1]);
vec3 result = vec3(0.0f);
result += diff * color * max(dot(normal, lightDir), 0.0f);
result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
float attenuation = 1.0f / (spotLight[idx].attenuation[3]
+ spotLight[idx].attenuation[2] * dis
+ spotLight[idx].attenuation[1] * dis * dis);
result *= attenuation * spotLight[idx].attenuation[0] + (1.0f - spotLight[idx].attenuation[0]);
return result * vec3(spotLight[idx].color) * clamp(intensity, 0.0f, 1.0f);
}
void main() {
vec3 T = normalize(mat3(modelMat) * tangent);
vec3 B = normalize(mat3(modelMat) * bitangent);
vec3 N = normalize(mat3(normalMat) * normal);
fragPos = vec3(modelMat * vec4(position, 1.0f));
fragTexCoords = texCoords;
TBN = mat3(T, B, N);
mat4 MVP = projMat * viewMat * modelMat;
vec3 color = material.useDiffuseMap == 1 ? texture(diffuseMap, fragTexCoords).rgb : vec3(material.color);
float spec = material.useSpecularMap == 1 ? texture(specularMap, fragTexCoords).r : material.specular;
vec3 normal = material.useBumpMap == 1 ? texture(bumpMap, fragTexCoords).rgb * 2 - 1 : vec3(0, 0, 1);
normal = normalize(TBN * normalize(normal));
afragColor = vec4(0, 0, 0, 1);
for (int i = 0; i < ambientLightNum; i++)
afragColor += vec4(calcAmbientLight(i, color, material.ambient), 1);
for (int i = 0; i < directionalLightNum; i++)
afragColor += vec4(calcDirectionalLight(i, normal, color, material.diffuse, spec), 1);
for (int i = 0; i < pointLightNum; i++)
afragColor += vec4(calcPointLight(i, normal, color, material.diffuse, spec), 1);
for (int i = 0; i < spotLightNum; i++)
afragColor += vec4(calcSpotLight(i, normal, color, material.diffuse, spec), 1);
if (highlighted == 1)
afragColor += vec4(0.2, 0.2, 0.2, 0);
if (selected == 1)
afragColor += vec4(0, 0, 0.4, 0);
gl_Position = MVP * vec4(position, 1.0f);
if (sizeFixed == 1) {
float w = (MVP * vec4(0.0f, 0.0f, 0.0f, 1.0f)).w / 100;
gl_Position = MVP * vec4(position * w, 1.0f);
}
}
//Fragment Shader
out vec4 fragColor;
in vec4 afragColor;
void main() {
fragColor = afragColor;
}
我感觉vertex shader returns 颜色很深而且不做纹理贴图。 谢谢
顶点着色器只是按顶点执行。因此,只查找图元的顶点(角)纹理。顶点着色器的输出沿片段进行插值。您不能在顶点着色器中执行此算法。您需要在片段着色器中按片段执行此操作。
“Per Vertex Lighting”仅对恒定的漫射光有意义。在镜面高光和纹理贴图的情况下,光分布不是线性的,不能用线性插值法计算。 Per-vertex lighting只用于非常简单的光照模型,现在一般不用了。