• Making the original
  • Let’s go straight to Shader
  • It’s confusing to see something else

Vertex shader

  • It’s basically computing normal vectors
#define USE_MATHS 1
#define USE_IBL 1
#define HAS_UV 1
#define HAS_NORMALS 1
#define HAS_TANGENTS 1
#define HAS_BASECOLORMAP 1
#define HAS_METALROUGHNESSMAP 1
#define HAS_NORMALMAP 1
#define HAS_OCCLUSIONMAP 1
#define USE_TEX_LOD 1
attribute vec4 a_Position; // Write vec4 with only three inputs. The last one defaults to 1.0?
#ifdef HAS_NORMALS
    attribute vec4 a_Normal;
#endif
#ifdef HAS_TANGENTS
    attribute vec4 a_Tangent;
#endif
#ifdef HAS_UV
    attribute vec2 a_UV;
#endif

uniform mat4 u_mvpMatrix;
uniform mat4 u_NormalMatrix;
varying vec3 v_Position;
varying vec2 v_UV;
#ifdef HAS_NORMALS
    #ifdef HAS_TANGENTS
        varying mat3 v_TBN;
    #else
        varying vec3 v_Normal;
    #endif
#endif

void main() {
    //u_NormalMatrix is the model matrix
    vec4 pos = u_NormalMatrix * a_Position;
    v_Position = vec3(pos.xyz) / pos.w;
    #ifdef HAS_NORMALS
        #ifdef HAS_TANGENTS
            vec3 normalW = normalize(vec3(u_NormalMatrix * vec4(a_Normal.xyz, 0.0)));
            vec3 tangentW = normalize(vec3(u_NormalMatrix * vec4(a_Tangent.xyz, 0.0)));
            vec3 bitangentW = cross(normalW, tangentW) * a_Tangent.w; //*w is not what I expected
            v_TBN = mat3(tangentW, bitangentW, normalW); //TBN
        #else // HAS_TANGENTS ! = 1
            v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));
        #endif
    #endif
    
    gl_Position = u_mvpMatrix * a_Position; // needs w for proper perspective correction
}
Copy the code

Chip shader

IBL map

#ifdef USE_IBL
    uniform samplerCube u_DiffuseEnvSampler;
    uniform samplerCube u_SpecularEnvSampler; // There are 60 cards in it
    uniform sampler2D u_brdfLUT;
#endif
Copy the code
  • U_DiffuseEnvSampler six

  • U_SpecularEnvSampler has 60 specularenvroughness levels

  • U_brdfLUT is a

Normal vector calculation

#ifndef HAS_TANGENTS
    vec3 pos_dx = dFdx(v_Position);
    vec3 pos_dy = dFdy(v_Position);
    vec3 tex_dx = dFdx(vec3(v_UV, 0.0));
    vec3 tex_dy = dFdy(vec3(v_UV, 0.0));
    vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
    #ifdef HAS_NORMALS
        vec3 ng = normalize(v_Normal);
    #else
        vec3 ng = cross(pos_dx, pos_dy);
    #endif

    t = normalize(t - ng * dot(ng, t));
    vec3 b = normalize(cross(ng, t));
    mat3 tbn = mat3(t, b, ng);
#else // HAS_TANGENTS && HAS_NORMALS
    mat3 tbn = v_TBN;
#endif
Copy the code
#ifdef HAS_NORMALMAP
    vec3 n = texture2D(u_NormalSampler, v_UV).rgb; / / [0 ~ 1]
    n = normalize(tbn * (2.0 * n - 1.0)); / / [1 ~ 1]
#else
    vec3 n = tbn[2].xyz;
#endif
Copy the code

You know the vectors and the angles between them

vec3 v = normalize(u_Camera - v_Position); //view 
vec3 l = normalize(u_LightDirection);      //light
vec3 h = normalize(l+v);                   //half
vec3 reflection = -normalize(reflect(v, n)); // reflection
float NdotL = clamp(dot(n, l), 0.0.1.0);  
float NdotV = clamp(dot(n, v), 0.0.1.0);
float NdotH = clamp(dot(n, h), 0.0.1.0);
float LdotH = clamp(dot(l, h), 0.0.1.0);
float VdotH = clamp(dot(v, h), 0.0.1.0);
Copy the code

