如何在简单光线跟踪器中使用纹理贴图? 我试图在C++中添加一个特性给光线跟踪程序。也就是说,我正在尝试向球体添加纹理贴图。为了简单起见,我使用数组来存储纹理数据。通过使用十六进制编辑器并将正确的字节值复制到代码中的数组中,我获得了纹理数据。这只是为了我的测试目的。当此数组的值对应于仅为红色的图像时,除了没有着色外,它的工作方式似乎与预期接近。 图像右下角显示了正确的球体应该是什么样子。此球体的颜色使用一组颜色,而不是纹理贴图

如何在简单光线跟踪器中使用纹理贴图? 我试图在C++中添加一个特性给光线跟踪程序。也就是说,我正在尝试向球体添加纹理贴图。为了简单起见,我使用数组来存储纹理数据。通过使用十六进制编辑器并将正确的字节值复制到代码中的数组中,我获得了纹理数据。这只是为了我的测试目的。当此数组的值对应于仅为红色的图像时,除了没有着色外,它的工作方式似乎与预期接近。 图像右下角显示了正确的球体应该是什么样子。此球体的颜色使用一组颜色,而不是纹理贴图,c++,graphics,texture-mapping,C++,Graphics,Texture Mapping,另一个问题是,当纹理贴图不是一种颜色像素时,它会变成白色。我的测试图像是一张水的图片,当它绘制地图时,它只显示白色周围的一圈蓝色像素 完成此操作后,其显示方式如下: 以下是一些代码片段: Color getColor(const Object *object,const Ray *ray, float *t) { if (object->materialType == TEXTDIF || object->materialType == TEXTMATTE) {

另一个问题是,当纹理贴图不是一种颜色像素时,它会变成白色。我的测试图像是一张水的图片,当它绘制地图时,它只显示白色周围的一圈蓝色像素

完成此操作后,其显示方式如下:

以下是一些代码片段:

  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;
}
};
Color getColor(常量对象*Object,常量光线*Ray,浮点*t)
{
如果(对象->材质类型==TEXTDIF | |对象->材质类型==TEXTMATTE){
浮动距离=*t;
点pnt=射线->原点+射线->方向*距离;
点oc=对象->中心;
向量ve=点(oc.x,oc.y,oc.z+1)-oc;
规范化(&ve);
向量vn=点(oc.x,oc.y+1,oc.z)-oc;
规范化(&vn);
向量vp=pnt-oc;
规范化&vp;
双φ=acos(-vn.dot(vp));
浮点数v=φ/M_π;
浮动u;
float num1=(float)acos(vp.dot(ve));
float num=(num1/(float)sin(phi));
浮点θ=num/(浮点)(2*M_π);
如果(θ<0 | |θ==NAN){θ=0;}
如果(垂直交叉点(ve).点(vp)>0){
u=θ;
}
否则{
u=1-θ;
}
int x=(u*图像宽度)-1;
int y=(v*图像宽度)-1;
int p=(y*图像宽度+x)*3;
返回颜色(文本数据[p+2],文本数据[p+1],文本数据[p]);
}
否则{
返回对象->颜色;
}
};
我将颜色代码称为Trace:

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;
}
if(对象->材质类型==MATTE)
返回getColor(对象、光线和t);
射线阴影射线;
int-isInShadow=0;
shadowRay.origin.x=pHit.x+nHit.x*偏差;
shadowRay.origin.y=pHit.y+nHit.y*偏差;
shadowRay.origin.z=pHit.z+nHit.z*偏差;
shadowRay.direction=灯光->对象->中心-pHit;
float len=shadowRay.direction.length();
规格化(&shadowRay.direction);
float LdotN=阴影线方向点(nHit);
if(LdotN<0)
返回0;
颜色灯光颜色=灯光->对象->颜色;
for(int k=0;kisLight){
if(对象[k]->materialType==玻璃)
lightColor*=getColor(对象[k]、&shadowRay、&t);//通过玻璃颜色衰减灯光颜色
其他的
isInShadow=1;
打破
}
}
lightColor*=1.f/(len*len);
返回(isInShadow)?0:getColor(对象、&shadowRay、&t)*lightColor*LdotN;
}
为了不让帖子陷入困境,我省略了其余的代码,但是可以看到它。非常感谢您的帮助。代码中唯一没有包含的部分是我定义纹理数据的地方,正如我所说的,它直接取自上面图像的位图文件


谢谢。

可能是因为光线太亮太近,纹理被洗掉了。请注意,在纯红的情况下,球体周围似乎没有任何渐变。红色看起来已经饱和了


你的u,v映射看起来不错,但可能有错误。我会添加一些
assert
语句,以确保u和v实际上介于0和1之间,并且
TEXT\u数据
数组中的p索引也在范围内。

如果要调试纹理,则应使用颜色仅由纹理而非灯光决定的恒定材质。这样,在对纹理进行任何照明之前,可以确保将纹理正确映射到基本体并对其进行适当过滤。那你就知道那部分不是问题了

然后,我不确定是否将球体设置为仅显示颜色而不显示纹理,渐变看起来很好。我将研究添加断言语句,并查看当我降低灯光亮度时会发生什么。这是问题的一部分。光线太亮了,它冲走了球体,但球体仍然只显示出单一的纯色,有什么想法吗?不要渲染为
int
,而是尝试对渲染缓冲区(以及所有计算)使用
float
double
。然后检查结果,并通过将每个像素的强度除以整个图像的最亮(最大强度)像素,将缓冲区转换为int。