faking standard opengl t&l with GL_NV_vertex_program

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

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.

[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_MODELVIEW_PROJECTION_NV,GL_IDENTITY_NV);
// ModelView in c[4] to c[7]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,4,GL_MODELVIEW,GL_IDENTITY_NV);
// Modelview invers transposed in c[8] to c[11]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,8,GL_MODELVIEW,GL_INVERSE_TRANSPOSE_NV);
// Modelview invers in c[8] to c[11]
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,12,GL_MODELVIEW,GL_INVERSE_NV);
// helpful numbers
glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV,95,0.0f,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_attenuation+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

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.

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

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?