Introduction
This one demonstrates usage of GL_ARB_vertex_program, GL_NV_vertex_program, and GL_NV_vertex_program2. If you don't have a NVidia card, then it's too bad but you can see that both ASM based scripts are similar, but the NV version gives more power - specially the newer GL_NV_vertex_program2.
We render optionally a sphere, cube, torus, cone, cylinder and a teapot (of course!) and we light and texture them *without* doing anything special. We are just emulating the fixed vertex pipeline here (loosly speeking).
You can turn the program on and off, compare the FPS in each case.

The Source
The ARB and NV API are quite close in this case.
The ARB version uses glGenProgramsARB (which I have renamed to glGenPrograms) and the NV version has glGenProgramsNV. They use similar parameters. The reason why I prefer getting rid of the ARB ending is that these functions and tokens will likely become part of OpenGL's core in the next version. Here I will leave them as is.

//ARB
GLuint ARBVertexProgramID[10];
glGenProgramsARB(1, &ARBVertexProgramID[0]);

//NV
GLuint NVVertexProgramID[10];
glGenProgramsNV(1, &NVVertexProgramID[0]);

The ARB has glBindProgramARB (again, the ARB ending is removed in my source) and NV uses glBindProgramNV and they both take similar parameters.

//ARB
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ARBVertexProgramID[0]);

//NV
glBindProgramNV(GL_VERTEX_PROGRAM_NV, NVVertexProgramID[0]);

The ARB has glProgramStringARB for uploading the vp to OpenGL and here is the first difference. NV uses glLoadProgramNV.
With NV, binding is not necessary to upload a program, so you have to pass an ID while in ARB, it is traditional to bind, then do whatever. For now, you must always pass GL_PROGRAM_FORMAT_ASCII_ARB to the ARB version but it's possible unicode support will be added in the future.

//ARB
char cBuffer[xxx];
int length;
glProgramString(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, length, cBuffer);

//NV
char cBuffer[xxx];
int length;
glLoadProgramNV(GL_VERTEX_PROGRAM_NV, NVVertexProgramID[0], length, cBuffer);

Now that you have uploaded, it's a good idea to check for errors.
With ARB, you can also check to see if native limits are respected and in my code, I decided to do a fail if it is not respected.
In NV, you can't check if native limits are respected.

//ARB
GLint errorPos, isNative;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
glGetProgramiv(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative);

//NV
GLint errorPos;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errorPos);

That's the main part just to get things going. Another difference is that NV allows you to query if a program is resident or not but in ARB, they decided it's not very useful.

NVidia decided that ARB is not far off from it's own extensions (or the ARB decided NV is not far so they chose the same tokens) so some functions have the same address and some tokens have the same ID.
If you learn one of the scripts and read the spec, you'll see that there is plenty in common with the others.

GL_NV_vertex_program2 is quite interesting.
I only needed to write 1 script for handling the multiple lights, thanks to flow control instructions (BRA which stands for branch) and subroutine support (CAL for call and RET for return).
I think you lose some FPS though, but it's a neat feature nonetheless.

Conclusion
These extensions, unlike others, give incredible power to the programmer.
Use it wisely!
PS: It's not necessary to write multiple scripts. You can of course write one and manipulate it in your program but I did not want to bother with this.


Download source + exe




This page is http://www.oocities.org/vmelkon/verybasicvp.html
This page is http://ee.1asphost.com/vmelkon/verybasicvp.html
Copyright (C) 2001-2003 Vrej M. All Rights Reserved.