我正在尝试加载.mtl
文件来为OpenGL设置对象。我加载的对象来自Google的Poly库,所以我知道它们有效,我相信我的着色器脚本出了问题。我的出发点是Google ARCore示例object_fragment.shader上提供的着色器。由于并非所有mtls都使用纹理我添加了一个布尔值来告诉我是否使用纹理贴图,我还更改了材质属性以允许mtl传递rgb值而不是单个标量。结果如下:
precision mediump float;
uniform bool u_TextureValid;
uniform sampler2D u_Texture;
uniform vec4 u_LightingParameters;
uniform vec2 u_MaterialParameters;
uniform vec3 u_MaterialAmbientLighting;
uniform vec3 u_MaterialDiffuseLighting;
uniform vec3 u_MaterialSpecularLighting;
varying vec3 v_ViewPosition;
varying vec3 v_ViewNormal;
varying vec2 v_TexCoord;
void main() {
// We support approximate sRGB gamma.
const float kGamma = 0.4545454;
const float kInverseGamma = 2.2;
// Unpack lighting and material parameters for better naming.
vec3 viewLightDirection = u_LightingParameters.xyz;
float lightIntensity = u_LightingParameters.w;
float materialSpecularPower = u_MaterialParameters.x;
float materialAlpha = u_MaterialParameters.y;
vec3 materialDiffuse = u_MaterialDiffuseLighting;
vec3 materialSpecular = u_MaterialSpecularLighting;
// Normalize varying parameters, because they are linearly interpolated in the vertex shader.
vec3 viewFragmentDirection = normalize(v_ViewPosition);
vec3 viewNormal = normalize(v_ViewNormal);
// Apply inverse SRGB gamma to the texture before making lighting calculations.
// Flip the y-texture coordinate to address the texture from top-left.
vec4 objectColor;
if (u_TextureValid) {
objectColor = texture2D(u_Texture, vec2(v_TexCoord.x, 1.0 - v_TexCoord.y));
} else {
objectColor = vec4(1.0, 1.0, 1.0, 1.0);
}
objectColor.rgb = pow(objectColor.rgb, vec3(kInverseGamma));
// Ambient light is unaffected by the light intensity.
vec3 ambient = u_MaterialAmbientLighting;
// Approximate a hemisphere light (not a harsh directional light).
vec3 diffuse = lightIntensity * materialDiffuse *
0.5 * (dot(viewNormal, viewLightDirection) + 1.0);
// Compute specular light.
vec3 reflectedLightDirection = reflect(-viewLightDirection, viewNormal);
float specularStrength = max(0.0, dot(viewFragmentDirection, reflectedLightDirection));
vec3 specular = lightIntensity * materialSpecular *
pow(specularStrength, materialSpecularPower);
// Apply SRGB gamma before writing the fragment color.
gl_FragColor.a = objectColor.a * materialAlpha;
if (u_TextureValid) {
gl_FragColor.rgb = pow(objectColor.rgb + ambient + diffuse + specular, vec3(kGamma));
} else {
gl_FragColor.rgb = pow(objectColor.rgb * (ambient + diffuse) + specular, vec3(kGamma));
}
}
带有纹理的模型看起来看起来很正确,但只有Ka
和Ks
值的其他模型看起来太亮了。
这应该是这样的:https://poly.google.com/view/9086wpJW1vO
传递的所有参数均来自mtl
文件,但来自恒定光源方向的u_LightingParameters
和ARCore提供的光强度除外。
有没有人知道在计算片段颜色时我可能做错了什么?
更新
我已经修复了反射的计算但是颜色仍然太亮了,这个模型的材料是:
newmtl mat8
Ka 0.96 0.26 0.21
Kd 0.96 0.26 0.21
newmtl mat18
Ka 1.00 0.80 0.53
Kd 1.00 0.80 0.53
newmtl mat19
Ka 0.87 0.60 0.27
Kd 0.87 0.60 0.27
newmtl mat21
Ka 1.00 1.00 1.00
Kd 1.00 1.00 1.00
newmtl mat22
Ka 0.62 0.62 0.62
Kd 0.62 0.62 0.62
newmtl mat23
Ka 0.10 0.10 0.10
Kd 0.10 0.10 0.10
我目前的理论是,当材料中没有使用纹理贴图时,问题是我对基色的选择。
更新
我很难解释它,但如果我将u_MaterialDiffuseLighting
值作为gl_FragColor
并且没有其他内容(甚至不执行伽马校正)那么颜色看起来正确......谁能解释一下?