Delay Coloring for WebGL – Jeff Zhong – Cnblogs.com

MRT

  • FBO
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
const fbo = {
  framebuffer: fb,
  textures: []};// Create a color texture
for(let i = 0; i < 3; i++){
  const tex = initTexture(gl, { informat: gl.RGBA16F, type: gl.FLOAT }, width, height);
  framebufferInfo.textures.push(tex);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, tex, 0);
}

// Create deep render buffer
const depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
Copy the code
  • draw buffer
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
Copy the code
  • Gbuffer shader
#version 300 es
in vec4 aPosition;
in vec4 aNormal;
uniform mat4 modelMatrix;
uniform mat4 vpMatrix;
out vec3 vPosition;
out vec3 vNormal;

void main() {
  gl_Position = vpMatrix * modelMatrix * aPosition;
  vNormal = vec3(transpose(inverse(modelMatrix)) * aNormal);
  vPosition = vec3(modelMatrix * aPosition);
}
Copy the code
#version 300 es
precision highp float;
layout (location = 0) out vec3 gPosition;// The location of each slice
layout (location = 1) out vec3 gNormal;  // The normal vector of each slice
layout (location = 2) out vec4 gColor;   // The color of each slice
uniform vec4 color;
in vec3 vPosition;
in vec3 vNormal;

void main() {
  gPosition = vPosition;
  gNormal = normalize(vNormal);
  gColor = color;
}
Copy the code

Light processing

  • Light processing shader
#version 300 es
#define GLSLIFY 1
in vec3 aPosition;
in vec2 aTexcoord;
out vec2 texcoord;
void main() {
    texcoord = aTexcoord;
    gl_Position = vec4(aPosition, 1.0);
}
Copy the code
#version 300 es
precision highp float;
#define GLSLIFY 1
uniform vec3 viewPosition;
uniform vec3 lightDirection;
uniform vec3 lightColor;
uniform vec3 ambientColor;
uniform float shininess;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gColor;
struct PointLight {
    vec3 position;
    vec3 color;
    float shininess;
    float line;
    float quad;
};
uniform PointLight pointLights[10];
struct SpotLight {
    vec3 position;
    vec3 direction;
    vec3 color;
    float outerRad;
    float innerRad;
    float shininess;
};
uniform SpotLight spotLights[3];
in vec2 texcoord;
out vec4 FragColor;
/* * point light source */
vec3 getPointLights(vec3 fragPos, vec3 normal, vec3 color, vec3 viewDir) {
    vec3 ret = vec3(0.0);
    for(int i = 0; i < 10; i++) {
        vec3 lightPos = pointLights[i].position;
        vec3 lightColor = pointLights[i].color;
        float lightShininess = pointLights[i].shininess;
        vec3 lightDir = normalize(lightPos - fragPos);
        float cosTheta = max(dot(lightDir, normal), 0.0);
        vec3 diffuse = lightColor * color * cosTheta;
        / / highlights
        vec3 halfwayDir = normalize(lightDir + viewDir);
        float specularIntensity = pow(max(dot(normal, halfwayDir), 0.0), lightShininess);
        vec3 specular = lightColor * specularIntensity;
        // Light intensity attenuation
        float dis = distance(lightPos, fragPos);
        float att = 1.0 / (1.0 + pointLights[i].line * dis + pointLights[i].quad * (dis * dis));
        ret += (diffuse + specular) * att;
    }
    return ret;
}
/* * spotlight */
vec3 getSpotLights(vec3 fragPos, vec3 normal, vec3 color, vec3 viewDir) {
    vec3 ret = vec3(0.0);
    for(int i = 0; i < 3; i++) {
        vec3 lightPos = spotLights[i].position;
        vec3 lightColor = spotLights[i].color;
        float lightShininess = spotLights[i].shininess;
        vec3 lightDir = normalize(spotLights[i].direction);
        float outerLimit = cos(spotLights[i].outerRad); / / irradiation Angle | fuzzy diameter range Angle
        float innerLimit = cos(spotLights[i].innerRad); // Blur the inner diameter Angle
        vec3 surToLightDir = normalize(lightPos - fragPos); // Point light position - vertex position
        float dotFromDirection = dot(surToLightDir, lightDir); // The Angle between the light direction and the surface light direction
        float inlightBloom = smoothstep(outerLimit, innerLimit, dotFromDirection); // Spotlight range + edge blur
        float cosTheta = max(dot(surToLightDir, normal), 0.0); // The dot product of the ray direction and the normal vector can be used to calculate the cosine of the Angle (range 0-90 degrees)
        vec3 diffuse = lightColor * color * cosTheta * inlightBloom;
        / / highlights
        vec3 halfwayDir = normalize(surToLightDir + viewDir);
        float specularIntensity = pow(max(dot(normal, halfwayDir), 0.0), lightShininess);
        vec3 specular = lightColor * specularIntensity * inlightBloom;
        ret += (diffuse + specular);
    }
    return ret;
}
void main() {
    vec3 fragPos = texture(gPosition, texcoord).rgb; // The location of each slice
    vec3 normal = texture(gNormal, texcoord).rgb; // The normal direction of each slice
    vec3 color = texture(gColor, texcoord).rgb; // The color of each slice
    
    vec3 viewDir = normalize(viewPosition - fragPos); // View direction
    vec3 lightDir = normalize(lightDirection); // Parallel light direction
    
    float cosTheta = max(dot(lightDir, normal), 0.0); // Angle between ray direction and normal vector
    
    / / the ambient light
    vec3 ambient = ambientColor * color;
    / / diffuse
    vec3 diffuse = lightColor * color * cosTheta;
    
    FragColor = vec4(ambient + diffuse + getPointLights(fragPos, normal, color, viewDir) + getSpotLights(fragPos, normal, color, viewDir), 1.0);
}
Copy the code