如何使用纹理映射在一个简单的光线追踪器?
-
27-09-2019 - |
题
我试图功能添加到光线跟踪器在C ++中。也就是说,我想纹理映射添加到该领域。为了简单起见,我使用的阵列来存储纹理数据。我通过使用十六进制编辑器和复制正确的字节值代入在我的代码的阵列获得的纹理数据。这只是我的测试目的。当这个数组对应于被简单地红色图像的值,它似乎工作接近的期望是什么,除了没有阴影。 第一图像http://dl.dropbox.com/u/367232/Texture.jpg 该图片显示了一个正确的范围应该是什么样子的右下角。使用一种颜色此球体的颜色,而不是一个纹理贴图。
的另一个问题是,当纹理映射是不是仅一个彩色像素以外的东西,它变为白色。我的测试图像是水的图像,并且当它映射,它示出了周围的白色带蓝色像素的仅一个环。
BMP http://dl.dropbox.com/u/367232/vPoolWater。 BMP
当这样做时,它简单地显示为这样的: 第二图像http://dl.dropbox.com/u/367232/texture2.jpg
这里有几个代码片断:
Color getColor(const Object *object,const Ray *ray, float *t)
{
if (object->materialType == TEXTDIF || object->materialType == TEXTMATTE) {
float distance = *t;
Point pnt = ray->origin + ray->direction * distance;
Point oc = object->center;
Vector ve = Point(oc.x,oc.y,oc.z+1) - oc;
Normalize(&ve);
Vector vn = Point(oc.x,oc.y+1,oc.z) - oc;
Normalize(&vn);
Vector vp = pnt - oc;
Normalize(&vp);
double phi = acos(-vn.dot(vp));
float v = phi / M_PI;
float u;
float num1 = (float)acos(vp.dot(ve));
float num = (num1 /(float) sin(phi));
float theta = num /(float) (2 * M_PI);
if (theta < 0 || theta == NAN) {theta = 0;}
if (vn.cross(ve).dot(vp) > 0) {
u = theta;
}
else {
u = 1 - theta;
}
int x = (u * IMAGE_WIDTH) -1;
int y = (v * IMAGE_WIDTH) -1;
int p = (y * IMAGE_WIDTH + x)*3;
return Color(TEXT_DATA[p+2],TEXT_DATA[p+1],TEXT_DATA[p]);
}
else {
return object->color;
}
};
我在这里所说的颜色代码在跟踪:
if (object->materialType == MATTE)
return getColor(object, ray, &t);
Ray shadowRay;
int isInShadow = 0;
shadowRay.origin.x = pHit.x + nHit.x * bias;
shadowRay.origin.y = pHit.y + nHit.y * bias;
shadowRay.origin.z = pHit.z + nHit.z * bias;
shadowRay.direction = light->object->center - pHit;
float len = shadowRay.direction.length();
Normalize(&shadowRay.direction);
float LdotN = shadowRay.direction.dot(nHit);
if (LdotN < 0)
return 0;
Color lightColor = light->object->color;
for (int k = 0; k < numObjects; k++) {
if (Intersect(objects[k], &shadowRay, &t) && !objects[k]->isLight) {
if (objects[k]->materialType == GLASS)
lightColor *= getColor(objects[k], &shadowRay, &t); // attenuate light color by glass color
else
isInShadow = 1;
break;
}
}
lightColor *= 1.f/(len*len);
return (isInShadow) ? 0 : getColor(object, &shadowRay, &t) * lightColor * LdotN;
}
余留出代码,以不陷入瘫痪柱的其余部分,但可以看出此处一>。任何帮助是极大的赞赏。不包括在代码的唯一部分,是我定义纹理数据,这正如我所说,被简单地直接从上面的图像的位图文件中取出。
感谢。
解决方案
这可能是因为纹理只是洗出因为光线如此明亮,如此接近。请注意,在红色实情况下,似乎都不怎么是球体周围的任何层次。红色看起来像它饱和的。
您U,V映射看起来正常,但有可能是一个错误的存在。我想补充一些assert
报表,以确保u和v,真正0和1之间,而且标普指数到您的TEXT_DATA
阵列也是在范围之内。
其他提示
如果你正在调试你的纹理,你应该使用一个恒定的材料,其颜色只由质地,而不是灯光确定。这样,你可以确保你正确映射你的纹理到你的原始和它做任何照明前适当对其进行筛选。然后,你知道的那部分是没有问题的。