obj. File - Color per vertex

I am playing around with the precompiled-samples from NVIDIA-OptiX-SDK-3.7.0-linux64, more specifically with sample6 with this command “./sample6 -o cube.obj” with the following obj. file.

# cube.obj
#
 
g cube
 
v  0.0  0.0  0.0  124  110  120
v  0.0  0.0  1.0  24  0  121
v  0.0  1.0  0.0  4  0  44
v  0.0  1.0  1.0  224  0  10
v  1.0  0.0  0.0  24  200  25
v  1.0  0.0  1.0  124  10  56
v  1.0  1.0  0.0  78  10  50
v  1.0  1.0  1.0  23  0  200

vn  0.0  0.0  1.0
vn  0.0  0.0 -1.0
vn  0.0  1.0  0.0
vn  0.0 -1.0  0.0
vn  1.0  0.0  0.0
vn -1.0  0.0  0.0
 
f  1//2  7//2  5//2
f  1//2  3//2  7//2 
f  1//6  4//6  3//6 
f  1//6  2//6  4//6 
f  3//3  8//3  7//3 
f  3//3  4//3  8//3 
f  5//5  7//5  8//5 
f  5//5  8//5  6//5 
f  1//4  5//4  6//4 
f  1//4  6//4  2//4 
f  2//1  6//1  8//1 
f  2//1  8//1  4//1

I only added RGB information at the vertices, but I dont get anything colored.

But I am using the .obj file with vertex coloring the correct way, right?

I compiled the sample by myself and it seems that the meshbase.cpp does not set the uses_colors flag even though the program reads in the RGB information. And if I set the flag by myself, i will just get a segmentation fault based on the uchar pointer of colors.

Can somebody please try this out too? Maybe you have encountered the problem as well.

Color per vertex is one of the more ill defined concepts of the OBJ file fomat given that it actually supports vertices with x,y,z and x,y,z,w formats. It’s probably only used in some specific saver/loader combination.

That said, I don’t have the OptiX code in front of me, but if you want to have color per vertex you would need to parse the given color information into a vertex attribute, make that available to the geometry like the other vertex attributes position, normal and texture coordinate, then adapt the intersection program to read that color attribute and copy it into an attribute variable you would then need to evaluate inside the closest hit programs instead of the diffuse color variable Kd.

I would expect that most of that is not implemented inside the example code.

Follow the code path which is taken for the vertices and add all cases needed for colors as well. There are just no transformations on them. I would recommend converting the colors to normalized floats on the host. That matches the representations inside the material descriptions better.

Thanks for the good explanation. I managed to have a color per vertex now. I calculate the diffuse color variable Kd by adding the color vectors per triangle and normalize it, so I have for each triangle one specific color.

But can I have multiple colors per triangle, i.e. that the color of a triangle would be interpolated between the vertices for each point of a triangle( like the RGB triangle) without textures?

Here is what I added to the interesection program and the closest hit program :

// triangle_mesh.cu
rtBuffer<float3> color_buffer;
rtDeclareVariable(float3, color_vec, attribute color_vec, );
/* Buffers */

RT_PROGRAM void mesh_intersect( int primIdx )
{
  int3 v_idx = vindex_buffer[primIdx];

  float3 c0 = color_buffer[ v_idx.x ];
  float3 c1 = color_buffer[ v_idx.y ];
  float3 c2 = color_buffer[ v_idx.y ];

  color_vec = normalize( c0 + c1 + c2 );

// Intersect ray with triangle
/* ...*/
}

and the closes hit program

// obj_material.cu
rtDeclareVariable(float3, color_vec, attribute color_vec, );

RT_PROGRAM void closest_hit_radiance()
{
/* ... */
float3 Kd = color_vec;
/* Ka,Ks,Kr ... */
phongShade( Kd, Ka, Ks, ffnormal, phong_exp, Kr );
}

Sure. Simply do the same barycentric interpolation on the per vertex color attributes inside your
intersection program which is done for the other attributes (except for the geometric_normal)

If color_vec is your interpolated color attribute, your code snippet won’t work!
Read the OptiX 3.8.0 Programming Guide chapter 4.1.4:
Attribute variables may only be written in an intersection program between calls to rtPotentialIntersection and rtReportIntersection.

Also note that your code snippet has a copy-paste error. You use v_idx.y twice instead of v_idx.z for the third color.

It should look similar to this:

...

  float3 n;
  float  t;
  float  beta;
  float  gamma;

  if (intersect_triangle(theRay, v0, v1, v2, n, t, beta, gamma))
  {
    if (rtPotentialIntersection(t))
    {
      // Standard barycentric interpolation code:
      const float alpha = 1.0f - beta - gamma;

      color_vec = color_buffer[ v_idx.x ] * alpha +
                  color_buffer[ v_idx.y ] * beta  +
                  color_buffer[ v_idx.z ] * gamma;

      ... // more attributes.

      rtReportIntersection(0);
    }
  }
}