PDA

View Full Version : faking standard opengl t&l with GL_NV_vertex_program



ScottManDeath
01-02-2002, 02:01 PM
Hi

I would like to replicate standard opengl's lighting calculation using vertex programs to modify the lightings color selecting. Instead of just linear interpolation between two vertices colors I would like to use a 1d texture map as a gradient(perhaps a 2d texture for additional specular gradients).
Texture coordinates would index the texture.
this would also be useful for doing toon shading. I tried it but i had some problems.
My goal is to use vertex and vertex state programs as easy and functional as gllightf...

for example standard t&l:
// scene positioning
// local viewer, local light, no attenuation
glLoadIdentity();
glTranslatef(scene pos)// based upon user input
glRotatef(scene rot)// -""-
// light in object coorinates
glLightf(light position)
...
...

// draw some object
glPushMatrix()
glRotatef(object yrot ...)
glutSoloidTeapot
glPopMatrix();
// another object
glPushMatrix()
glTranslatef(object pos ...)
glutSoloidTeapot
glPopMatrix();

using vertexprograms:

scene and object positioning using matrices

glLoadIdentity();
glTranslatef(scene pos)// based upon user input
glRotatef(scene rot)// -""-
// light in object coorinates

//using vertex state program to calc lights eye coordinates using current modelview matrix
glExecuteProgramNV(...,lightpos);
...
...
glEnable(GL_VERTEX_PROGRAM_NV);
glEnable(GL_TEXTURE_2d);
// draw some object
glBindTExture(material one gradient)
glPushMatrix()
glRotatef(object yrot ...)
glutSoloidTeapot
glPopMatrix();
// another object
glBindTExture(material two gradient)
glPushMatrix()
glTranslatef(object pos ...)
glutSoloidTeapot
glPopMatrix();

I tested it in a program where I could switch between opengl lighting and vertex program lighting, but I recognized that both results were unequal.the light moved with the scene but when i rotated the scene the diffuse lighting changed, wether i wanted to stay the object const within my scene space.

tracking of MODELVIEW_PROJECTION
MODELVIEW
MODELVIEW, INVERSE_TRANSPOSE
in the vertex state program i do following

matrix multiplication program paramter v[0] with modelview matrix and storing it in constant register


the vertex program
matrix multiplication v[OPOS] with MODELVIEWPROJECTION and storing it in o[HPOS]

matrix multiplication v[OPOS] with MODELVIEW and storing it in a temporary register

matrix mult v[NRML] with MODELVIEW_INVERSE_TRANSPOSE
set length to 1

vector vertex --> light
set length to 1

dot product normal with vertex-->light vector


use as o[TEX0].x // 1D texture clamping active; GL_DECAL environment linear (greyscale)gradient -> should be equal do standard opengl t&l

Can anyone help ??

ScottManDeath

Korval
01-02-2002, 06:12 PM
Can anyone help ??

Maybe you should show us the actual vertex program and the rest of your code rather than this pseudo-code. The actual bug is likely not in the code you've given us.

ScottManDeath
01-03-2002, 09:58 AM
[Hi

you are right, pseudo code seems not be very helpful
here are the important parts of my code.

I changed the light calculation form eye space to object space.

The vertex state program transform the light position v[0]
using the tracked modelview matrix temporary into eye space.

The vertex program uses the light position and converts it into object space by
applying the current inverse modelviewmatrix. then the diffuse dot product is
calculated by dotting the vertex' normal with the (normalized)vertex light vector
Now diffuse lighting works as espected. because I specified the lights psosition in the
current scene view space it stays as I move and rote the view .

For the specular part I have a problem. the specular highlight moves when I move the light or the object but not when
I rotate my scene view??

tracked matrices and program parameters:
(set up once after loading vertex program from disk)
// ModelViewProjection in c[0] to c[3]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,0,GL_MODELVIE W_PROJECTION_NV,GL_IDENTITY_NV);
// ModelView in c[4] to c[7]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,4,GL_MODELVIE W,GL_IDENTITY_NV);
// Modelview invers transposed in c[8] to c[11]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,8,GL_MODELVIE W,GL_INVERSE_TRANSPOSE_NV);
// Modelview invers in c[8] to c[11]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,12,GL_MODELVI EW,GL_INVERSE_NV);
// helpful numbers
glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV,95,0.0 f,0.5f,1.0f,2.0f);

