现在来生成球光照贴图。
上一文的方法对于粗糙的物体是合适的,这个球上有镜面反射产生亮斑。
所以、这里准备以贴图坐标所对应球上点和视点连线为入射光,生成密集的球光照贴图。
双向生成密集球光照图
//以球上的点和视点为入射光,反面使用对称视点(双向)
void 球纹理生成球上点和视点为入射光(vector<Sphere_GLSL> &spheres, std::vector<Triangle_GLSL> &triangles, int Sphere_n) {
double* image = new double[WIDTH * HEIGHT * 4];
memset(image, 0.0, sizeof(double) * WIDTH * HEIGHT * 4);
Sphere_GLSL *s1 = NULL;
for (int i = 0; i < spheres.size(); i++)
{
if (spheres[i].Sphere_n == Sphere_n) {
s1 = &spheres[i];
break;
}
}
MaxMin t0 = 计算MaxMin(spheres, Sphere_n);
float zmax, zmin;
zmin = t0.zmin;
zmax = t0.zmax;
printf("zmin:%.2f\n", zmin);
printf("zmax:%.2f\n", zmax);
//反面视点
vec3 eye = EYE; eye.z = -.9;// zmin - .2f;
printf("eye.z:%.2f\n", eye.z);
// 球体的基本参数
float x0 = s1->O.x, y0 = s1->O.y, z0 = s1->O.z; // 球心坐标
float r = s1->R; // 球的半径
std::vector<Ray> Raywh;
for (int k = 0; k < SAMPLE; k++)
{
if (k % 10 == 0)
printf("\r%d", k);
double* p = image;
Raywh.clear();
//生成入射光组-------------------------------------开始结束
for (float u = 0; u < WIDTH; u++)
{
for (float w = 0; w < HEIGHT; w++)
{
float x, y, z;
// 计算球体表面上的点坐标
求xyz(x0, y0, z0, r, u, w, x, y, z);
// MSAA
if (k != SAMPLE - 1) {
x += (randf() - 0.5f) / float(WIDTH);
y += (randf() - 0.5f) / float(HEIGHT);
}
//以球上的点和视点为入射光
vec3 direction;
Ray ray;
// 计算光线投射方向
if (z>=s1->O.z)
{//正面
direction = normalize(vec3(x, y, z) - EYE);
ray.startPoint = EYE;
ray.direction = direction;
Raywh.push_back(ray);
}
else {
//反面
direction = normalize(vec3(x, y, z) - eye);
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 通道
}
}
}printf("\n");
//像素剪裁0-255
powClamp0255(image, WIDTH*HEIGHT * 4);
//保存图像
char filename[256];
sprintf_s(filename, "Sphere%d.png", Sphere_n);
imSave(image, WIDTH, HEIGHT, filename);
}
球1、2、3图:
然后运行opengl程序:
已经完成,后续应该把它制成OBJ,PLY文件,方便交流。
感谢观看!