如何使用像素着色器渲染Wavefront Obj文件中的材质
MTL材质参数在像素着色器的使用方法
核心参数定义
首先明确Blender导出MTL文件中四类参数的作用:
- Ambient(环境光颜色):材质对场景间接环境光的反射系数,属于无方向的基础光照贡献,不受光源角度影响
- Diffuse(漫反射颜色):材质对直射光源的漫反射系数,反射光线均匀向各方向发散,亮度仅和光源与表面法线的夹角相关
- Specular(高光颜色):材质对直射光源的镜面反射系数,对应表面光滑度带来的高光区域亮度,和视线、反射光线的夹角相关
- Emissive(自发光颜色):材质本身主动发射的颜色,不需要依赖外部光照即可显示的亮度
基础实现逻辑
一般使用经典Blinn-Phong光照模型整合四类参数,计算逻辑为:
最终片元颜色 = 自发光贡献 + 环境光贡献 + 所有光源的漫反射贡献总和 + 所有光源的高光贡献总和
如果MTL文件附带对应纹理,需要先将纹理采样结果和对应系数相乘后再参与计算。
像素着色器代码示例(GLSL)
#version 330 core // 顶点着色器传入的插值数据 in vec3 FragPos; // 片元世界空间位置 in vec3 Normal; // 片元法线 in vec2 TexCoords; // 纹理坐标 // 从MTL文件读取的材质参数 struct Material { vec3 ambient; vec3 diffuse; vec3 specular; vec3 emissive; float shininess; // 对应MTL的Ns参数,值越高高光范围越小 // 存在对应纹理时添加采样器,无纹理可删除 sampler2D diffuseTex; sampler2D specularTex; }; // 单一点光源参数示例,多光源可扩展为数组 struct Light { vec3 position; vec3 ambientColor; // 场景全局环境光颜色 vec3 diffuseColor; // 光源直射光颜色 vec3 specularColor; // 光源高光颜色 }; out vec4 FragColor; uniform Material material; uniform Light light; uniform vec3 viewPos; // 相机世界空间位置 void main() { // 1. 自发光贡献 vec3 emissive = material.emissive; // 2. 环境光贡献 vec3 ambient = light.ambientColor * material.ambient; // 带漫反射纹理时替换为: // vec3 ambient = light.ambientColor * texture(material.diffuseTex, TexCoords).rgb * material.ambient; // 3. 漫反射贡献 vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = light.diffuseColor * diff * material.diffuse; // 带漫反射纹理时替换为: // vec3 diffuse = light.diffuseColor * diff * texture(material.diffuseTex, TexCoords).rgb * material.diffuse; // 4. 高光贡献 vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); vec3 specular = light.specularColor * spec * material.specular; // 带高光纹理时替换为: // vec3 specular = light.specularColor * spec * texture(material.specularTex, TexCoords).rgb * material.specular; // 汇总得到最终颜色 vec3 result = emissive + ambient + diffuse + specular; FragColor = vec4(result, 1.0); }
适配提示
- Blender导出MTL时默认Ambient参数和Diffuse参数一致,若场景无单独环境光配置,可以直接合并两类参数的计算,减少性能消耗
- 不需要自发光效果时直接将
material.emissive设为vec3(0)即可,不影响其他光照计算 - 多光源场景下,仅需对每个光源单独计算漫反射、高光贡献后累加,再叠加全局环境光和自发光即可
内容的提问来源于stack exchange,提问作者Rafael Ferreira
相关产品推荐
相关产品推荐