Vertex State Program
!!VSP1.0

# lightposition to eye space
DP4 R1.x,v[0],c[4];
DP4 R1.y,v[0],c[5];
DP4 R1.z,v[0],c[6];
DP4 R1.w,v[0],c[7];
MOV c[16],R1;

END


Vertex program//not optimized
!!VP1.0
# c
# 0 MODELVIEW_PROJECTION_0
# 1 MODELVIEW_PROJECTION_1
# 2 MODELVIEW_PROJECTION_2
# 3 MODELVIEW_PROJECTION_3
# 4 MODEL_VIEW_0
# 5 MODEL_VIEW_1
# 6 MODEL_VIEW_2
# 7 MODEL_VIEW_3
# 8 MODEL_VIEW_INVERSE_TRANSPOSE_0
# 9 MODEL_VIEW_INVERSE_TRANSPOSE_1
# 10 MODEL_VIEW_INVERSE_TRANSPOSE_2
# 11 MODEL_VIEW_INVERSE_TRANSPOSE_3
# 12 MODEL_VIEW_INVERSE_0
# 13 MODEL_VIEW_INVERSE_1
# 14 MODEL_VIEW_INVERSE_2
# 15 MODEL_VIEW_INVERSE_3
# 16 light position in eye space
# 32 some material coeefficients 0.0f,32.0f,64.0f,128.0f;
# 95 0.0f,0.5f,1.0f,2.0f
# temp register
# R0
# R1
# R2
# R3
# R4
# R5
# R6
# R7
# R8 > Temp

#*************** Common ************************************

# Vertex --> clip space
MOV R11,v[OPOS];
DP4 o[HPOS].x, R11, c[0];
DP4 o[HPOS].y, R11, c[1];
DP4 o[HPOS].z, R11, c[2];
DP4 o[HPOS].w, R11, c[3];


# vertex normal in object space
MOV R1,v[NRML];

# Normal --> length 1
DP3 R1.w, R1, R1;
RSQ R1.w, R1.w;
MUL R1.xyz, R1, R1.w;

#R1 contains normal object space

# light in object space(from eye space)
MOV R3,c[16];
DP4 R4.x,R3,c[12];
DP4 R4.y,R3,c[13];
DP4 R4.z,R3,c[14];
DP4 R4.w,R3,c[15];

#R4 contains light pos object space

# ---------------DIFFUSE-------------------------

# vector light --> vertex in object space
ADD R0,-v[OPOS],R4;

# normalize vector light --> vertex
DP3 R0.w, R0, R0;
RSQ R0.w, R0.w;
MUL R0.xyz, R0, R0.w;

#R0 contains vector light vertex in object space

# dot normal with vertex light vector

# for lit instruction
DP3 R7.x, R0, v[NRML];

# ---------------SPECULAR------------------------
# still buggy, shine only moves when light or object moves but not when
# scene is moved
MOV R6,c[95].x; # zero

#R6 contains eye pos

#build halfway vector into R9
ADD R9,R6,R4;

#normalize R9
DP3 R9.w, R9, R9;
RSQ R9.w, R9.w;
MUL R9.xyz, R9, R9.w;

#dot normal with half vector
DP3 R7.y,R9,R1;

#material shine
MOV R7.w,c[32].x;

# do lighting calcualtion
LIT R8,R7;

# for use with light map
#MOV o[TEX0].x,R8.y;
#MOV o[TEX0].y,R8.z;

# only grey colors
#primary diffuse color
MOV o[COL0],R8.y;
#secondary specular color;
MOV o[COL1],R8.z;

END


