WebGL之延迟着色 - Jeff.Zhong - 博客园 (cnblogs.com)
MRT
- FBO
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
const fbo = {
framebuffer: fb,
textures: []
};
// 创建颜色纹理
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);
}
// 创建深度渲染缓冲区
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);
- draw buffer
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
- gbuffer着色器
#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);
}
#version 300 es
precision highp float;
layout (location = 0) out vec3 gPosition;// 每个片元的位置
layout (location = 1) out vec3 gNormal; // 每个片元的法向量
layout (location = 2) out vec4 gColor; // 每个片元的颜色
uniform vec4 color;
in vec3 vPosition;
in vec3 vNormal;
void main() {
gPosition = vPosition;
gNormal = normalize(vNormal);
gColor = color;
}
光照处理
- 光照处理着色器
#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);
}
#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;
/*
* 点光源
*/
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;
// 高光
vec3 halfwayDir = normalize(lightDir + viewDir);
float specularIntensity = pow(max(dot(normal, halfwayDir), 0.0), lightShininess);
vec3 specular = lightColor * specularIntensity;
// 光强衰减
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;
}
/*
* 聚光灯
*/
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); //照射范围角度|模糊外径角度
float innerLimit = cos(spotLights[i].innerRad); //模糊内径角度
vec3 surToLightDir = normalize(lightPos - fragPos); // 点光源反向 光源位置-顶点位置
float dotFromDirection = dot(surToLightDir, lightDir); //光源方向与表面光线方向的夹角
float inlightBloom = smoothstep(outerLimit, innerLimit, dotFromDirection); //聚光灯范围 + 边缘模糊
float cosTheta = max(dot(surToLightDir, normal), 0.0); // 光线方向和法向量的夹角,它们的点积即可求出夹角余弦值(范围0-90度)
vec3 diffuse = lightColor * color * cosTheta * inlightBloom;
// 高光
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; //每个片元的位置
vec3 normal = texture(gNormal, texcoord).rgb; //每个片元的法向
vec3 color = texture(gColor, texcoord).rgb; //每个片元的颜色
vec3 viewDir = normalize(viewPosition - fragPos); //视点方向
vec3 lightDir = normalize(lightDirection); // 平行光方向
float cosTheta = max(dot(lightDir, normal), 0.0); // 光线方向和法向量夹角
// 环境光
vec3 ambient = ambientColor * color;
// 漫反射
vec3 diffuse = lightColor * color * cosTheta;
FragColor = vec4(ambient + diffuse + getPointLights(fragPos, normal, color, viewDir) + getSpotLights(fragPos, normal, color, viewDir), 1.0);
}