OpenGL ES 2.0/3.0 中的各向异性照明。黑色文物
Anisotropic lighting in OpenGL ES 2.0/3.0. Black artifacts
我正在尝试实现各向异性照明。
顶点着色器:
#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec3 a_normal;
...
out lowp float v_DiffuseIntensity;
out lowp float v_SpecularIntensity;
const vec3 lightPosition = vec3(-1.0, 0.0, 5.0);
const lowp vec3 grainDirection = vec3(15.0, 2.8, -1.0);
const vec3 eye_positiion = vec3(0.0, 0.0, 0.0);
void main() {
// transform normal orientation into eye space
vec3 modelViewNormal = mat3(u_mvMatrix) * a_normal;
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
vec3 lightVector = normalize(lightPosition - modelViewVertex);
lightVector = mat3(u_vMatrix) * lightVector;
vec3 normalGrain = cross(modelViewNormal, grainDirection);
vec3 tangent = normalize(cross(normalGrain, modelViewNormal));
float LdotT = dot(tangent, normalize(lightVector));
float VdotT = dot(tangent, normalize(mat3(u_mvMatrix) * eye_position));
float NdotL = sqrt(1.0 - pow(LdotT, 2.0));
float VdotR = NdotL * sqrt(1.0 - pow(VdotT, 2.0)) - VdotT * LdotT;
v_DiffuseIntensity = max(NdotL * 0.4 + 0.6, 0.0);
v_SpecularIntensity = max(pow(VdotR, 2.0) * 0.9, 0.0);
...
}
片段着色器:
...
in lowp float v_DiffuseIntensity;
in lowp float v_SpecularIntensity;
const lowp vec3 default_color = vec3(0.1, 0.7, 0.9);
void main() {
...
lowp vec3 resultColor = (default_color * v_DiffuseIntensity)
+ v_SpecularIntensity;
outColor = vec4(resultColor, 1.0);
}
总的来说,灯光在不同的设备上效果很好。但是在SAMSUNG平板上出现了神器,如图:
似乎最黑暗的地方已经完全黑了。谁能建议为什么会这样?感谢任何 answer/comment!
你有几个表达式有未定义行为的风险:
sqrt(1.0 - pow(LdotT, 2.0))
sqrt(1.0 - pow(VdotT, 2.0))
如果 x 为负,则 pow
函数未定义。我怀疑你逃脱了这个因为 y 是 2.0 所以他们可能被优化为 x * x.
如果 x 为负,则 sqrt
函数未定义。在数学上它永远不应该是因为两个归一化向量的点积的大小永远不会超过 1,但计算总是有错误。我认为这是造成您的渲染瑕疵的原因。
我会将这两个表达式更改为:
sqrt(max(0.0, 1.0 - pow(max(0.0, LdotT), 2.0)))
sqrt(max(0.0, 1.0 - pow(max(0.0, VdotT), 2.0)))
代码看起来更丑陋,但它更安全,max(0.0, x)
是一个相当便宜的操作。
编辑:刚注意到 pow(VdotR, 2.0)
,我也会更改它。
我正在尝试实现各向异性照明。 顶点着色器:
#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec3 a_normal;
...
out lowp float v_DiffuseIntensity;
out lowp float v_SpecularIntensity;
const vec3 lightPosition = vec3(-1.0, 0.0, 5.0);
const lowp vec3 grainDirection = vec3(15.0, 2.8, -1.0);
const vec3 eye_positiion = vec3(0.0, 0.0, 0.0);
void main() {
// transform normal orientation into eye space
vec3 modelViewNormal = mat3(u_mvMatrix) * a_normal;
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
vec3 lightVector = normalize(lightPosition - modelViewVertex);
lightVector = mat3(u_vMatrix) * lightVector;
vec3 normalGrain = cross(modelViewNormal, grainDirection);
vec3 tangent = normalize(cross(normalGrain, modelViewNormal));
float LdotT = dot(tangent, normalize(lightVector));
float VdotT = dot(tangent, normalize(mat3(u_mvMatrix) * eye_position));
float NdotL = sqrt(1.0 - pow(LdotT, 2.0));
float VdotR = NdotL * sqrt(1.0 - pow(VdotT, 2.0)) - VdotT * LdotT;
v_DiffuseIntensity = max(NdotL * 0.4 + 0.6, 0.0);
v_SpecularIntensity = max(pow(VdotR, 2.0) * 0.9, 0.0);
...
}
片段着色器:
...
in lowp float v_DiffuseIntensity;
in lowp float v_SpecularIntensity;
const lowp vec3 default_color = vec3(0.1, 0.7, 0.9);
void main() {
...
lowp vec3 resultColor = (default_color * v_DiffuseIntensity)
+ v_SpecularIntensity;
outColor = vec4(resultColor, 1.0);
}
总的来说,灯光在不同的设备上效果很好。但是在SAMSUNG平板上出现了神器,如图:
似乎最黑暗的地方已经完全黑了。谁能建议为什么会这样?感谢任何 answer/comment!
你有几个表达式有未定义行为的风险:
sqrt(1.0 - pow(LdotT, 2.0))
sqrt(1.0 - pow(VdotT, 2.0))
如果 x 为负,则 pow
函数未定义。我怀疑你逃脱了这个因为 y 是 2.0 所以他们可能被优化为 x * x.
如果 x 为负,则 sqrt
函数未定义。在数学上它永远不应该是因为两个归一化向量的点积的大小永远不会超过 1,但计算总是有错误。我认为这是造成您的渲染瑕疵的原因。
我会将这两个表达式更改为:
sqrt(max(0.0, 1.0 - pow(max(0.0, LdotT), 2.0)))
sqrt(max(0.0, 1.0 - pow(max(0.0, VdotT), 2.0)))
代码看起来更丑陋,但它更安全,max(0.0, x)
是一个相当便宜的操作。
编辑:刚注意到 pow(VdotR, 2.0)
,我也会更改它。