Metallicity/roughness

  • Metal (only 0 and 1)

  • roughness

#ifdef HAS_METALROUGHNESSMAP
    vec4 mrSample = texture2D(u_MetallicRoughnessSampler, v_UV);
    float roughness = clamp(mrSample.g, 0.04.1.0);
    float metallic = clamp(mrSample.b, 0.0.1.0);
#else
    float roughness = clamp(u_MetallicRoughnessValues.y, 0.04.1.0);
    float metallic = u_MetallicRoughnessValues.x;
#endif
Copy the code

BaseColor

#ifdef HAS_BASECOLORMAP
    vec3 baseColor = texture2D(u_BaseColorSampler, v_UV).rgb;
#else
    vec3 baseColor = vec3(1.0.1.0.1.0);
#endif
Copy the code

F0 and I don’t know how these two colors work out, right

vec3 f0 = vec3(0.04);
vec3 diffuseColor = mix(baseColor.rgb * (1.0 - f0), vec3(0..0..0.), metallic); // Metallicity to calculate diffuse
vec3 specularColor = mix(f0, baseColor, metallic); //F0 is related to specular.
Copy the code

What is the purpose of calculating the reflection coefficient of 90

float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
float reflectance90 = clamp(reflectance * 25.0.0.0.1.0);
Copy the code

Plug in F0, what’s R90

vec3 specularEnvironmentR0 = specularColor.rgb; F0 = mix(F0, albedo, metallic);
vec3 specularEnvironmentR90 = vec3(1.0.1.0.1.0) * reflectance90;
Copy the code

PBRinfo

struct PBRInfo {
    float NdotL;
    float NdotV;
    float NdotH;
    float LdotH;
    float VdotH;
    float roughness;
    float metalness;
    vec3 baseColor;
    vec3 reflectance0;  / / specularEnvironmentR0 is F0
    vec3 reflectance90; //specularEnvironmentR90
};
Copy the code

Calculate Fresnel F

vec3 fresnelSchlick2(PBRInfo pbrInputs) {
    return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0.1.0), 5.0);
}
Copy the code

Calculate GGX

float SmithVisibilityGGX(PBRInfo pbrInputs) {
    return SmithVisibilityG1_var2(pbrInputs.NdotL, pbrInputs.roughness) * SmithVisibilityG1_var2(pbrInputs.NdotV, pbrInputs.roughness);
}
float SmithVisibilityG1_var2(float NdotV, float r) {
    float tanSquared = (1.0 - NdotV * NdotV) / max((NdotV * NdotV), 0.00001);
    return 2.0 / (1.0 + sqrt(1.0 + r * r * tanSquared));
}
Copy the code

Calculate D

float GGX(PBRInfo pbrInputs) {
    float roughnessSq = pbrInputs.roughness*pbrInputs.roughness;
    float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
    return roughnessSq / (M_PI * f * f);
}
Copy the code

Calculate the diffuse part of direct illumination

vec3 diffuseContrib = (1.0 - F) * lambertianDiffuse(pbrInputs) * NdotL * u_LightColor;
vec3 lambertianDiffuse(PBRInfo pbrInputs) {
    return pbrInputs.baseColor / M_PI;
}
Copy the code

Calculate the specular reflection of direct illumination

vec3 specContrib = M_PI * u_LightColor * F * G * D / 4.0*NdotL*NdotV;
Copy the code

Direct illumination BRDF is calculated

vec3 color = (diffuseContrib + specContrib);
Copy the code

Calculate BRDF of indirect illumination and see the formula below

  • finalColor = (diffuseLight + diffuseColor) + (specularLight * (specularColor * brdf.x + brdf.y))
#ifdef USE_IBL
    float mipCount = 9.0; // Resolution of 512x512 //10 order roughness
    float lod = (roughness * mipCount);      // LoD range [0-9]
    vec3 brdf = texture2D(u_brdfLUT, vec2(NdotV, 1.0 - roughness)).rgb;  //brdf
    vec3 diffuseLight = textureCube(u_DiffuseEnvSampler, n).rgb;  / / the ambient light
    #ifdef USE_TEX_LOD
        vec3 specularLight = textureCubeLodEXT(u_SpecularEnvSampler, reflection, lod).rgb;  Reflection is the roughness directed by reflection
    #else
        vec3 specularLight = textureCube(u_SpecularEnvSampler, reflection).rgb; ///
    #endif

    vec3 IBLcolor = (diffuseLight * diffuseColor * u_scaleIBLAmbient.x) + (specularLight * (specularColor * brdf.x + brdf.y) *u_scaleIBLAmbient.y);
    color += IBLcolor; / / plus the IBL
