# Normal mapping using shaders in Open GL

Page 1 of 1

## 4 Replies - 3135 Views - Last Post: 29 July 2009 - 02:20 PMRate Topic: //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'http://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=117166&amp;s=5443dc3cdca23bf0287c93870e95dc2e&md5check=' + ipb.vars['secure_hash'], cur_rating: 0, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

### #1 Telestia

Reputation: 0
• Posts: 24
• Joined: 12-January 09

# Normal mapping using shaders in Open GL

Posted 27 July 2009 - 09:45 PM

Hey everyone, I'm having some problems with trying to figure out how to take an RGB texture and turn it into a normal vector using a shader program in Open GL and multi-texturing.

Here are my Vertex and Fragment programs. (Vertex first)

```uniform float lightRadius;

varying vec3 lightDir;
varying vec3 viewDir;

void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;

gl_TexCoord[1] = gl_MultiTexCoord1;

vec3 vertexPos = vec3(gl_ModelViewMatrix * gl_Vertex);

vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);
vec3 b = cross(n, t) * gl_MultiTexCoord1.w;

mat3 tbnMatrix = mat3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z);

lightDir = (gl_LightSource[0].position.xyz - vertexPos) / lightRadius;
lightDir = tbnMatrix * lightDir;

viewDir = -vertexPos;
viewDir = tbnMatrix * viewDir;
}

```

```uniform sampler2D colorMap;
uniform sampler2D normalMap;

varying vec3 lightDir;
varying vec3 viewDir;

void main()
{
vec3 l = lightDir;
float atten = max(0.0, 1.0 - dot(l, l));

l = normalize(l);

vec3 n = normalize(texture2D(normalMap, gl_TexCoord[1].st).xyz * 2.0 - 1.0);
vec3 v = normalize(viewDir);
vec3 h = normalize(l + v);

float nDotL = max(0.0, dot(n, l));
float nDotH = max(0.0, dot(n, h));
float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);

vec4 ambient = gl_FrontLightProduct[0].ambient * atten;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL * atten;
vec4 specular = gl_FrontLightProduct[0].specular * power * atten;
vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;

gl_FragColor = color * texture2D(colorMap, gl_TexCoord[0].st);
}

```

