PlayCanvas PBR材质shader代码分析(pixel shader)

#version 300 es
#define varying in
out highp vec4 pc_fragColor;
#define gl_FragColor pc_fragColor
#define texture2D texture
#define textureCube texture
#define texture2DProj textureProj
#define texture2DLodEXT textureLod
#define texture2DProjLodEXT textureProjLod
#define textureCubeLodEXT textureLod
#define texture2DGradEXT textureGrad
#define texture2DProjGradEXT textureProjGrad
#define textureCubeGradEXT textureGrad
#define GL2
precision highp float;
#ifdef GL2
    precision highp sampler2DShadow;
#endif
varying vec3 vPositionW;
varying vec3 vNormalW;
uniform vec3 view_position;
uniform vec3 light_globalAmbient;
float square(float x) {
    return x*x;
}
float saturate(float x) {
    return clamp(x, 0.0, 1.0);
}
vec3 saturate(vec3 x) {
    return clamp(x, vec3(0.0), vec3(1.0));
}
vec4 dReflection;
vec3 dAlbedo;
vec3 dNormalW;
vec3 dVertexNormalW;
vec3 dViewDirW;
vec3 dReflDirW;
vec3 dDiffuseLight;
vec3 dSpecularLight;
vec3 dSpecularity;
float dGlossiness;
float dAlpha;
void getNormal() {
    dNormalW = normalize(dVertexNormalW);
}
vec3 gammaCorrectInput(vec3 color) {
    return pow(color, vec3(2.2));
}
float gammaCorrectInput(float color) {
    return pow(color, 2.2);
}
vec4 gammaCorrectInput(vec4 color) {
    return vec4(pow(color.rgb, vec3(2.2)), color.a);
}
vec4 texture2DSRGB(sampler2D tex, vec2 uv) {
    vec4 rgba = texture2D(tex, uv);
    rgba.rgb = gammaCorrectInput(rgba.rgb);
    return rgba;
}
vec4 texture2DSRGB(sampler2D tex, vec2 uv, float bias) {
    vec4 rgba = texture2D(tex, uv, bias);
    rgba.rgb = gammaCorrectInput(rgba.rgb);
    return rgba;
}
vec4 textureCubeSRGB(samplerCube tex, vec3 uvw) {
    vec4 rgba = textureCube(tex, uvw);
    rgba.rgb = gammaCorrectInput(rgba.rgb);
    return rgba;
}
vec3 gammaCorrectOutput(vec3 color) {
    #ifdef HDR
        return color;
    #else
        color += vec3(0.0000001);
        return pow(color, vec3(0.45));
    #endif
}
uniform float exposure;
// 线性toneMap整体颜色亮度调节
vec3 toneMap(vec3 color) {
    return color * exposure;
}
vec3 addFog(vec3 color) {
    return color;
}
// 这里RGBM解码是pc引擎专门修改过的 编码做了pow(0.5) 最大值调整为了8.0
vec3 decodeRGBM(vec4 rgbm) {
    vec3 color = (8.0 * rgbm.a) * rgbm.rgb;
    return color * color;
}
vec3 texture2DRGBM(sampler2D tex, vec2 uv) {
    return decodeRGBM(texture2D(tex, uv));
}
vec3 textureCubeRGBM(samplerCube tex, vec3 uvw) {
    return decodeRGBM(textureCube(tex, uvw));
}
vec3 fixSeams(vec3 vec, float mipmapIndex) {
    float scale = 1.0 - exp2(mipmapIndex) / 128.0;
    float M = max(max(abs(vec.x), abs(vec.y)), abs(vec.z));
    if (abs(vec.x) != M) vec.x *= scale;
    if (abs(vec.y) != M) vec.y *= scale;
    if (abs(vec.z) != M) vec.z *= scale;
    return vec;
}
vec3 fixSeams(vec3 vec) {
    float scale = 1.0 - 1.0 / 128.0;
    float M = max(max(abs(vec.x), abs(vec.y)), abs(vec.z));
    if (abs(vec.x) != M) vec.x *= scale;
    if (abs(vec.y) != M) vec.y *= scale;
    if (abs(vec.z) != M) vec.z *= scale;
    return vec;
}
vec3 fixSeamsStatic(vec3 vec, float invRecMipSize) {
    float scale = invRecMipSize;
    float M = max(max(abs(vec.x), abs(vec.y)), abs(vec.z));
    if (abs(vec.x) != M) vec.x *= scale;
    if (abs(vec.y) != M) vec.y *= scale;
    if (abs(vec.z) != M) vec.z *= scale;
    return vec;
}
vec3 cubeMapProject(vec3 dir) {
    return dir;
}
vec3 processEnvironment(vec3 color) {
    return color;
}
#undef MAPFLOAT

