视点游动生成光照贴图
上一文生成的光照贴图有两个缺点。其一稀疏点需要插值,插值后彩色不均。
其二物体遮挡有黑洞。
如果把入射光起点(视点)放在目标物体附近,然后移动光线,估计会形成一个密集的无黑洞的图像。
在平面上视点游动生成光照贴图
void 平面纹理生成(vector<Sphere_GLSL> &spheres, std::vector<Triangle_GLSL> &triangles, int Triangle_n0, int Triangle_n1) {
double* image = new double[WIDTH * HEIGHT * 4];
memset(image, 0.0, sizeof(double) * WIDTH * HEIGHT * 4);
MaxMin t0 = 计算MaxMin(triangles, Triangle_n0);
MaxMin t1 = 计算MaxMin(triangles, Triangle_n1);
float xmax, xmin;
float ymax, ymin;
float zmax, zmin;
xmin = min(t0.xmin, t1.xmin);
xmax = max(t0.xmax, t1.xmax);
ymin = min(t0.ymin, t1.ymin);
ymax = max(t0.ymax, t1.ymax);
zmin = min(t0.zmin, t1.zmin);
zmax = max(t0.zmax, t1.zmax);
string xyz = "xy";
if (xmax == xmin)xyz = "yz";
else if (ymax == ymin)xyz = "xz";
else if (zmax == zmin)xyz = "xy";
else {
printf("err\n");
return;
}
// 平面的基本参数
float w, h, r, imin, imax, jmin, jmax;
if (xyz == "xy") {
w = xmax - xmin, h = ymax - ymin;
r = zmin;
imin = ymin, imax = ymax, jmin = xmin, jmax = xmax;
}
else if (xyz == "yz") {
w = ymax - ymin, h = zmax - zmin;
r = xmax;
imin = zmin, imax = zmax, jmin = ymin, jmax = ymax;
}
else if (xyz == "xz") {
w = xmax - xmin, h = zmax - zmin;
r = ymin;
jmin = xmin, jmax = xmax;
imin = zmin, imax = zmax;
}
else {
printf("err !!!\n");
return;
}
// 参数化的步长
float xStep = w / WIDTH;
float yStep = h / HEIGHT;
std::vector<Ray> Raywh;
for (int k = 0; k < SAMPLE; k++)
{
printf("\r%d", k);
double* p = image;
Raywh.clear();
//平面纹理生成
//以平面大一圈的位置为起点,向平面垂线的方向为射线
//--------------------------------------------
// 遍历表面
for (float i = imin; i < imax; i += yStep) {
for (float j = jmin; j < jmax; j += xStep) {
//printf("%.1f\n", j);
// 计算面外的点坐标
double x = j;
double y = i;
double z = r + 0.01f;
vec3 eye = vec3(x, y, z);
vec3 coord = vec3(x, y, r);
float 移动 = 0.01f;
if (r > 0)移动 = -0.01f;
if (xyz == "xy") {
x = j, y = i, z = r + 移动;
// MSAA
x += (randf() - 0.5f) / double(WIDTH);
y += (randf() - 0.5f) / double(HEIGHT);
eye = vec3(x, y, z);
coord = vec3(x, y, r);
}
else if (xyz == "yz") {
x = r + 移动, y = j, z = i;
y += (randf() - 0.5f) / double(WIDTH);
z += (randf() - 0.5f) / double(HEIGHT);
eye = vec3(x, y, z);
coord = vec3(r, y, z);
}
else if (xyz == "xz") {
x = j, y = r + 移动, z = i;
x += (randf() - 0.5f) / double(WIDTH);
z += (randf() - 0.5f) / double(HEIGHT);
eye = vec3(x, y, z);
coord = vec3(x, r, z);
}
// 计算光线投射方向
vec3 direction = normalize(coord - eye);
Ray ray;
ray.startPoint = eye;
ray.direction = direction;
Raywh.push_back(ray);
}
}
//--------------------------------------------
std::vector<vec4> color;
// 路径追踪
pathTracing_GLSL_TSn(Raywh, color);
int nc = 0;
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
// 生成光线
vec4 color0 = color[nc++];
color0 *= BRIGHTNESS;
*p += color0.x; p++; // R 通道
*p += color0.y; p++; // G 通道
*p += color0.z; p++; // B 通道
*p += color0.w; p++; // A 通道
}
}
}
//imshow(image);
{
double* p = image;
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
*p = clamp(pow(*p, 1.0f / 2.2f) * 255, 0.0, 255.0); p++; // R 通道
*p = clamp(pow(*p, 1.0f / 2.2f) * 255, 0.0, 255.0); p++; // G 通道
*p = clamp(pow(*p, 1.0f / 2.2f) * 255, 0.0, 255.0); p++; // B 通道
*p = clamp(pow(*p, 1.0f / 2.2f) * 255, 0.0, 255.0); p++; // A 通道
}
}
}
char filename[256];
sprintf_s(filename, "triangle0%d%d.png", Triangle_n0, Triangle_n1);
imSave(image, WIDTH, HEIGHT, filename);
delete image;
}
对比:左边是前面生成的,右边是这次生成的。
然后运行代码
球上要怎么处理,还没有想好,以后再写吧。