#endif
Copy the code

The ao map

#ifdef HAS_OCCLUSIONMAP
    float ao = texture2D(u_OcclusionSampler, v_UV).r; //r
    color *= ao;  / / multiplied
#endif
Copy the code

Self-illumination map

#ifdef HAS_EMISSIVEMAP
    vec3 emissive = texture2D(u_EmissiveSampler, v_UV).rgb;
    color += emissive;  // Add it directly
#endif
Copy the code

#define USE_MATHS 1
#define USE_IBL 1
#define HAS_UV 1
#define HAS_NORMALS 1
#define HAS_TANGENTS 1
#define HAS_BASECOLORMAP 1
#define HAS_METALROUGHNESSMAP 1
#define HAS_NORMALMAP 1
#define HAS_EMISSIVEMAP 1
#define HAS_OCCLUSIONMAP 1
#define USE_TEX_LOD 1
#extension GL_EXT_shader_texture_lod: enable
#extension GL_OES_standard_derivatives : enable

precision highp float;
uniform vec3 u_LightDirection;
uniform vec3 u_LightColor;
#ifdef USE_IBL
    uniform samplerCube u_DiffuseEnvSampler;
    uniform samplerCube u_SpecularEnvSampler;
    uniform sampler2D u_brdfLUT;
#endif

#ifdef HAS_BASECOLORMAP
    uniform sampler2D u_BaseColorSampler;
#endif
#ifdef HAS_NORMALMAP
    uniform sampler2D u_NormalSampler;
#endif
#ifdef HAS_EMISSIVEMAP
    uniform sampler2D u_EmissiveSampler;
#endif
#ifdef HAS_METALROUGHNESSMAP
    uniform sampler2D u_MetallicRoughnessSampler;
#else
    uniform vec2 u_MetallicRoughnessValues;
#endif
#ifdef HAS_OCCLUSIONMAP
    uniform sampler2D u_OcclusionSampler;
#endif

uniform vec3 u_Camera;
uniform vec4 u_scaleDiffBaseMR;
uniform vec4 u_scaleFGDSpec;
uniform vec4 u_scaleIBLAmbient;
varying vec3 v_Position;
varying vec2 v_UV;
#ifdef HAS_NORMALS
    #ifdef HAS_TANGENTS
        varying mat3 v_TBN;
    #else
        varying vec3 v_Normal;
    #endif
#endif

struct PBRInfo {
    float NdotL;
    float NdotV;
    float NdotH;
    float LdotH;
    float VdotH;
    float roughness;
    float metalness;
    vec3 baseColor;
    vec3 reflectance0;
    vec3 reflectance90;
};
const float M_PI = 3.141592653589793;

// diffuse