// main program (partially
// global variables changed by user interface/keystrokes/mouse
// scene rotation
float srotation[16]={1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
// Scenentranslation
float stranslation[3]={0.0f, 0.0f, -4.0f };

// light
float light_pos[4] ={0.0f, 0.0f, 2.0f, 1.0f};
float light_ambient[4]={0.0f, 0.0f, 0.0f, 1.0f};
float light_diffuse[4]={1.0f, 1.0f, 1.0f, 1.0f};
float light_specular[4]={1.0f,1.0f, 1.0f, 1.0f};
float light_attenuation[4]={0.0f,1.0f,0.0f,0.0f};
//Material
float mat_ambient[4]= {0.0f, 0.0f, 0.0f, 1.0f};
float mat_diffuse[4]= {0.0f, 0.0f, 0.0f, 1.0f};
float mat_specular[4]= {1.0f, 1.0f, 1.0f, 1.0f};
float mat_shine = 64;
// use lighting with glLightf...
int gllighting=1;
// use vertex program
int usevp=1;

// the render loop
void OnInit()
{
glClearColor(0.5f,0.5f,0.5f,1.0f);
glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHT0);

float amb[4]={0.0f,0.0f,0.0f,1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,1);

// glTrackMatrixNV ... see begin of post

}
void OnRender()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glPushMatrix();
glLoadIdentity();
// Scene
glTranslatef(stranslation[0],stranslation[1],stranslation[2]);
glMultMatrixf(srotation);

glPushMatrix();// storing of scene view
ShowAxes();// jut draws coordinate systems axes with labels

// where is the light ...
glPushMatrix();
glTranslatef(light_pos[0],light_pos[1],light_pos[2]);
glColor3f(1.0f,1.0f,1.0f);
glutSolidSphere(0.2f,16,16);
glPopMatrix();

if(gllighting&& !usevp)
{
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);// not meant to be a performance killer ;-)
glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
glLightfv(GL_LIGHT0,GL_CONSTANT_ATTENUATION,light_ attenuation+1);
glLightfv(GL_LIGHT0,GL_LINEAR_ATTENUATION,light_at tenuation+2);
glLightfv(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,light _attenuation+3);
glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glMaterialf(GL_FRONT,GL_SHININESS,mat_shine);

glLightfv(GL_LIGHT0,GL_POSITION,light_pos);

}
else if(usevp)
{
glEnable(GL_VERTEX_PROGRAM_NV);
glExecuteProgramNV( GL_VERTEX_STATE_PROGRAM_NV, vspid, light_pos );
glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV,32,mat _shine,32.0f,64.0f,128.0f);
glBindProgramNV( GL_VERTEX_PROGRAM_NV, vpid );
}

glutSolidTeapot(0.5f);

if(gllighting)
{
glDisable(GL_LIGHTING);
}
if(usevp)
{
glDisable(GL_VERTEX_PROGRAM_NV);
}


glPopMatrix();// scene view

glPopMatrix();// matrix on entry of OnRender

glutSwapBuffers();
}

I hope this will clear something a little bit up

Bye ScottManDeath

jwatte
01-03-2002, 03:42 PM
If all you want is a custom diffuse lighting solution, it's much easier to do that using NORMAL_MAP texgen mode and the appropriate texture matrix.

ScottManDeath
01-04-2002, 12:46 AM
Originally posted by jwatte:
If all you want is a custom diffuse lighting solution, it's much easier to do that using NORMAL_MAP texgen mode and the appropriate texture matrix.

Hi
that sounds interesting, what is that exactly. Which extension has to be used ?
This would be sufficient for diffuse lighting but what can I do for specular lighting ?

Bye
ScottManDeath

jwatte
01-04-2002, 01:16 PM
NORMAL_MAP texgen is a standard part of OpenGL 1.3 and later; it's part of the cubemap extension before that. You can set up the texture matrix to collapse the 3 coordinates to a 1D texture; you don't need to bind a cube map texture just because you're using NORMAL_MAP texgen mode.

I believe that the reflective environment map mode _might_ be used for specular with the right incantations, but I haven't delved into the math to see if that's right or not. Intuitively, you'd use the same trick of collapsing a 3D texture vector into a 1D texture using the matrix, and rotate that matrix by the half angle vector, perhaps?