第 9 课:Deferred Shading
本课需 多 pass / 后处理,暂以代码复盘呈现。
实现
uniform float iTime;
uniform vec2 iResolution;
uniform mat4 inverseViewMatrix;
uniform sampler2D iRTBuffer0; // color
uniform sampler2D iRTBuffer1; // normal + specular shininess
uniform sampler2D iRTBuffer2; // position
out vec4 FragColor;
struct TLight { vec3 position; vec3 color; };
TLight c_Lights[4] = TLight[4](
TLight(vec3( 2.5, 0.5, 2.5), vec3(1.0, 0.2, 0.2)),
TLight(vec3(-2.5, 0.5, 2.5), vec3(0.2, 1.0, 0.2)),
TLight(vec3( 2.5, 0.5, -2.5), vec3(0.2, 0.2, 1.0)),
TLight(vec3(-2.5, 0.5, -2.5), vec3(1.0, 1.0, 0.2))
);
vec3 getViewPos() {
return (inverseViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
}
mat3 rotationYMatrix(float angle) {
float cosAngle = cos(angle);
float sinAngle = sin(angle);
return mat3(
vec3(cosAngle, 0, -sinAngle),
vec3(0, 1, 0),
vec3(sinAngle, 0, cosAngle)
);
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
vec4 color = texture(iRTBuffer0, uv);
vec4 normal = texture(iRTBuffer1, uv);
vec4 position = texture(iRTBuffer2, uv);
float specularShine = normal.w;
vec3 viewPos = getViewPos();
mat3 rotateY = rotationYMatrix(iTime * 1.57);
float kc = 0.1;
float kl = 0.1;
float kq = 0.1;
float ambient = 0.5;
vec3 lights = vec3(0.0);
for(int i = 0; i < 4; i++){
vec3 lightColor = c_Lights[i].color;
vec3 lightPos = rotateY * c_Lights[i].position;
vec3 lightDir = normalize(position.xyz - lightPos);
vec3 viewDir = normalize(viewPos - position.xyz);
vec3 halfwayVec = normalize(-lightDir + viewDir);
float diffuse = max(dot(normal.xyz,-lightDir),0.0);
float specular = max(dot(normal.xyz,halfwayVec),0.0);
specular = pow(specular, specularShine);
float Distance = distance(position.xyz, lightPos);
float Attenuation = 1.0 / (kc + kl * Distance + kq * Distance * Distance);
lights += color.xyz * lightColor * (ambient + diffuse + specular) * Attenuation;
}
FragColor = vec4(lights, 1.0) ;
}