直接整合了别人的博客代码
最后那个各向异性切线 X 和 Y 变量不知道怎么定义所以没加上
直接把上一篇博客 换下面这个
fshader.fsh
#version 330 core
in vec3 pix;
out vec4 fragColor;
// ----------------------------------------------------------------------------- //
uniform uint frameCounter;
uniform int nTriangles;
uniform int nNodes;
uniform int width;
uniform int height;
uniform samplerBuffer triangles;
uniform samplerBuffer nodes;
uniform sampler2D lastFrame;
uniform sampler2D hdrMap;
uniform vec3 eye;
uniform mat4 cameraRotate;
// ----------------------------------------------------------------------------- //
#define PI 3.1415926
#define INF 114514.0
#define SIZE_TRIANGLE 12
#define SIZE_BVHNODE 4
// ----------------------------------------------------------------------------- //
// Triangle 数据格式
struct Triangle {
vec3 p1, p2, p3; // 顶点坐标
vec3 n1, n2, n3; // 顶点法线
};
// BVH 树节点
struct BVHNode {
int left; // 左子树
int right; // 右子树
int n; // 包含三角形数目
int index; // 三角形索引
vec3 AA, BB; // 碰撞盒
};
// 物体表面材质定义
struct Material {
vec3 emissive; // 作为光源时的发光颜色
vec3 baseColor;
float subsurface;
float metallic;
float specular;
float specularTint;
float roughness;
float anisotropic;
float sheen;
float sheenTint;
float clearcoat;
float clearcoatGloss;
float IOR;
float transmission;
};
// 光线
struct Ray {
vec3 startPoint;
vec3 direction;
};
// 光线求交结果
struct HitResult {
bool isHit; // 是否命中
bool isInside; // 是否从内部命中
float distance; // 与交点的距离
vec3 hitPoint; // 光线命中点
vec3 normal; // 命中点法线
vec3 viewDir; // 击中该点的光线的方向
Material material; // 命中点的表面材质
};
// ----------------------------------------------------------------------------- //
/*
* 生成随机向量,依赖于 frameCounter 帧计数器
* 代码来源:https://blog.demofox.org/2020/05/25/casual-shadertoy-path-tracing-1-basic-camera-diffuse-emissive/
*/
uint seed = uint(
uint((pix.x * 0.5 + 0.5) * width) * uint(1973) +
uint((pix.y * 0.5 + 0.5) * height) * uint(9277) +
uint(frameCounter) * uint(26699)) | uint(1);
uint wang_hash(inout uint seed) {
seed = uint(seed ^ uint(61)) ^ uint(seed >> uint(16));
seed *= uint(9);
seed = seed ^ (seed >> 4);
seed *= uint(0x27d4eb2d);
seed = seed ^ (seed >> 15);
return seed;
}
float rand() {
return float(wang_hash(seed)) / 4294967296.0;
}
// ----------------------------------------------------------------------------- //
// 半球均匀采样
vec3 SampleHemisphere() {
float z = rand();
float r = max(0, sqrt(1.0 - z*z));
float phi = 2.0 * PI * rand();
return vec3(r * cos(phi), r * sin(phi), z);
}
/*
vec3 toNormalHemisphere(vec3 v, vec3 N) {
vec3 tangent = vec3(0);
if(N.yz==vec2(0)) tangent = vec3(0, 0, -N.x);
else if(N.xz==vec2(0)) tangent = vec3(0, 0, N.y);
else if(N.xy==vec2(0)) tangent = vec3(-N.z, 0, 0);
else if(abs(N.x)>abs(N.y)) tangent = normalize(vec3(0, N.z, -N.y));
else tangent = normalize(vec3(-N.z, 0, N.x));
vec3 bitangent = cross(N, tangent);
return normalize(v.x * tangent + v.y * bitangent + v.z * N);
}
*/
// 将向量 v 投影到 N 的法向半球
vec3 toNormalHemisphere(vec3 v, vec3 N) {
vec3 helper = vec3(1, 0, 0);
if(abs(N.x)>0.999) helper = vec3(0, 0, 1);
vec3 tangent = normalize(cross(N, helper));
vec3 bitangent = normalize(cross(N, tangent));
return v.x * tangent + v.y * bitangent + v.z * N;
}
// ----------------------------------------------------------------------------- //
// 将三维向量 v 转为 HDR map 的纹理坐标 uv
vec2 SampleSphericalMap(vec3 v) {
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
uv /= vec2(2.0 * PI, PI);
uv += 0.5;
uv.y = 1.0 - uv.y;
return uv;
}
// 获取 HDR 环境颜色
vec3 sampleHdr(vec3 v