第 19 课:Normal Space
我的解:和36是一个写法
我的解
uniform sampler2D iDepthBuffer;
uniform mat4 projectionMatrix;
// uniform mat4 viewMatrix;
const float PI = 3.14;
const float c_Error = 1e-6;
varying vec3 vPos;
varying vec3 vNormal;
mat3 getNormalSpace(vec3 normal) {
//随便某个单位向量,找一个很可能不和normal共线的方向
vec3 someVec = vec3(1.0, 0.0, 0.0);
//判断两者是否接近,几乎共线接近0,否则接近1
float dd = dot(someVec, normal);
//作为x向量备选
vec3 tangent = vec3(0.0, 1.0, 0.0);
//如果足够接近,小于c_Error;
if (1.0 - abs(dd) > c_Error) {
//垂直于两个向量的向量,作为x向量
tangent = normalize(cross(someVec, normal));
}
//z向量
vec3 bitangent = cross(tangent, normal);
//y肯定是法向量
return mat3(tangent, normal, bitangent);
}
void main() {
mat3 normalSpace = getNormalSpace(vNormal);
float occlusion = 0.0;
for (int i = 0; i < 4; ++i){
for (int j = 0; j < 16; ++j){
float theta = float(i) * (PI * 0.5)/4.0;
float phi = float(j) * (2.0 * PI)/16.0;
vec3 localDir = vec3(
sin(phi) * sin(theta),
cos(theta),
cos(phi) * sin(theta)
);
vec3 worldDir = normalize(normalSpace * localDir);
vec3 samplePos = vPos + normalize(worldDir) * 0.01;
// world pos to screen space
vec4 proj = projectionMatrix * viewMatrix * vec4(samplePos, 1.0);
proj.xyz /= proj.w; // prospective division
proj.xyz = proj.xyz * 0.5 + 0.5; // transformation to the interval [0, 1]
float pDepth = texture(iDepthBuffer, proj.xy).r;
float bias = c_Error;
float rangeCheck = smoothstep(0.0, 1.0, 0.01 / abs(proj.z - pDepth));
float occluded = (proj.z - bias > pDepth ? 1.0 : 0.0);
occlusion += occluded * rangeCheck;
}
}
occlusion = 1.0 - occlusion / 64.0;
gl_FragColor = vec4(vec3(occlusion) * vec3(0.8), 1.0);
}
复盘笔记
- 和36是一个写法
<2025/05/29>