2010-04-15 5 views
2

C++에서 레이 트레이서에 피쳐를 추가하려고합니다. 즉, 구체에 텍스처 매핑을 추가하려고합니다. 간단히하기 위해 배열을 사용하여 텍스처 데이터를 저장하고 있습니다. 16 진수 편집기를 사용하고 올바른 바이트 값을 내 코드의 배열에 복사하여 텍스처 데이터를 가져 왔습니다. 이것은 단지 테스트 목적이었습니다. 이 배열의 값이 단순히 빨간색 인 이미지에 해당하면 음영이없는 경우를 제외하고는 예상 한 것과 거의 유사하게 작동합니다. first image http://dl.dropbox.com/u/367232/Texture.jpg 이미지의 오른쪽 하단에는 정확한 구 모양을 보여줍니다. 이 구체의 색상은 텍스처 맵이 아닌 설정된 색상 하나를 사용합니다.간단한 광선 추적기에서 텍스처 매핑을 사용하려면 어떻게해야합니까?

또 다른 문제는 텍스처 맵이 단색 픽셀이 아닌 다른 것일 때 흰색이됩니다. 내 테스트 이미지는 물 사진이며, 매핑하면 흰색을 둘러싼 한 개의 푸른 색 픽셀 링 만 표시됩니다. 이 작업이 완료

bmp http://dl.dropbox.com/u/367232/vPoolWater.bmp

, 단순히이 같이 나타납니다 : 내가 추적 여기에 컬러 코드를 호출

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; 
} 
}; 

: 여기 second image http://dl.dropbox.com/u/367232/texture2.jpg

몇 가지 코드 조각입니다

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; 
} 

나는 코드의 나머지 부분을 포스트를 늪지는 것처럼 버렸지 만, here을 볼 수있다. 어떤 도움이라도 대단히 감사합니다. 코드에 포함되지 않은 유일한 부분은 텍스처 데이터를 정의하는 곳입니다. 위에서 말했듯이 위 이미지의 비트 맵 파일에서 바로 가져옵니다.

감사합니다.

답변

1

빛이 너무 밝고 가깝기 때문에 질감이 완전히 사라져 버린 것일 수 있습니다. 단색의 경우에는 구 주위에 그라데이션이없는 것처럼 보입니다. 빨간색은 포화 된 것처럼 보입니다.

u, v 매핑이 올바르게 보이지만 거기에 실수가있을 수 있습니다. 나는 assert 문을 추가하여 u와 v를 확인하고 실제로 0과 1 사이에 있고 TEXT_DATA 배열의 p 인덱스도 범위 내에 있음을 확인합니다.

+0

그렇다면 구를 단순히 색을 표시하고 텍스처를 표시하지 않으면 그라디언트가 잘 표시됩니다. 나는 assert 문장을 추가하고 빛의 밝기를 줄일 때 어떤 일이 일어나는지 살펴볼 것이다. – fastrack20

+0

그것이 문제의 일부였습니다. 빛은 너무 밝아서 구를 씻어 내고 있었지만 구가 여전히 단색만을 보여주고 있습니까? http://dl.dropbox.com/u/367232/image3.jpg – fastrack20

+0

'int'로 렌더링하는 대신 클립을 사용하여 렌더링 버퍼 (및 모든 계산)에'float' 또는'double'을 사용해보십시오. 그런 다음 결과를 조사하고 전체 픽셀의 가장 밝은 (최대 강도) 픽셀로 각 픽셀의 강도를 나눔으로써 버퍼를 int로 변환하십시오. – SingleNegationElimination

0

텍스처를 디버깅하는 경우 조명이 아닌 텍스처만으로 색상이 결정되는 상수 재료를 사용해야합니다. 그렇게하면 조명을하기 전에 텍스처를 원시에 올바르게 매핑하고 올바르게 필터링 할 수 있습니다. 그렇다면 당신은 그 부분이 문제가 아니라는 것을 압니다.

관련 문제