Also, here is the code that I have for my rendering, init, and such.
```
#include "GLView.h"

////////////////////////////////////////////////////////////////////////////
// Do not put any OpenGL code here. General guidence on constructors in
// general is to not put anything that can fail here either (opening files,
// allocating memory, etc.)
GLView::GLView(void) : _screenWidth(800), _screenHeight(600), _bFullScreen(false), _bAnimated(true)
{

}
void GLView::DrawFloor()
{
GLfloat floorsize = 20.0f;
GLfloat floorlevel = -0.4f;
GLfloat gridsize = 0.5f;

glBegin(GL_LINES);
for (GLfloat i = -floorsize; i <= floorsize; i += gridsize)
{
glVertex3f(i, floorlevel, floorsize);
glVertex3f(i, floorlevel, -floorsize);

glVertex3f(floorsize, floorlevel, i);
glVertex3f(-floorsize, floorlevel, i);
}
glEnd();

}
void GLView::PollKeyboard()
{
static CStopWatch timer;
float fTimePassed = timer.GetElapsedSeconds();
timer.Reset();
if (GetAsyncKeyState(VK_UP))
{
Camera.MoveForward(3.0f * fTimePassed);
}
if (GetAsyncKeyState(VK_DOWN))
{
Camera.MoveForward(-3.0f * fTimePassed);
}
if (GetAsyncKeyState(VK_LEFT))
{
Camera.RotateWorld( m3dDegToRad(60.0f) * fTimePassed, 0.0f, 1.0f, 0.0f);
}
if (GetAsyncKeyState(VK_RIGHT))
{
Camera.RotateWorld( m3dDegToRad(-60.0f) * fTimePassed, 0.0f, 1.0f, 0.0f);
}

}

///////////////////////////////////////////////////////////////////////////////
// OpenGL related startup code is safe to put here. Load textures, etc.
void GLView::Initialize(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);

GLfloat noLight[4] = {0.0f, 0.0f, 0.0f, 0.0f};

GLfloat BrightLight[] = {1.0f, 1.0f, 1.0f, 1.0f};

GLfloat dimLight[] = {0.2, 0.2f, 0.2f, 1.0f};

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, dimLight);
glLightfv(GL_LIGHT0, GL_AMBIENT, dimLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, BrightLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, BrightLight);
glEnable(GL_LIGHT0);

glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glGenTextures(2, textures);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);

BoxList = glGenLists(1);

glNewList(BoxList, GL_COMPILE);

//back
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10.0f, -10.0f, -10.0f);
glTexCoord2f(5.0f, 0.0f);
glVertex3f(10.0f, -10.0f, -10.0f);
glTexCoord2f(5.0f, 5.0f);
glVertex3f(10.0f, 10.0f, -10.0f);
glTexCoord2f(0.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, -10.0f);

//right
glTexCoord2f(0.0f, 0.0f);
glVertex3f(10.0f, -10.0f, -10.0f);
glTexCoord2f(5.0f, 0.0f);
glVertex3f(10.0f, -10.0f, 10.0f);
glTexCoord2f(5.0f, 5.0f);
glVertex3f(10.0f, 10.0f, 10.0f);
glTexCoord2f(0.0f, 5.0f);
glVertex3f(10.0f, 10.0f, -10.0f);

//front
glTexCoord2f(0.0f, 0.0f);
glVertex3f(10.0f, -10.0f, 10.0f);
glTexCoord2f(5.0f, 0.0f);
glVertex3f(-10.0f, -10.0f, 10.0f);
glTexCoord2f(5.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, 10.0f);
glTexCoord2f(0.0f, 5.0f);
glVertex3f(10.0f, 10.0f, 10.0f);

//left
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10.0f, -10.0f, 10.0f);
glTexCoord2f(5.0f, 0.0f);
glVertex3f(-10.0f, -10.0f, -10.0f);
glTexCoord2f(5.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, -10.0f);
glTexCoord2f(0.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, 10.0f);

//top
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10.0f, 10.0f, -10.0f);
glTexCoord2f(5.0f, 0.0f);
glVertex3f(10.0f, 10.0f, -10.0f);
glTexCoord2f(5.0f, 5.0f);
glVertex3f(10.0f, 10.0f, 10.0f);
glTexCoord2f(0.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, 10.0f);

//bottom
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10.0f, -10.0f, 10.0f);
glTexCoord2f(5.0f, 0.0f);
glVertex3f(10.0f, -10.0f, 10.0f);
glTexCoord2f(5.0f, 5.0f);
glVertex3f(10.0f, -10.0f, -10.0f);
glTexCoord2f(0.0f, 5.0f);
glVertex3f(-10.0f, -10.0f, -10.0f);

glEnd();

glEndList();
glEnable(GL_TEXTURE_2D);

glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);

}
{

BYTE* pBits;
int nWidth, nHeight;
if (pBits == NULL)
{
MessageBox(NULL, "Can't find texture file", szFileName, MB_OK);
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, pBits);
free (pBits);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
{

GLbyte* pBits;
int nWidth, nHeight;
GLint component;
GLenum enumm;
pBits = gltLoadTGA(szFileName, &nWidth, &nHeight, &component, &enumm);
if (pBits == NULL)
{
MessageBox(NULL, "Can't find texture file", szFileName, MB_OK);
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, component, nWidth, nHeight, 0, enumm, GL_UNSIGNED_BYTE, pBits);
free (pBits);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

///////////////////////////////////////////////////////////////////////////////
// Do your cleanup here. Free textures, display lists, buffer objects, etc.
void GLView::Shutdown(void)
{

}

///////////////////////////////////////////////////////////////////////////////
// This is called at least once and before any rendering occurs. If the screen
// is a resizeable window, then this will also get called whenever the window
// is resized.
void GLView::Resize(GLsizei nWidth, GLsizei nHeight)
{
glViewport(0, 0, nWidth, nHeight);

glMatrixMode(GL_PROJECTION);
gluPerspective(35.0f, float(nWidth)/ float(nHeight), 1.0f, 1000.0f);

glMatrixMode(GL_MODELVIEW);

}

///////////////////////////////////////////////////////////////////////////////
// Render a frame. The owning framework is responsible for buffer swaps,
// flushes, etc.
void GLView::Render(void)
{
static CStopWatch Timer;
float yrot = Timer.GetElapsedSeconds() * 60;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

PollKeyboard();

glPushMatrix();
Camera.ApplyCameraTransform();

GLfloat whereLight[] = {0.0f, 1.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, whereLight);

glDisable(GL_LIGHTING);

glPushMatrix();
glTranslatef(whereLight[0], whereLight[1], whereLight[2]);
glColor3f(1.0f, 1.0f, 1.0f);
gltDrawSphere(0.1f, 26, 13);
glPopMatrix();

glColor3f(0.0f, 1.0f, 0.0f);
DrawFloor();

glTranslatef(0.0f, 1.5f, 0.0f);
glScalef(0.2f, 0.2f, 0.2f);
glColor3f(1.0f, 1.0f, 1.0f);
glActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE1);
glUniform1f(iIndex, 10.0f);
glCallList(BoxList);
glUseProgramObjectARB(NULL);

glPopMatrix();

}

```

