Texture mapping w/vertex & fragment shaders

Looking for simple example code triple (host C, vertex & fragment) for simple texture mapping. Here’s what I’ve tried, but it’s not making it (hope the long post is OK!):

C snippet for creating the texture:
glBindTexture(GL_TEXTURE_2D, g_textureID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 1, 1024, 1024, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, textureBuffer);
free(TextureBuffer);

C Render code:
void render( void )
{
// Clear the screen and the depth buffer
// glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
setShaderConstants();
glBindProgramARB( GL_VERTEX_PROGRAM_ARB, g_vertexProgramID );
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, g_fragmentProgramID );
glEnable( GL_VERTEX_PROGRAM_ARB );
glEnable( GL_FRAGMENT_PROGRAM_ARB );
glBindTexture( GL_TEXTURE_2D, g_textureID );
glInterleavedArrays( GL_C4UB_V3F, 0, g_quadVertices );
glDrawArrays( GL_QUADS, 0, 4 );
glDisable( GL_FRAGMENT_PROGRAM_ARB );
glDisable( GL_VERTEX_PROGRAM_ARB );
SwapBuffers( g_hDC );
}

Vertex program:
!!ARBvp1.0

Constant Parameters

PARAM mvp[4] = { state.matrix.mvp }; # modelview projection matrix
PARAM constColor = program.env[0]; # constant color (defined by the application)

Per-vertex inputs

ATTRIB inPosition = vertex.position;
ATTRIB inColor = vertex.color;

Per-vertex outputs

OUTPUT outPosition = result.position;
OUTPUT outColor = result.color;
MOV outPosition, vertex.position;
MOV result.texcoord, vertex.texcoord;
MOV outColor, inColor;
END

And fragment shader:

!!ARBfp1.0
MOV result.color, fragment.texcoord[0];
END

So what am I doing wrong? It renders at 900 frames per second into a 1kx1k image, but the result is blank!

A related question - what turns the asm source into machine code and who provides it? Did it come with the ATI DX 9 RC0 driver I installed?

Scott

Firstly, you’re not specifying any texture coordinates or generating them in the vertex program. The GL_C4UB_V3F flag for glInterleavedArrays only specifies a vertex position and a color.

Secondly, you’re not transforming vertex positions to clip coordinates in the vertex program. You have to multiply vertex.position by your mvp parameter declared in the vertex program.

Finally, MOV result.color, fragment.texcoord[0] pretty much does what the opcode name implies. It moves the interpolated texture coordinates to the final output color register. This is most likely not what you want. To sample a texture use the TEX instruction, e.g. TEX result.color, fragment.texcoord[0], texture[0], 2D performs a 2D texture lookup using texture coordinate set 0 and texture sampler stage 0.

A related question - what turns the asm source into machine code and who provides it?

The OpenGL driver translates the programs. In your case, ATI provides these drivers.

edit: typos, as usual

[This message has been edited by Asgard (edited 11-19-2002).]

Thank you for such a prompt response Asgard.

> you’re not specifying any texture coordinates or generating them in the vertex program

What I’m shooting for is 2 triangles covering the output buffer of 1kx1k pixels and the texture mapped directly to that - 1:1 mapping of texels to output pixels. I’m trying to keep input bandwidth to a minimum so I want to generate texture coords in the vertex pgm. That’s what I was trying to accomplish with MOV result.texcoord, vertex.texcoord;, which is now MOV result.texcoord, vertex.position;

> Secondly, you’re not transforming vertex positions to clip coordinates in the vertex program.

This isn’t your typical OpenGL application I’m trying to use the R9700 as a general purpose array processor.

Since I’m shooting for 1:1 texel : pixel mapping, shouldn’t I be able to avoid this?

> MOV result.color, fragment.texcoord[0] pretty much does what the opcode name implies

OK, got that one. I’m moving in the right direction, since with TEX result.color, fragment.texcoord[0], texture[0], 2D I’m running at ~600 FPS, so it looks like it’s doing a texture lookup. It’s still black though

Scott

[This message has been edited by Mr. HDTV (edited 11-19-2002).]

How do the vertex coordinates of your quad look like? You’ll most likely still want to apply some sort of projection matrix.

The reason you’re probably not seeing anything is that your camera is either in the plane or behind the plane of the textured quad.

> How do the vertex coordinates of your quad look like?

Vertex g_quadVertices[] =
{
// r g b a x y z
{ 255, 255, 0, 255, -1.0f,-1.0f, 0.0f, }, // Bottom-Left, color = yellow
{ 255, 0, 0, 255, 1.0f,-1.0f, 0.0f, }, // Bottom-Right, color = red
{ 0, 255, 0, 255, 1.0f, 1.0f, 0.0f, }, // Top-Right, color = green
{ 0, 0, 255, 255, -1.0f, 1.0f, 0.0f }, // Top-Left, color = blue
};

If I replace (in the fragment shader) TEX result.color, fragment.texcoord[0], texture[0], 2D with MOV result.color, fragment.color;, I get a very nice 1kx1k output image that’s (moving clockwise from upper left) blue, green, red, yellow. This seems to tell me that everything other than the texture mapping is working OK.

Aside: odd behavior - the frame rate changes dramatically depending on screen alignment of the output image. Just by moving the output frame around I get 69x, 79x or 89x frames per second.

Scott

Update:
With the following as my fragment program:

!!ARBfp1.0
MOV result.color, fragment.texcoord[0];
END
I get what I’d expect: clockwise from lower left: black, green, yellow, red. So the texture coords are making it through OK to my fragment shader. For some reason the texels aren’t.

There’s something fundamental that I’m missing.

Is there someplace I can get sample code like the texture mapping example here http://www.codesampler.com/oglsrc.htm, but that uses vertex and fragment shaders?
Scott

Perhaps it’s my texture load proc. Here it is:

void loadTexture( void )
{
FILE *TextureFile;
int BytesRead;
char *TextureBuffer;

TextureFile = fopen("FOV12.raw", "r+b");
if (!TextureFile) {
    MessageBox( NULL, "Cannot open texture file Tex.raw", "ERROR",
                MB_OK | MB_ICONEXCLAMATION );
}

TextureBuffer = (char*)malloc(1024*1024);

BytesRead = fread(TextureBuffer, 1, 1024*1024, TextureFile);

if (BytesRead != 1024*1024) {
    MessageBox( NULL, "Didn't read the entire texture file Tex.raw", "ERROR",
                MB_OK | MB_ICONEXCLAMATION );
}

// thrown in as a test.  Makes no diff
for (int i=0; i<1024*1024; i++)
	TextureBuffer[i] = (char)0xff;

glGenTextures( 1, &g_textureID );

glBindTexture(GL_TEXTURE_2D, g_textureID);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_2D, 0, 1, 1024, 1024, 0,
			GL_LUMINANCE, GL_UNSIGNED_BYTE, TextureBuffer);

free(TextureBuffer);

}

Everything seems to succeed. Only strangeness is that the texture is 8-bit luma only.

Scott

[This message has been edited by Mr. HDTV (edited 11-19-2002).]

If you’re rendering a 1k x 1k image, then the efficiency of transforming the 4 vertices that build your triangles is not going to matter at all, as it’ll completely drown in the fill rate hit.

I don’t see you enabling the TEXTURE_2D target for texture unit 0 anywhere. Perhaps that’s why you’re not getting texels.

I don’t see you enabling the TEXTURE_2D target for texture unit 0 anywhere. Perhaps that’s why you’re not getting texels.

If an ARB_f_p fragment program is enabled, the texture enables are ignored.