Monday, March 26

A Little Texturing Tutorial

Well its been a few weeks but I can proudly say I've gotten a whole bunch of shaders done lately.  With that said, I'm much more confident texturing with shaders now, so I'm going to give a simple tutorial on how to slap on some textures for your models.

Lets start with the basics, you're going to need a variable to hold the texture itself. (Make sure the texture is in your project file!)  Preferably this variable should be off in your global header somewhere to keep your main from getting cluttered.

static GLuint textureName;

This variable holds the information for whichever texture you choose.  Loading the texture is just as simple.  **Make sure you have all your DevIL libs included, and initialized**  DevIL pretty much takes care of this step for you with:

textureName = ilutGLLoadImage("nameOfTextureFile.extension");

You can throw this function in main or maybe somewhere in your code where it can be dynamically changed on the fly.  Its up to you, but for this tutorial the texture is loaded in main as that is all which is necessary.

Next you'll want to make sure all your CG stuff is initialized properly.  I'll assume you know the basics of setting up a context/program/profile etc so I'll just show you how to get the parameter.  Note that it can be a vertex or fragment parameter, it doesn't make a big difference for a simple program like this.

cgVertexParam_textureMap = cgGetNamedParameter(vertexProgram, "textureMap");

Now that you have the texture initialized, your shader will need to know where to get the texture coordinates.  These come from the actual drawing of your shape/obj.  Somewhere in your code you must have 

glTexCoord2f(0.0,0.0);

for each texture coordinate your shape/obj has.  This is crucial because your shader program will use these valuables when it has the correct semantic.

There's one more important thing to add in your main code, but I'm going to jump ahead to the shader itself for now.  In the vertex or fragment shader, you will need a variable called 

float2 texCoord : TEXCOORD0

This variable is varying, so it will automatically take in the values you specified with glTexCoord2f().

If you put this variable in your vertex shader, you should just pass it along to the fragment shader by specifying an out variable like so

out float2 oTexCoord : TEXCOORD0

Now in your fragment shader, you will need both the texCoord variable and a new one to specify the textureMap which the shader will use.  Remember that textureMap parameter we set?  Now it finally gets to be part of the action.   The variable goes as such:

uniform sampler2D textureMap : TEXUNIT0

The uniform states it is a constant variable set by the program, the sampler2D is what grabs the actual texture, and TEXUNIT0 tell the shader which texture is going to be applied.

Lets go back to the program itself for a moment, and set the texture that will be applied in the shader.  This code should be in the display function after you bind your programs and enable the shader profiles.

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D,textureMap);


These two lines of code tell the shader which texture is being used, and then binds it to the textureMap variable.  Note the TEXTURE0 will match up with TEXUNIT0 in your fragment shader.  **I do not think glEnable(TEXTURE_2D) is necessary because the shader itself handles all the texturing instead of OpenGL**


Now back to the fragment shader to put it all together.  As long as there is some form of lighting in your program (ambient is fine) then the following code should make your shape/obj nice and pretty:


float3 mappedObj = tex2D(textureMap, texCoord);


This applies the texture you loaded and matches it up with the texture coordinates you have specified.  Now you can multiply this with your ambient colour (make sure its white) and output your final colour.  Voila, you have a beautifully textured object; not that difficult eh?


**As a side note, if you want to blend multiple textures its as easy as setting more texture parameters, then lerping them in the fragment shader.**


:D

No comments:

Post a Comment