#undef MAPCOLOR

#undef MAPVERTEX

#undef MAPTEXTURE
#ifdef MAPCOLOR
    uniform vec3 material_diffuse;
#endif
#ifdef MAPTEXTURE
    uniform sampler2D texture_diffuseMap;
#endif
// 获取基础色
void getAlbedo() {
    dAlbedo = vec3(1.0);
    #ifdef MAPCOLOR
        dAlbedo *= material_diffuse.rgb;
    #endif
    #ifdef MAPTEXTURE
        dAlbedo *= texture2DSRGB(texture_diffuseMap, UV).CH;
    #endif
    #ifdef MAPVERTEX
        dAlbedo *= gammaCorrectInput(saturate(vVertexColor.VC));
    #endif
}
#undef MAPFLOAT

#undef MAPCOLOR
#define MAPCOLOR

#undef MAPVERTEX

#undef MAPTEXTURE
#ifdef MAPCOLOR
    uniform vec3 material_emissive;
#endif
#ifdef MAPFLOAT
    uniform float material_emissiveIntensity;
#endif
#ifdef MAPTEXTURE
    uniform sampler2D texture_emissiveMap;
#endif
// 获取自发光颜色
vec3 getEmission() {
    vec3 emission = vec3(1.0);
    #ifdef MAPFLOAT
        emission *= material_emissiveIntensity;
    #endif
    #ifdef MAPCOLOR
        emission *= material_emissive;
    #endif
    #ifdef MAPTEXTURE
        emission *= texture2DSAMPLE(texture_emissiveMap, UV).CH;
    #endif
    #ifdef MAPVERTEX
        emission *= gammaCorrectInput(saturate(vVertexColor.VC));
    #endif
    return emission;
}
float antiAliasGlossiness(float power) {
    return power;
}
#undef MAPFLOAT
#define MAPFLOAT

#undef MAPCOLOR

#undef MAPVERTEX

#undef MAPTEXTURE
// 通过金属性计算各个颜色通道镜面反射强度系数,调整基础色颜色亮度
void processMetalness(float metalness) {
    const float dielectricF0 = 0.04;
    dSpecularity = mix(vec3(dielectricF0), dAlbedo, metalness);
    dAlbedo *= 1.0 - metalness;
}
#ifdef MAPFLOAT
    uniform float material_metalness;
#endif
#ifdef MAPTEXTURE
    uniform sampler2D texture_metalnessMap;
#endif
// 获取镜面反射强度系数
void getSpecularity() {
    float metalness = 1.0;
    #ifdef MAPFLOAT
        metalness *= material_metalness;
    #endif
    #ifdef MAPTEXTURE
        metalness *= texture2D(texture_metalnessMap, UV).CH;
    #endif
    #ifdef MAPVERTEX
        metalness *= saturate(vVertexColor.VC);
    #endif
    processMetalness(metalness);
}
#undef MAPFLOAT
#define MAPFLOAT

#undef MAPCOLOR

#undef MAPVERTEX

#undef MAPTEXTURE
#ifdef MAPFLOAT
    uniform float material_shininess;
#endif
#ifdef MAPTEXTURE
    uniform sampler2D texture_glossMap;
#endif
// 计算光泽度
void getGlossiness() {
    dGlossiness = 1.0;
    #ifdef MAPFLOAT
        dGlossiness *= material_shininess;
    #endif
    #ifdef MAPTEXTURE
        dGlossiness *= texture2D(texture_glossMap, UV).CH;
    #endif
    #ifdef MAPVERTEX
        dGlossiness *= saturate(vVertexColor.VC);
    #endif
    dGlossiness += 0.0000001;
}
// Schlick's approximation
uniform float material_fresnelFactor; // unused
// 计算菲尼尔系数并且调整镜面反射系数
void getFresnel() {
    float fresnel = 1.0 - max(dot(dNormalW, dViewDirW), 0.0);
    float fresnel2 = fresnel * fresnel;
    fresnel *= fresnel2 * fresnel2;
    fresnel *= dGlossiness * dGlossiness;
    dSpecularity = dSpecularity + (1.0 - dSpecularity) * fresnel;
}
#ifndef PMREM4
    #define PMREM4
    uniform samplerCube texture_prefilteredCubeMap128;
