2010-04-15 4 views
2

Je tente d'ajouter des fonctionnalités à un ray tracer en C++. À savoir, j'essaye d'ajouter le mappage de texture aux sphères. Pour simplifier, j'utilise un tableau pour stocker les données de texture. J'ai obtenu les données de texture en utilisant un éditeur hexadécimal et en copiant les valeurs d'octets correctes dans un tableau dans mon code. C'était juste pour mes tests. Lorsque les valeurs de ce tableau correspondent à une image qui est simplement rouge, il semble fonctionner près de ce qui est attendu, sauf qu'il n'y a pas d'ombrage. first image http://dl.dropbox.com/u/367232/Texture.jpg La partie inférieure droite de l'image montre à quoi devrait ressembler une sphère correcte. La couleur de cette sphère en utilisant une couleur de jeu, pas une carte de texture.Comment utiliser la cartographie de texture dans un simple traceur de rayons?

Un autre problème est que lorsque la carte de texture a autre chose qu'un seul pixel de couleur, elle devient blanche. Mon image de test est une image de l'eau, et quand elle est mappée, elle montre seulement un anneau de pixels bleutés entourant la couleur blanche.

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

Lorsque cela est fait, il apparaît simplement comme ceci: second image http://dl.dropbox.com/u/367232/texture2.jpg

Voici quelques extraits de code:

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

J'appelle le code couleur ici 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; 
} 

J'ai omis le reste du code pour ne pas emboîter le poteau, mais on peut le voir here. Toute aide est grandement appréciée. La seule partie non incluse dans le code, est où je définis les données de texture, qui, comme je l'ai dit, est simplement pris directement à partir d'un fichier bitmap de l'image ci-dessus.

Merci.

Répondre

1

Il se peut que la texture soit juste délavée parce que la lumière est si brillante et si proche. Remarquez comment dans le cas du solide rouge, il ne semble pas y avoir de gradation autour de la sphère. Le rouge a l'air saturé.

Votre mappage u, v semble correct, mais il pourrait y avoir une erreur. J'ajouterais quelques instructions assert pour m'assurer que u et v et vraiment entre 0 et 1 et que l'index p dans votre tableau TEXT_DATA est également à portée.

+0

Ensuite, je ne suis pas sûr si je mets la sphère simplement pour afficher la couleur et pas de texture, les gradations semblent bien. Je vais regarder dans l'ajout d'assert déclarations et aussi voir ce qui se passe lorsque je réduis la luminosité de la lumière. – fastrack20

+0

Cela faisait partie du problème. La lumière était trop brillante et la sphère était lavée, mais la sphère ne montre toujours qu'une seule couleur solide, aucune idée? http://dl.dropbox.com/u/367232/image3.jpg – fastrack20

+0

Au lieu de rendre dans un 'int', quels clips, essayez d'utiliser' float' ou 'double' pour votre tampon de rendu (et tout le calcul). Puis examinez le résultat et convertissez le tampon en int en divisant l'intensité de chaque pixel par le pixel le plus lumineux (intensité maximum) de l'image entière. – SingleNegationElimination

0

Si vous mettez au point vos textures, vous devez utiliser un matériau constant dont la couleur est déterminée uniquement par la texture et non par les lumières. De cette façon, vous pouvez vous assurer que vous avez correctement mappé votre texture à votre primitive et que vous l'avez filtrée correctement avant de l'allumer. Alors vous savez que cette partie n'est pas le problème.

Questions connexes