VBO with tangent data

Started by
12 comments, last by bootstrap 17 years ago
Hi, I want to use VBO's for my objects, but I can't find space for putting the tangent data in it as well. My vertex-data contains this: - Vertices(3f) - Texcoords(2f) - Normals(3f) - Tangents(3f) - BiTangents(3f) Its a while ago since I used VBO's, so correct me if I'm wrong. Normally I would use the "glInterleavedArrays" function to tell what the data format is. For example, I can choose for "GL_C4UB_V3F" format, which means it the vertex-data contains 4 unsigned bytes for the color, and a vertices with 3 components. But what format to use for the stuff I want? Normally I put my tangents/biTangents inside texture coordinates on channel 1 and 2. But I can't find a format for that. greetings, Rick
Advertisement
It is, perhaps, time to switch to defining your own layouts. I never even bothered trying those pre-packaged configurations. Modern 3D cards, and most certainly VBO processing, are designed for vertex-structures that contain some multiple of 32-bytes (32-bytes, 64-bytes, etc).

I have two vertex structures in my engine, one with 32-bytes that contains:
position: x,y,z
tcoords: u,v
color: r,g,b,a
normal: nx,ny,[nz]
and another with 64-bytes that contains:
position: x,y,z
tcoords: u,v
color: r,g,b,a
normal: nx,ny,nz
tangent: tx,ty,tz
bitangent: bx,by,bz

You are being pushed in this direction now, and this is where you should go. Once you have it working, you will never look back! However, you will probably want/need to consider making some of your components with integers. For example, to make my vertex-structures and VBO arrangement "work out", I store my colors and texture-coordinates as u16 values (unsigned 16-bit integers). This required me to NOT put the z component of the normal vector into the VBO, to make room for the four u16 RGBA color values in one-half of the vertex. But that is no problem since the shader can compute nz from nx,ny! :-)

64 bytes should be sufficient. But... how to render it in that case? I didn't know this was possible as well. Is there a constant to tell OpenGL 64 bytes is coming? And ifso, how to set the data up?

Before I made an array with floats, something like this:
// format = GL_T2F_C4UB_V3Fdata[n][0] = texcoord.xdata[n][1] = texcoord.ydata[n][2] = <packed rgba in 1 float>data[n][3] = vertex.xdata[n][4] = vertex.ydata[n][5] = vertex.z


But what to do now? Is there an example somewhere?

greetings,
Rick
Don't use GL's built in glInterleavedArrays, setup the arrays yourself.

Make a struct and put the vertex attributes in it you need. Than allocate the memory you need and fill the data and upload the data to the VBO as a whole unit if you want or map it. Then you use offsets in bytes of the size of the data you want to access. e.g.