#endif
uniform float material_reflectivity;
// 添加ibl全局光镜面反射颜色
void addReflection() {
    float bias = saturate(1.0 - dGlossiness) * 5.0; // multiply by max mip level
    
    #ifdef ENABLE_ENVROT
        vec3 fixedReflDir = fixSeams(cubeMapProject(environmentRotate(dReflDirW)), bias);
    #else
        vec3 fixedReflDir = fixSeams(cubeMapProject(dReflDirW), bias);
    #endif
    fixedReflDir.x *= -1.0;
    vec3 refl = processEnvironment(decodeRGBM( textureCubeLodEXT(texture_prefilteredCubeMap128, fixedReflDir, bias) ).rgb);
    dReflection += vec4(refl, material_reflectivity);
}
// 漫反射 * 基础色 * (1.0 - 镜面反射强度) + (镜面反射 + 环境反射) * 镜面反射强度
// 这里漫反射包含了直接光+ibl全局光
vec3 combineColor() {
    return mix(dAlbedo * dDiffuseLight, dSpecularLight + dReflection.rgb * dReflection.a, dSpecularity);
}
#ifndef PMREM4
    #define PMREM4
    uniform samplerCube texture_prefilteredCubeMap128;
#endif

// 获取ibl全局光漫反射颜色
void addAmbient() {
    #ifdef ENABLE_ENVROT
        vec3 fixedReflDir = fixSeamsStatic(environmentRotate(dNormalW), 1.0 - 1.0 / 4.0);
    #else
        vec3 fixedReflDir = fixSeamsStatic(dNormalW, 1.0 - 1.0 / 4.0);
    #endif
    fixedReflDir.x *= -1.0;
    dDiffuseLight += processEnvironment(decodeRGBM( textureCubeLodEXT(texture_prefilteredCubeMap128, fixedReflDir, 5.0) ).rgb);
}
// 获取V向量
void getViewDir() {
    dViewDirW = normalize(view_position - vPositionW);
}
// 获取R向量
void getReflDir() {
    dReflDirW = normalize(-reflect(dViewDirW, dNormalW));
}
void main(void) {
    // 漫反射颜色
    dDiffuseLight = vec3(0);
    // 镜面反射颜色
    dSpecularLight = vec3(0);
    // ibl全局环境反射
    dReflection = vec4(0);
    // 镜面反射强度系数
    dSpecularity = vec3(0);
    // 顶点世界空间法线
    dVertexNormalW = vNormalW;
    dAlpha = 1.0;
    getViewDir();// 计算 view - pos
    getNormal();// 计算世界空间法线
    getReflDir();// 计算反射方向
    getAlbedo();// 计算基础色,一般走diffuseMap、顶点颜色、材质diffuse颜色直接取出
    getSpecularity();// 计算镜面反射强度系数, 镜面反射强度通过金属性系数来计算,金属性越强反射强度越大漫反射越弱,金属性越弱反射强度越小漫反射颜色越强,从而漫反射和镜面反射遵循能量守恒
    getGlossiness();// 计算光泽度(相当于粗糙度的相反叫法) 通过外部给材质设定系数或者走光泽度贴图获取
    getFresnel();  // 计算菲尼尔效果
    addAmbient(); // 计算环境光颜色(间接光漫反射颜色)
    addReflection(); // 计算环境光反射(间接光镜面高光颜色)
    gl_FragColor.rgb = combineColor(); // 组合漫反射、基础色、镜面反射输出颜色
    gl_FragColor.rgb += getEmission(); // 累加自发光颜色
    gl_FragColor.rgb = addFog(gl_FragColor.rgb); // 雾化效果计算
    #ifndef HDR
        gl_FragColor.rgb = toneMap(gl_FragColor.rgb); // tonemap计算
        gl_FragColor.rgb = gammaCorrectOutput(gl_FragColor.rgb);// gamma矫正回到gama颜色空间
    #endif
    gl_FragColor.a = 1.0;
}

猜你喜欢

转载自www.cnblogs.com/zzatp/p/11497020.html