vec3 disneyDiffuse(PBRInfo pbrInputs) {
    float f90 = 2.*pbrInputs.LdotH*pbrInputs.LdotH*pbrInputs.roughness - 0.5;
    return (pbrInputs.baseColor/M_PI)*(1.0+f90*pow((1.0-pbrInputs.NdotL), 5.0)) * (1.0+f90*pow((1.0-pbrInputs.NdotV), 5.0));
}
vec3 lambertianDiffuse(PBRInfo pbrInputs) {
    return pbrInputs.baseColor / M_PI;
}
// F
// r
vec3 fresnelSchlick2(PBRInfo pbrInputs) {
    return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0.1.0), 5.0);
}
vec3 fresnelSchlick(PBRInfo pbrInputs) {
    return pbrInputs.metalness + (vec3(1.0) - pbrInputs.metalness) * pow(1.0 - pbrInputs.VdotH, 5.0);
}
// G
float microfacetCookTorrance(PBRInfo pbrInputs) {
    return min(min(2.*pbrInputs.NdotV*pbrInputs.NdotH/pbrInputs.VdotH, 2.*pbrInputs.NdotL*pbrInputs.NdotH/pbrInputs.VdotH), 1.0);
}
float microfacetSchlick(PBRInfo pbrInputs) {
    float k = pbrInputs.roughness * 0.79788; / / 0.79788 = SQRT (2.0/3.1415);
    
    // alternately, k can be defined with
    // float k = (pbrInputs.roughness + 1)*(pbrInputs.roughness + 1)/8;
    
    float l = pbrInputs.LdotH / (pbrInputs.LdotH * (1.0 - k) + k);
    float n = pbrInputs.NdotH / (pbrInputs.NdotH * (1.0 - k) + k);
    return l * n;
}
float microfacetSmith_var1(PBRInfo pbrInputs) {
    float NdotL2 = pbrInputs.NdotL * pbrInputs.NdotL;
    float NdotV2 = pbrInputs.NdotV * pbrInputs.NdotV;
    float v = ( 1. + sqrt ( pbrInputs.roughness * (1. - NdotL2 ) / NdotL2 + 1.)) * 0.5;
    float l = ( 1. + sqrt ( pbrInputs.roughness * (1. - NdotV2 ) / NdotV2 + 1.)) * 0.5;
    return (1. / max((1. + v + l ), 0.000001));
}
float SmithVisibilityG1_var2(float NdotV, float r) {
    float tanSquared = (1.0 - NdotV * NdotV) / max((NdotV * NdotV), 0.00001);
    return 2.0 / (1.0 + sqrt(1.0 + r * r * tanSquared));
}
float SmithG1(float NdotV, float r) {
    return 2.0 * NdotV / (NdotV + sqrt(r*r+(1.0-r*r)*(NdotV*NdotV)));
}
float SmithVisibilityGGX(PBRInfo pbrInputs) {
    return SmithVisibilityG1_var2(pbrInputs.NdotL, pbrInputs.roughness) * SmithVisibilityG1_var2(pbrInputs.NdotV, pbrInputs.roughness);
}
// D
float GGX(PBRInfo pbrInputs) {
    float roughnessSq = pbrInputs.roughness*pbrInputs.roughness;
    float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
    return roughnessSq / (M_PI * f * f);
}
void main() {
    // Normal Map
    #ifndef HAS_TANGENTS
        vec3 pos_dx = dFdx(v_Position);
        vec3 pos_dy = dFdy(v_Position);
        vec3 tex_dx = dFdx(vec3(v_UV, 0.0));
        vec3 tex_dy = dFdy(vec3(v_UV, 0.0));
        vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
        #ifdef HAS_NORMALS
            vec3 ng = normalize(v_Normal);
        #else
            vec3 ng = cross(pos_dx, pos_dy);
        #endif
        
        t = normalize(t - ng * dot(ng, t));
        vec3 b = normalize(cross(ng, t));
        mat3 tbn = mat3(t, b, ng);
    #else // HAS_TANGENTS && HAS_NORMALS
        mat3 tbn = v_TBN;
    #endif
    
    #ifdef HAS_NORMALMAP
        vec3 n = texture2D(u_NormalSampler, v_UV).rgb;
        n = normalize(tbn * (2.0 * n - 1.0));
    #else
        vec3 n = tbn[2].xyz;
    #endif
    
    vec3 v = normalize(u_Camera - v_Position);
    vec3 l = normalize(u_LightDirection);
    vec3 h = normalize(l+v);
    vec3 reflection = -normalize(reflect(v, n));
    float NdotL = clamp(dot(n, l), 0.0.1.0);
    float NdotV = clamp(dot(n, v), 0.0.1.0);
    float NdotH = clamp(dot(n, h), 0.0.1.0);
    float LdotH = clamp(dot(l, h), 0.0.1.0);
    float VdotH = clamp(dot(v, h), 0.0.1.0);
    #ifdef HAS_METALROUGHNESSMAP
        vec4 mrSample = texture2D(u_MetallicRoughnessSampler, v_UV);
        float roughness = clamp(mrSample.g, 0.04.1.0);
        float metallic = clamp(mrSample.b, 0.0.1.0);
    #else
        float roughness = clamp(u_MetallicRoughnessValues.y, 0.04.1.0);
        float metallic = u_MetallicRoughnessValues.x;
    #endif
    
    #ifdef HAS_BASECOLORMAP
        vec3 baseColor = texture2D(u_BaseColorSampler, v_UV).rgb;
    #else
        vec3 baseColor = vec3(1.0.1.0.1.0);
    #endif
    
    vec3 f0 = vec3(0.04);
    // is this the same? test!
    
    vec3 diffuseColor = mix(baseColor.rgb * (1.0 - f0), vec3(0..0..0.), metallic);
    // Vec3 diffuseColor = baseColor * (1.0-metallic);
    
    vec3 specularColor = mix(f0, baseColor, metallic);
    #ifdef USE_MATHS
        
        // Compute reflectance.
        float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
        
        // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
        
        // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
        float reflectance90 = clamp(reflectance * 25.0.0.0.1.0);
        vec3 specularEnvironmentR0 = specularColor.rgb;
        vec3 specularEnvironmentR90 = vec3(1.0.1.0.1.0) * reflectance90;
        PBRInfo pbrInputs = PBRInfo(
        NdotL, NdotV, NdotH, LdotH, VdotH, roughness, metallic, diffuseColor, specularEnvironmentR0, specularEnvironmentR90
        );
        vec3 F = fresnelSchlick2(pbrInputs);
        //vec3 F = fresnelSchlick(pbrInputs);
        
        //float G = microfacetCookTorrance(pbrInputs);
        //float G = microfacetSmith(pbrInputs);
        //float G = microfacetSchlick(pbrInputs);
        float G = SmithVisibilityGGX(pbrInputs);
        float D = GGX(pbrInputs);
        vec3 diffuseContrib = (1.0 - F) * lambertianDiffuse(pbrInputs) * NdotL * u_LightColor;
        // Vec3 diffuseContrib = (1.0-f) * disneyDiffuse(pbrInputs) * NdotL * u_LightColor;
        
        
        vec3 specContrib = M_PI * u_LightColor * F * G * D / 4.0*NdotL*NdotV;
        vec3 color = (diffuseContrib + specContrib);
    #endif
    
    #ifdef USE_IBL
        float mipCount = 9.0; // resolution of 512x512
        
        float lod = (roughness * mipCount);
        vec3 brdf = texture2D(u_brdfLUT, vec2(NdotV, 1.0 - roughness)).rgb;
        vec3 diffuseLight = textureCube(u_DiffuseEnvSampler, n).rgb;
        #ifdef USE_TEX_LOD
            vec3 specularLight = textureCubeLodEXT(u_SpecularEnvSampler, reflection, lod).rgb; // This is correct
        #else
            vec3 specularLight = textureCube(u_SpecularEnvSampler, reflection).rgb;
        #endif
        
        vec3 IBLcolor = (diffuseLight * diffuseColor * u_scaleIBLAmbient.x) + (specularLight * (specularColor * brdf.x + brdf.y) *u_scaleIBLAmbient.y);
        color += IBLcolor;
    #endif
    
    #ifdef HAS_OCCLUSIONMAP
        float ao = texture2D(u_OcclusionSampler, v_UV).r;
        color *= ao;
    #endif
    
    #ifdef HAS_EMISSIVEMAP
        vec3 emissive = texture2D(u_EmissiveSampler, v_UV).rgb;
        color += emissive;
    #endif
    
    #ifdef USE_MATHS
        // mix in overrides
        color = mix(color, F, u_scaleFGDSpec.x);
        color = mix(color, vec3(G), u_scaleFGDSpec.y);
        color = mix(color, vec3(D), u_scaleFGDSpec.z);
        color = mix(color, specContrib, u_scaleFGDSpec.w);
        color = mix(color, diffuseContrib, u_scaleDiffBaseMR.x);
        color = mix(color, baseColor, u_scaleDiffBaseMR.y);
        color = mix(color, vec3(metallic), u_scaleDiffBaseMR.z);
        color = mix(color, vec3(roughness), u_scaleDiffBaseMR.w);
    #endif
    
    gl_FragColor = vec4(color, 1.0);
    //gl_FragColor = vec4(n * 0.5 + 0.5, 1.0);
    
    //gl_FragColor = vec4(NdotV, NdotV, NdotV, 1.0);
    //gl_FragColor = vec4(v_uv. rg, 0.0, 1.0);
}

Copy the code