Translating vertex shader

Hi there,

right now I’m in the middle of translating a shader from GPU assembler to glsl. I’ve just started with glsl a week ago, and all the stuff I’ve read about it is this article Article At NeHe's and some of the links provided there, so please dont flame too hard if this is just some simple thing I’m over looking :slight_smile:

Its a vertex shader for bone animation, 4 bones per vertex. In the assebler version it indexes the required matrix for the transformations like so:

ATTRIB index = vertex.attrib[3];<- creates variable
...
MUL R4, index, constant.y;<-constant.y=3
ARL A0.x, R4.y; <- creates the offset address
DP3 R0.x, matrix[A0.x].xyzx, normal.xyzx; <-indexes the matrix, which was created like so
PARAM matrix[87] = { program.local[0..86] };

but how do the same with hlsl?
when i create
attribute ivec4 Indexes;
the shader just doesnt compile, but with
attribute vec4 Indexes;
it doesnt compile when i add the second line here:
vec4 RealIndexes=Indexes*3;
Temp1Norm.x = dot(BoneMatrix[RealIndexes.y].xyz,Normal.xyz);<-this one
Well, that seems logical, since im using a float to lookup in the array. But how else do i do that?

In other words: how do I create a variable & pass a value to it from my application so that i can use it to index an entry in an array?

Ok, now with the help of some other forums & online material, I’ve got a bit further. Now the actual problem is sending the attributes as arrays from a VBO. I’ve written a little test shader to keep things simple until I solve this problem. Heres what I have so far for the test:

Heres the extension initialization:

GLUX_LOAD(GL_ARB_vertex_program);
GLUX_LOAD(GL_ARB_vertex_buffer_object);
GLUX_LOAD(GL_EXT_draw_range_elements);
GLUX_LOAD(GL_ARB_shader_objects);
GLUX_LOAD(GL_ARB_shading_language_100);
GLUX_LOAD(GL_ARB_vertex_shader);
GLUX_LOAD(GL_ARB_fragment_shader);

The variables:

int ShaderColor[4],ShaderIndex,ShaderVertex;
unsigned ShaderVBO,ShaderVertexVBO;

The initialization:

glShaderSourceARB(ProgramObject, 1, (const GLcharARB **)&ShaderSource, &length);
//i know it compiles ok, cos if i dont use the VBOs everything runs fine
//that is if i use just plain old glVertex3f & glColor to pass the index
glAttachObjectARB(ShaderObject, ProgramObject);
glLinkProgramARB(ShaderObject);

for(int i=0;i<4;i++)
{
char txt[256];
sprintf(txt,"Color[%i]",i);
ShaderColor[i]=glGetUniformLocationARB(ShaderObject, txt);
if(ShaderColor[i]==-1)
MessageBox(NULL,txt,"Cant Get Uniform",MB_OK);
}

glGenBuffersARB(1,&ShaderVBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, ShaderVBO);
float TempData[4];
TempData[0]=0.0f;
TempData[1]=1.0f;
TempData[2]=2.0f;
TempData[3]=3.0f;
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 4*sizeof(float),TempData, GL_STATIC_DRAW_ARB);
if( glGetError() != GL_NO_ERROR )
{
MessageBox(NULL,"Error!","VBO",MB_OK);
}

glGenBuffersARB(1,&ShaderVertexVBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, ShaderVertexVBO);
float VertData[16];
VertData[0]=0.0f;
VertData[1]=0.0f;
VertData[2]=0.0f;
VertData[3]=1.0f;

VertData[4]=800.0f;
VertData[5]=0.0f;
VertData[6]=0.0f;
VertData[7]=1.0f;

VertData[8]=800.0f;
VertData[9]=600.0f;
VertData[10]=0.0f;
VertData[11]=1.0f;

VertData[12]=0.0f;
VertData[13]=600.0f;
VertData[14]=0.0f;
VertData[15]=1.0f;

glBufferDataARB(GL_ARRAY_BUFFER_ARB, 4*4*sizeof(float),VertData, GL_STATIC_DRAW_ARB);
if( glGetError() != GL_NO_ERROR )
{
MessageBox(NULL,"Error!","VBO",MB_OK);
}

ShaderIndex=myWeaponShader->GetAttribIndexByName("Index");
//allways returns 1, as it should be?
if(ShaderIndex==-1)
{
MessageBox(NULL,"Index","Cant Find Attribute",MB_OK);
}

ShaderVertex=myWeaponShader->GetAttribIndexByName("Vertex");
//allways returns 2, as it should be?
if(ShaderVertex==-1)
{
MessageBox(NULL,"Vertex","Cant Find Attribute",MB_OK);
}

The glsl shader:

uniform vec4 Color[4];
attribute float Index;
attribute vec4 Vertex;

void main(void)
{
	gl_FrontColor = Color[int(Index)];
	gl_Position = gl_ModelViewProjectionMatrix * Vertex;
}

And heres the rendering:

glUseProgramObjectARB(ShaderObject);
glEnableVertexAttribArrayARB(ShaderIndex);
glEnableVertexAttribArrayARB(ShaderVertex);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, ShaderVBO);
glVertexAttribPointerARB(ShaderIndex, 1 , GL_FLOAT, false, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, ShaderVertexVBO);
glVertexAttribPointerARB(ShaderVertex, 4 , GL_FLOAT, false, 0, NULL);

float TempColor[4];
TempColor[0]=0.0f;
TempColor[1]=0.0f;
TempColor[2]=0.0f;
glUniform4fvARB(ShaderColor[0], 4, TempColor);
TempColor[0]=1.0f;
TempColor[1]=1.0f;
TempColor[2]=0.0f;
glUniform4fvARB(ShaderColor[1], 4, TempColor);
TempColor[0]=0.0f;
TempColor[1]=1.0f;
TempColor[2]=0.0f;
glUniform4fvARB(ShaderColor[2], 4, TempColor);
TempColor[0]=0.0f;
TempColor[1]=0.0f;
TempColor[2]=1.0f;
glUniform4fvARB(ShaderColor[3], 4, TempColor);

glDrawArrays( GL_QUADS, 0, 4 );

glDisableVertexAttribArrayARB(ShaderIndex);
glDisableVertexAttribArrayARB(ShaderVertex);
glUseProgramObjectARB(0);

Can You spot what am I missing here? As You can see, it should just draw a quad all over the screen using the atrribute Vertex as the vertex position, and the attribyte Index to get a color from the uniform array. Which does work if rewrite to use glVertex for position and glColor for passing the index, but i cant get it to work with VBO (or arrays, for that matter).

One of the attribute indices must be 0, otherwise the drawing command will not invoke the vertex shader.
If the automatic attribute binding didn’t do that, you must bind it explicitly.

Check issue 9 in the ARB_vertex_program spec:

(9) In unextended OpenGL, calling Vertex() specifies a vertex and causes
vertex transformation operations to be performed on the vertex. Should
there be an equivalent method to specify a vertex using generic vertex
attributes? If so, how should this be accomplished?

  RESOLVED:  Setting generic vertex attribute zero will always specify a
  vertex.  Vertex*(...) and VertexAttrib*(0,...) are specified to be
  equivalent, whether or not vertex program mode is enabled.  Allowing
  generic vertex attribute zero to specify a vertex allows applications to
  write vertex programs that use only generic attributes; otherwise,
  applications would have had to use Vertex() to provoke vertex
  processing.

Thanks a lot, man! No, really, thanks :slight_smile: This little thing had me going mad for about a week! The test shader worked, now I hope the real one does, I’m off to code it right now :wink:

Thanks again :wink:

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.