c - 为什么我的法线贴图不能在球体上正常工作?
问题描述
这可能更适合另一个堆栈交换,但因为我的 3d 引擎都是我从头开始编写的,所以我认为这是最好的地方。
我在网上找到的所有关于法线贴图的资源都是关于将它们应用于网格的,所以我只是猜到了为球体做这件事的正确方法。我用来扰动法线向量的基本算法是:
struct _Vec3 {
double x;
double y;
double z;
};
struct _Rgb {
unsigned char r;
unsigned char g;
unsigned char b;
};
void adjustNormal(Sphere* sphere, Vec3* point, Vec3* normal) {
double* arr = getSphereCoordinates(sphere, point); // get coordinates of point, where 0 < x, y < 1
double x = arr[0];
double y = arr[1];
Rgb* color = getPixel(sphere -> normalMap, x, y); // get the data from normal map
x = (color -> r) / 255.0;
y = (color -> g) / 255.0;
double z = (color -> b) / 255.0;
Vec3** ortho = getOrthogonalVectors(normal); // basis of tangent space
Vec3* tangent = ortho[0];
Vec3* bitangent = ortho[1];
scaleVec3(normal, z); // scale normal vector by z
scaleVec3(tangent, y); // scale tangent vector by y
scaleVec3(bitangent, x); // scale bitangent vector by x
normal = add3(normal, tangent, bitangent); // add together three vectors
normalize(normal);
}
现在,我对此非常有信心getSphereCoordinates
并且getPixel
可以正常工作,因为将常规纹理(不是法线贴图)应用于球体可以正常工作。我不太自信,getOrthogonalVectors
因为即使我改变它,我仍然对法线贴图有问题。以防万一,这里是:
Vec3** getOrthogonalVectors(Vec3* vec) {
Vec3 temp;
copyVec3(&temp, vec);
temp.x += 10; // no matter how I change
temp.y += 1; // this to get a nonparallel vector,
temp.z += 1; // the normal map isn't correct
Vec3* v1 = cross(vec, &temp);
Vec3* v2 = cross(vec, v1);
scaleVec3(v2, -1); // necessary for orientation
normalize(v1);
normalize(v2);
Vec3** ans = malloc(sizeof(Vec3*) * 2);
ans[1] = v1;
ans[0] = v2;
return ans;
}
下面是正在使用的法线贴图以及应用贴图后球体的外观。
这张照片的光源与相机位于同一位置,因此理论上应该照亮球体的整个正面。有什么我做错了吗?
解决方案
推荐阅读
- rust - Ref::map 内的人体工程学选项处理
- javascript - React checkbox - Onchange 复选框,第一次未定义
- reactjs - 在重定向时反应嵌套路由问题
- json - 使用 XSLT 和在文本中转义双引号的 XML 到 JSON
- mongodb - 将 mongo 文档数组合并为一个
- php - PHPBrew:无法安装或添加 argon2i 散列
- android - 如何在 Android 中通过 IR blaster 传输十六进制代码?
- excel - 将我的 Access 表导出到 Excel,但将列中的不同值拆分到不同的工作表中
- sql - 连接表,选择所有但重命名几个 SQL BQ
- laravel - 处理会话过期,Laravel 与 Vue 和 Axios