struct Vertex{float vx,vy,vz;float nx,ny,nz;float tx,ty,tz;//others};//then you get the size of the dataunsigned int normalsOffset = sizeof(float) * 3;unsigned int tangentOffset = sizeof(float) * 6;


then you use the offsets in the array pointer functions with the Bufferoffset macro from the extension doc.

hope that helps

Uhm... I understand how to make the data array. But with which function to pass it? So far I always use "glDrawElements". Its a while ago I used VBO's. Possibly I also have an older version of the OpenGL function library.

greetings and thanks for helping,
Rick

Well, this is a somewhat involved process that you need to grind through once to get right. For me, it took reading the OpenGL information carefully about thirty-seven million, nine-hundred and fifty-six thousand, eight-hundred and twenty-six times. I think I looked in "OpenGL SuperBible" and the "OpenGL Programmer Manual" a few times too. Oh, and after I got it working I got "OpenGL Distilled" and it would have saved me a couple years I think.

All the above just means "it ain't trivial".

Here is some code to read to get hints from. This code WORKS, so I know it is correct, but many of the variables are specific to my engine, and therefore make no sense to you (though they are pretty descriptive names). However, all the OpenGL function calls are what you need to understand, and this code shows you what order they come in. The first function is where the shaders are created and initialized and all the vertex-element positions are registered with OpenGL and double-checked by the code (to make sure it happened correctly).

This code is called once to set up the shaders and its variables (which are specific to processing the vertex structure I outlined previously).

The second chunk of code is a function the first function/code-chunk calls.

The third chunk of code is code that sets up OpenGL before every draw call (and you can see the draw call down at the bottom).

If all this code isn't enough to drive you crazy, then you will end up very happy and never return to fixed predefined vertex arrangements - which are hopelessly ancient and inflexible and inefficient in new video cards.

Sorry, but you will need to do some reading and learning to understand this. But you'll probably find lots of VBO experts to explain this a hundred times better than I ever could. I only know how to slog until it works! And since I have the worst memory on earth, I cannot remember all the hows and whys. :-(


cpu ig_shader_create (cpu vertex, cpu pixel) {                // function entry  buffer = memory_buffer_create (maxbytes);  file_load (L"igtan003.vs", &vsource, &vbytes);              // vertex shader  file_load (L"igtan003.ps", &psource, &pbytes);              // pixel shader//// create vertex shader and pixel shader//  vshader = glCreateShader (GL_VERTEX_SHADER);                // GL_VERTEX_SHADER or GL_FRAGMENT_SHADER  pshader = glCreateShader (GL_FRAGMENT_SHADER);              // GL_VERTEX_SHADER or GL_FRAGMENT_SHADER//// specify vertex shader and pixel shader source-code text//  const GLchar** vstext = (const GLchar**)&vsource;           // vstext is an array of pointers to strings that contain vertex-shader-programs-or-functions (source code)  const GLchar** pstext = (const GLchar**)&psource;           // pstext is an array of pointers to strings that contain pixel-shader-programs-or-functions (source code)  glShaderSource (vshader, vlines, vstext, &vbytes);          //  glShaderSource (pshader, plines, pstext, &pbytes);          ////// compile vertex shader//  glCompileShader (vshader);                                  // compile vertex shader  glGetShaderiv (vshader, GL_COMPILE_STATUS, &success);       // success or failure ???  if (success == 0) {    glGetShaderiv (vshader, GL_INFO_LOG_LENGTH, &ebytes);    log = memory_buffer_create (ebytes + 1);    if (log == 0) { return (CORE_ERROR_MEMORY_ALLOCATION); }    glGetShaderInfoLog (vshader, ebytes, NULL, (GLchar*)log);    error = file_log_c08 (log);    memory_buffer_destroy (log);    memory_buffer_destroy (buffer);    memory_buffer_destroy (vsource);    memory_buffer_destroy (psource);    return (CORE_ERROR_INTERNAL);  }//// compile pixel shader and test for error message//  glCompileShader (pshader);                                  // compile pixel shader  glGetShaderiv (pshader, GL_COMPILE_STATUS, &success);       // success or failure ???  if (success == 0) {    glGetShaderiv (pshader, GL_INFO_LOG_LENGTH, &ebytes);    log = memory_buffer_create (ebytes + 1);    if (log == 0) { return (CORE_ERROR_MEMORY_ALLOCATION); }    glGetShaderInfoLog (pshader, ebytes, NULL, (GLchar*)log);    error = file_log_c08 (log);    memory_buffer_destroy (log);    memory_buffer_destroy (buffer);    memory_buffer_destroy (vsource);    memory_buffer_destroy (psource);    return (CORE_ERROR_INTERNAL);  }//// create empty "program object"//  program = glCreateProgram ();                              // create "program object"//// attach vertex-shader and pixel-shader to this "program object"//  glAttachShader (program, vshader);                         // attach vertex shader to program  glAttachShader (program, pshader);                         // attach pixel shader to program//// establish://   - vertex structure component types and offsets//   - generic vertex attribute variables//   - uniform variables [and others?]//   - other shader stuff//  error = ig_shader_setup (program, vshader, pshader, 0);  if (error < 0) { return (error); }//// link vertex-shader and pixel-shader in this "program object"//  char* logc = (char*)log;  glLinkProgram (program);                                  // link program object  glGetProgramiv (program, GL_LINK_STATUS, &success);       // success or failure ???  if (success == 0) {    glGetProgramiv (program, GL_INFO_LOG_LENGTH, &ebytes);    log = memory_buffer_create (ebytes + 1);    if (log == 0) { return (CORE_ERROR_MEMORY_ALLOCATION); }    glGetProgramInfoLog (program, ebytes, NULL, (GLchar*)log);    logc = (char*)log;    error = file_log_c08 (log);    memory_buffer_destroy (log);    memory_buffer_destroy (buffer);    memory_buffer_destroy (vsource);    memory_buffer_destroy (psource);    return (CORE_ERROR_INTERNAL);  }//// attempt to validate this program-object (try to validate vertex-shader and pixel-shader in this program-object)//  glValidateProgram (program);  glGetProgramiv (program, GL_VALIDATE_STATUS, &success);  if (success == 0) {    glGetProgramiv (program, GL_INFO_LOG_LENGTH, &ebytes);    log = memory_buffer_create (ebytes + 1);    if (log == 0) { return (CORE_ERROR_MEMORY_ALLOCATION); }    glGetProgramInfoLog (program, ebytes, NULL, (GLchar*)log);    error = file_log_c08 (log);    memory_buffer_destroy (log);    memory_buffer_destroy (buffer);    memory_buffer_destroy (vsource);    memory_buffer_destroy (psource);    return (CORE_ERROR_INTERNAL);  }//// tell GPU to activate our program-object (our vertex-shader and pixel-shader)//  glstate.active_vshader = vshader;  glstate.active_pshader = pshader;  glstate.active_program = program;  igstate.active_shaders = program;  igstate.shaderprogram = program;//// make program active (GPU executes shader rather than current shaders --- or default fixed pipeline)//  glUseProgram (program);  glGetShaderiv (vshader, GL_INFO_LOG_LENGTH, &vsbytes);  glGetShaderiv (pshader, GL_INFO_LOG_LENGTH, &psbytes);  glGetProgramiv (program, GL_INFO_LOG_LENGTH, &prbytes);  glGetShaderInfoLog (vshader, maxbytes, &readbytes, (GLchar*)buffer);  glGetShaderInfoLog (pshader, maxbytes, &readbytes, (GLchar*)buffer);  glGetProgramInfoLog (program, maxbytes, &readbytes, (GLchar*)buffer);//// load and install any textures required for this shader//// [special-purpose texture-map/normal-map loading code snipped]////  GLuint texid;  glGenTextures (1, &texid);  glstate.texid_texturemap = texid;                                   // remember OpenGL texture-object ID #//// set-up the necessary textures for texture/height/normal/relief/parallax/distance/occlusion/displacement mapping (normal-tweaking tricks in tangent-space)//// first a simple texture map to apply to surface//  glActiveTexture (GL_TEXTURE0);                                      // set active texture unit # = 0  glBindTexture (GL_TEXTURE_2D, glstate.texid_texturemap);            // attach the "texturemap" texture to texture-unit #0  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmap);//// second a height-map in the A channel and a normal-map in the RGB channels//  glGenTextures (1, &texid);  glstate.texid_surfacemap = texid;                                   // remember OpenGL texture-object ID #  glActiveTexture (GL_TEXTURE1);                                      // set active texture unit # = 1  glBindTexture (GL_TEXTURE_2D, glstate.texid_surfacemap);            // attach the "surfacemap" texture to texture-unit #1  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, swidth, sheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, smap);  glActiveTexture (GL_TEXTURE0);                                      // set active texture unit # = 0 == default-location//// see if we can verify our attributes//  glstate.index_position     = glGetAttribLocation (program, "ig_position");     // position  glstate.index_tcoord       = glGetAttribLocation (program, "ig_tcoord");       // tcoord  glstate.index_up           = glGetAttribLocation (program, "ig_up");           // up-vector AKA zenith-vector AKA normal-vector  glstate.index_color        = glGetAttribLocation (program, "ig_color");        // color == RGBA  glstate.index_east         = glGetAttribLocation (program, "ig_east");         // east-vector AKA tangent-vector  glstate.index_north        = glGetAttribLocation (program, "ig_north");        // north-vector AKA bitangent-vector  glstate.index_select       = glGetAttribLocation (program, "ig_select");       // select behavior in vertex-shader and pixel-shader  glstate.index_pcamera      = glGetUniformLocation (program, "ig_pcamera");     // uniform variable == camera position  glstate.index_plight0      = glGetUniformLocation (program, "ig_plight0");     // uniform variable == light0 position  glstate.index_plight1      = glGetUniformLocation (program, "ig_plight1");     // uniform variable == light1 position  glstate.index_plight2      = glGetUniformLocation (program, "ig_plight2");     // uniform variable == light2 position  glstate.index_texturemap   = glGetUniformLocation (program, "ig_texturemap");  // texture-map #0 == texture-unit #0  glstate.index_surfacemap   = glGetUniformLocation (program, "ig_surfacemap");  // texture-map #1 == texture-unit #1//// NOTE: We do not assign values to pcamera, plight0, plight1, plight2 here,// because they must be set every frame (since they can be moved every frame).// However, we do assign values to texturemap, surfacemap, [foldingmap], [steppermap],// because they remain fixed [probably] as long as these shaders remain installed.//  glUniform1i (glstate.index_texturemap, 0);            // specify texture unit # that contains "texturemap"  glUniform1i (glstate.index_surfacemap, 1);            // specify texture unit # that contains "surfacemap"//// If we execute the rest of this function (below),// we cannot switch back to default-pipeline processing// and THEN back to this program (cuz it has been trashed)!//// Therefore, we really should not detach and delete these resource,// we should do that when the program is done executing (to clean up).//  if (1) {    glDetachShader (program, vshader);    glDetachShader (program, pshader);    glDeleteShader (vshader);    glDeleteShader (pshader);    glDeleteProgram (program);  }  memory_buffer_destroy (log);  memory_buffer_destroy (buffer);  memory_buffer_destroy (vsource);  memory_buffer_destroy (psource);}



//// the following is the guts of function ig_shader_setup() --- called from the other code//cpu  ig_shader_setup (cpu program, cpu vshader, cpu pshader, cpu options) {//// [snip internal setup code]//// get offset to each element in ig_vertex32 structure (vertex structure we put into VBO)//  u08* base = (u08*)&vertex;  u08* offsetp = (u08*)((u08*)&vertex.position - (u08*)base);           // 0x0000 to 0x000B ::: 3 * f32 position.xyz  u08* offsett = (u08*)((u08*)&vertex.tcoords - (u08*)base);            // 0x000C to 0x000F ::: 2 * u16 tcoord.st  u08* offsetu = (u08*)((u08*)&vertex.up - (u08*)base);                 // 0x0010 to 0x0018 ::: 2 * f32 up.xy  u08* offsetc = (u08*)((u08*)&vertex.coloru16[0] - (u08*)base);        // 0x0018 to 0x001F ::: 4 * u16 color.rgba  u08* offsete = (u08*)((u08*)&vertex.east - (u08*)base);               // 0x0020 to 0x002F ::: 4 * f32 east.xyz + up.z  u08* offsetn = (u08*)((u08*)&vertex.north - (u08*)base);              // 0x0030 to 0x003B ::: 3 * f32 north.xyz  u08* offsets = (u08*)((u08*)&vertex.selectu08[0] - (u08*)base);       // 0x003C to 0x003F ::: 4 * u08 select.xyzw//// define vertex attributes --- each corresponds to one component of the vertex structure we put into the VBO//  glVertexAttribPointer (1, 2, GL_UNSIGNED_SHORT, 1, vbytes, offsett);  // 2 * u16 == tcoord.st  glVertexAttribPointer (2, 2, GL_FLOAT, 0, vbytes, offsetu);           // 2 * f32 == up.xy  glVertexAttribPointer (3, 4, GL_UNSIGNED_SHORT, 1, vbytes, offsetc);  // 4 * u16 == color  glVertexAttribPointer (4, 4, GL_FLOAT, 0, vbytes, offsete);           // 4 * f32 == east.xyz + up.z  glVertexAttribPointer (5, 3, GL_FLOAT, 0, vbytes, offsetn);           // 3 * f32 == north.xyz  glVertexAttribPointer (6, 4, GL_UNSIGNED_BYTE, 1, vbytes, offsets);   // 4 * u08 == select.xyzw  glVertexAttribPointer (0, 3, GL_FLOAT, 0, vbytes, offsetp);           // 3 * f32 == position (must be executed LAST)//// enable every vertex attribute --- evidentally not needed (!!!!!  until we implement long AND short (halfsize) vertices  !!!!!)//  glEnableVertexAttribArray (0);      // enable vertex position  glEnableVertexAttribArray (1);      // enable vertex tcoords  glEnableVertexAttribArray (2);      // enable vertex up-vector  glEnableVertexAttribArray (3);      // enable vertex color  glEnableVertexAttribArray (4);      // enable vertex east-vector  glEnableVertexAttribArray (5);      // enable vertex north-vector  glEnableVertexAttribArray (6);      // enable vertex select-behavior//  glEnableVertexAttribArray (0);      // enable vertex position//// just curious whether the following function exist and function//  void* attr00 = 0;  void* attr01 = 0;  void* attr02 = 0;  void* attr03 = 0;  void* attr04 = 0;  void* attr05 = 0;  void* attr06 = 0;  glGetVertexAttribPointerv (0, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr00);  glGetVertexAttribPointerv (1, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr01);  glGetVertexAttribPointerv (2, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr02);  glGetVertexAttribPointerv (3, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr03);  glGetVertexAttribPointerv (4, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr04);  glGetVertexAttribPointerv (5, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr05);  glGetVertexAttribPointerv (6, GL_VERTEX_ATTRIB_ARRAY_POINTER, (GLvoid**)&attr06);  error = glGetError ();//// assocatiates attribute variable names in vertex shader with vertex structure components//  glBindAttribLocation (program, 0, "ig_position");     // 0 == position  glBindAttribLocation (program, 1, "ig_tcoord");       // 1 == tcoord  glBindAttribLocation (program, 2, "ig_up");           // 2 == up-vector  glBindAttribLocation (program, 3, "ig_color");        // 3 == color  glBindAttribLocation (program, 4, "ig_east");         // 4 == east-vector  glBindAttribLocation (program, 5, "ig_north");        // 5 == north-vector  glBindAttribLocation (program, 6, "ig_select");       // 6 == select  return (0);}


cpu ig_batch_draw (cpu batchid, cpu mode) {//// #######################################// THE FOLLOWING CODE SHOULD NOT BE NEEDED// #######################################//// get offset to each element in ig_vertex32 structure (vertex structure we put into VBO)//  ig_vertex32 vertex;  cpu vbytes = sizeof(ig_vertex32);  u08* base = (u08*)&vertex;  u08* offsetp = (u08*)((u08*)&vertex.position - (u08*)base);          // 0x0000 to 0x000B ::: 3 * f32 position.xyz  u08* offsett = (u08*)((u08*)&vertex.tcoords - (u08*)base);           // 0x000C to 0x000F ::: 2 * u16 tcoord.st  u08* offsetu = (u08*)((u08*)&vertex.up - (u08*)base);                // 0x0010 to 0x0018 ::: 2 * f32 up.xy  u08* offsetc = (u08*)((u08*)&vertex.coloru16[0] - (u08*)base);       // 0x0018 to 0x001F ::: 4 * u16 color.rgba  u08* offsete = (u08*)((u08*)&vertex.east - (u08*)base);              // 0x0020 to 0x002F ::: 4 * f32 east.xyz + up.z  u08* offsetn = (u08*)((u08*)&vertex.north - (u08*)base);             // 0x0030 to 0x003B ::: 3 * f32 north.xyz  u08* offsets = (u08*)((u08*)&vertex.selectu08[0] - (u08*)base);      // 0x003C to 0x003F ::: 4 * u08 select.xyzw//// define vertex attributes --- each corresponds to one component of the vertex structure we put into the VBO////  glVertexAttribPointer (0, 3, GL_FLOAT, 0, vbytes, offsetp);        // 3 * f32 == position.xyz (must be executed LAST)  glVertexAttribPointer (1, 2, GL_UNSIGNED_SHORT, 1, vbytes, offsett); // 2 * u16 == tcoord.st  glVertexAttribPointer (2, 2, GL_FLOAT, 0, vbytes, offsetu);          // 2 * f32 == up.xy  glVertexAttribPointer (3, 4, GL_UNSIGNED_SHORT, 1, vbytes, offsetc); // 4 * u16 == color  glVertexAttribPointer (4, 4, GL_FLOAT, 0, vbytes, offsete);          // 4 * f32 == east.xyz + up.z  glVertexAttribPointer (5, 3, GL_FLOAT, 0, vbytes, offsetn);          // 3 * f32 == north.xyz  glVertexAttribPointer (6, 4, GL_UNSIGNED_BYTE, 1, vbytes, offsets);  // 4 * u08 == select.xyzw  glVertexAttribPointer (0, 3, GL_FLOAT, 0, vbytes, offsetp);          // 3 * f32 == position (must be executed LAST)  error = glGetError ();//// enable every vertex attribute --- evidentally not needed (until we implement long AND short vertices)//  if (0) {    glEnableVertexAttribArray (0);      // enable vertex position    glEnableVertexAttribArray (1);      // enable vertex tcoords    glEnableVertexAttribArray (2);      // enable vertex up-vector    glEnableVertexAttribArray (3);      // enable vertex color    glEnableVertexAttribArray (4);      // enable vertex east-vector    glEnableVertexAttribArray (5);      // enable vertex north-vector    glEnableVertexAttribArray (6);      // enable vertex select-behavior//    glEnableVertexAttribArray (0);      // enable vertex position    error = glGetError ();  }////// OpenGL draw modes  - IG support ::: IG primitive//// GL_POINTS          - IG supports == IG_PRIMITIVE_POINT// GL_LINES           - IG supports == IG_PRIMITIVE_LINE// GL_TRIANGLES       - IG supports == IG_PRIMITIVE_TRIANGLE == IG_PRIMITIVE_SURFACE//// GL_LINE_STRIP      - no -------- but IG supports line strips with GL_LINES// GL_LINE_LOOP       - no -------- but IG supports line loops with GL_LINES//// GL_TRIANGLE_STRIP  - no// GL_TRIANGLE_FAN    - no// GL_QUAD            - no// GL_QUAD_STRIP      - no// GL_POLYGON         - no//// trying to disable our shaders for points and lines --- disables our shaders COMPLETELY and PERMANENTLY --- FIX THIS//  u32 activeshaders = igstate.active_shaders;  u32 shaderprogram = igstate.shaderprogram;  error = GL_TRIANGLES;  error = GL_LINES;  error = GL_POINTS;  switch (ptype) {    case IG_PRIMITIVE_TRIANGLE:      gmode = GL_TRIANGLES;      break;    case IG_PRIMITIVE_LINE:      gmode = GL_LINES;      break;    case IG_PRIMITIVE_POINT:      gmode = GL_POINTS;      break;    default:      gmode = GL_TRIANGLES;      break;  }//// draw IBO/VBO pair == draw batch//   - separate batches for points versus lines versus triangles/surfaces//  if (icount) {    glDrawElements (gmode, icount, GL_UNSIGNED_SHORT, 0);    error = glGetError();  }  return (0);}
You need to use the offsets with the pointerarray functions. As for the VBO side, just upload the whole array into glBufferData().
One of you other VBO experts will have to tell him how many things he does NOT need to do if he has no shaders (just lets the fixed function run). I have never run OpenGL without IBOs and VBOs or without vertex and pixel shaders, so I have no idea whatsoever how to advise about those situations! :-(
Wow, thanks for the code :) I'm studying it now. That probably takes a while, I never used some of the OpenGL calls.

I'm using (cg) shaders as well, so I have one more question about that, how to get the data in the shader? I guess the positions, texcoords and normals come in the "usual" way. But where to get other data, the tangents for example? Are they inside another texture coordinate channel?

-edit-
I see you are sending the data to parameters inside the shaders ("ig_position", "ig_tcoord", and so on). Are these uniform array parameters in your shader program? Could you show how you get these values back in your shader? Normally I use the "vertex", "normal" and "texcoord(s)" in my Cg shader, but I guess its a little different now.

greetings,
Rick

[Edited by - spek on April 7, 2007 1:20:49 PM]
If you look in the code, you will see references to "up", "east", "north". These are my way of saying "normal", "tangent", "bitangent" (or "binormal"). The names I choose are easy to visualize which direction they point relative to each other, that's all.

So when you look at the code, you will find the "east" (tangent) vector and "north" (bitangent/binormal) vector are in the vertex-structure, just like the "up" (normal) vector.

At the top of the "shader_setup" function you will see code that shows exactly what each of the vertex-structure elements is, how big it is, what type it is, and how the information about it is told to OpenGL (the glVertexAttribPointer functions and the code-section just above that finds the offsets of each of those vertex elements in the vertex-structure (which goes in the VBO) so OpenGL knows where each vertex element is in each vertex-structure.

You can mix "conventional" vertex component (position, normal, color, etc) with extra application-defined "vertex attributes", but I find that confusing. So I made *every* vertex component an application-defined "vertex attribute" - so everything is defined the same way. The vertex and pixel shaders the code refers to "igtan003.vs" and "igtan003.ps" also access two textures, one of which contains pixel-colors (as usual), while the other contains a normal-map with nx,ny,nz,h components. I removed the code that loads these two maps from memory because it is totally irrelevant code that you don't need to copy.

PS: My shaders are GLSL shaders, and I know nothing about Cg shaders. Therefore your questions that might have different answers for Cg shaders are totally outta my knowledge. Some of the code refers to the variable names in my shader code, but I'm not sure that is part of your question. I will send you the corresponding shader code by PM in case that helps you understand.

This topic is closed to new replies.

Advertisement