I have my color map on texture 0 and my normal map on texture 1. When I run the programs the texture just get really dark and I can't figure out what might be wrong with it. Any help would be much appreciated.

Is This A Good Question/Topic? 0

## Replies To: Normal mapping using shaders in Open GL

### #2 wildgoose

• D.I.C Regular

Reputation: 67
• Posts: 468
• Joined: 29-June 09

## Re: Normal mapping using shaders in Open GL

Posted 29 July 2009 - 11:06 AM

You're building floor and walls! Don't need to calculate your normal to the face. You can hard code it. The normal is perpendicular to the face!

You're using OpenGL so -Z is into scene! X is left, and assumiing Y is up!
Floor {0,1,0} Y is up!
Back wall { 0, 0, 1 }
Right wall { -1, 0, 0 }
Left wall {1, 0, 0 }

By the way. Textures don't turn into normals. The vertex mesh does! However the normal is used in conjunction with a light source and the pixel color to illuminate those pixels! But that's typically done in a shader.

This post has been edited by wildgoose: 29 July 2009 - 11:10 AM

### #3 Tom9729

• Segmentation fault

Reputation: 180
• Posts: 2,641
• Joined: 30-December 07

## Re: Normal mapping using shaders in Open GL

Posted 29 July 2009 - 12:59 PM

GLSL example here...
http://codesampler.c...ng_bump_mapping

### #4 Telestia

Reputation: 0
• Posts: 24
• Joined: 12-January 09

## Re: Normal mapping using shaders in Open GL

Posted 29 July 2009 - 02:17 PM

wildgoose, on 29 Jul, 2009 - 10:06 AM, said:

You're building floor and walls! Don't need to calculate your normal to the face. You can hard code it. The normal is perpendicular to the face!

I'm sorry, I don't think I explained what I'm doing well enough. I have 2 textures, one for the color map, and the other is the normal map. The second one is the same as the first only all the colors are either red, green, or blue. I'm trying to use a color lookup on the second texture, or texture unit one, and make that color into the normal for that particular vertex.

I'll have to take a look at the code Tom9792, I think that pretty much what I'm looking for.

### #5 wildgoose

• D.I.C Regular

Reputation: 67
• Posts: 468
• Joined: 29-June 09

## Re: Normal mapping using shaders in Open GL

Posted 29 July 2009 - 02:20 PM

Ah, you're texture bump mapping!