镜面高光故障 OpenGL
Posted
技术标签:
【中文标题】镜面高光故障 OpenGL【英文标题】:Specular Highlight Glitch OpenGL 【发布时间】:2014-03-07 22:39:15 【问题描述】:我在渲染 Phong 或其他高光 BRDF 时遇到了这个问题。
我从搅拌机导入 OBJ。只有顶点。在我这样重新计算法线之后:
Vertex& v1 = _vertices[id1];
Vertex& v2 = _vertices[id2];
Vertex& v3 = _vertices[id3];
glm::vec3 edge1 = v2.position - v1.position;
glm::normalize(edge1);
glm::vec3 edge2 = v3.position - v1.position;
glm::normalize(edge2);
glm::vec3 normal = glm::cross(edge1, edge2);
if (normal != glm::vec3(0.0))
glm::normalize(normal);
TrianglePtr triangle(new Triangle);
triangle->normal = normal;
之后,我将顶点三角形中的所有法线相加。当我显示法线时,它们看起来还不错。
我在几何着色器阶段计算所有内容
VS:
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec3 tangent;
layout (location = 4) in vec2 uv;
layout (location = 0) out vec3 outNormal;
layout (location = 1) out vec3 outTangent;
layout (location = 2) out vec3 outBitangent;
layout (location = 3) out vec3 outColor;
layout (location = 4) out vec2 outUV;
out gl_PerVertex
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[];
;
void main()
outNormal = normalize(normal);
outTangent = normalize(tangent);
outBitangent = normalize(cross(normal, tangent));
outColor = color;
outUV = uv;
gl_Position = vec4(position, 1.0);
GS:
#version 430 core
layout(triangles, invocations = 1) in;
layout (triangle_strip, max_vertices = 3) out;
layout (location = 0) in vec3 normal[];
layout (location = 1) in vec3 tangent[];
layout (location = 2) in vec3 bitangent[];
layout (location = 3) in vec3 color[];
layout (location = 4) in vec2 uv[];
layout (location = 0) out vec3 outNormal;
layout (location = 1) out vec3 outTangent;
layout (location = 2) out vec3 outBitangent;
layout (location = 3) out vec3 outColor;
layout (location = 4) out vec2 outUv;
layout (location = 5) out vec3 lightDir;
layout (location = 6) out vec3 viewDir;
layout (std140, binding = 0) uniform WorldDataBlock
mat4 modelMatrix;
mat4 viewMatrix;
mat4 projectionMatrix;
mat4 normalMatrix;
worldData;
uniform vec3 lightPosition = vec3(100.0, 100.0, 100.0);
in gl_PerVertex
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[];
gl_in[];
out gl_PerVertex
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[];
;
void main()
mat4 MV = worldData.viewMatrix * worldData.modelMatrix;
mat4 MVP = worldData.projectionMatrix * MV;
for(int idx = 0; idx < gl_in.length(); ++idx)
outNormal = normalize(worldData.normalMatrix * vec4(normal[idx], 0.0)).xyz;
outTangent = normalize(mat3(worldData.normalMatrix) * tangent[idx]);
outBitangent = normalize(mat3(worldData.normalMatrix) * bitangent[idx]);
vec3 pos = (MV * gl_in[idx].gl_Position).xyz;
vec3 lightPos = (worldData.viewMatrix * vec4(lightPosition, 1.0)).xyz;
lightDir = normalize(lightPos - pos);
viewDir = normalize(-pos);
gl_Position = MVP * gl_in[idx].gl_Position;
EmitVertex();
EndPrimitive();
FS:(尝试 Dysney 材质着色器),与标准 Phong 的结果相同
float roughness = clamp(materialData.roughness, 0.0, 1.0);
float alpha = roughness * roughness;
float k = pow((roughness + 1.0), 2) / 8.0;
vec3 H = normalize(lightDir + viewDir);
float NdotV = max(dot(normal, viewDir), 0.0);
float NdotL = max(dot(normal, lightDir), 0.0);
float NdotH = max(dot(normal, H), 0.0);
float VdotH = max(dot(viewDir, H), 0.0);
float LdotH = max(dot(lightDir, H), 0.0);
float D = alpha * alpha / ( PI * pow((pow(NdotH, 2) * ( alpha * alpha - 1.0) + 1), 2));
float Gv = NdotV / (NdotV * (1.0 - k) + k);
float Gl = NdotL / (NdotL * (1.0 - k) + k);
float G = Gv * Gl;
float F0 = 0.5 + 2 * VdotH * VdotH * roughness;
float exponent = -5.55473 * VdotH - 6.98316 * VdotH;
float F = F0 + (1.0 - F0) * pow(2.0, exponent);
float denum = clamp(4.0 * NdotL * NdotV, EPSILON, 1.0);
return max(D * G * F / denum, 0.0);
有什么想法吗?
【问题讨论】:
【参考方案1】:故障是由于我的正常计算造成的。我只从 OBJ 导入顶点。我基本上使用叉积来计算法线以对三角形进行加权,但这还不够。所以我改进了在公式中添加角权重的微积分。 对于基本形状,我在我的程序中创建它而不是导入它们。所以我可以直接计算给定形状的法线。
【讨论】:
以上是关于镜面高光故障 OpenGL的主要内容,如果未能解决你的问题,请参考以下文章
Unity-Shader-镜面高光Phong&BlinnPhong-油腻的师姐在哪里
浅墨Unity3D Shader编程之十三 单色透明Shader & 标准镜面高光Shader