From: David Lannan (david.lannan++at++sydac.com.au)
Date: 04/26/2004 17:18:45
Hi all,
Previously I was going to post our results of implementing ARB vertex and
fragment shaders in Performer 3.02. I have included a basic example of Pre
and Post draw callbacks, that can be used to apply a shader to any geometry
node - it will probably work on any pfNode. This system is purely for
Performer 3.02, I am uncertain of the operation under Performer 3.1 (because
of our problems).
In these functions I was implementing a light scattering routine :-) .. but
the parameters can be set for the shader you want to use. Again this is just
a rudimentary sample. If you want to have proper parameter handling you'll
need to write it yourself :-)
VERTEX_SHADER_BUFFER and FRAGMENT_SHADER_BUFFER are char buffers of the ARB
programs. Make sure the program is formatted correctly - I didnt post any
checking routines. Also, I have have couple of simple shaders I can post if
need be, but there is a fair amount of ARB examples on the net.
I hope this helps, it certainly has the capability to improve the graphical
content and attaching to a particular node is ideal for specific
implementations - ie a water shader, some specular highlighting on metal
components and so on.
The following should be enough to get the vertex and fragment programs
running. Oh, make sure you have a decent video card for fragment shaders -
it seems GF4's and some Quadros arent fragment capable, but the 9700 & 9800
series seem to be fine.
<Sorry Peter, this was supposed to go to info-performer :-)>
Cheers,
David Lannan
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#include<gl/gl.h> // OpenGL header.
#include<gl/glu.h> // OpenGL utility.
#include"glext.h" // OpenGL extensions.
// These are OpenGL functions that we will need for our vertex shader.
Actually they
// are pointers and we will get the address of the functions we need.
static PFNGLGENPROGRAMSARBPROC glGenProgramsARB = NULL;
static PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB = NULL;
static PFNGLBINDPROGRAMARBPROC glBindProgramARB = NULL;
static PFNGLPROGRAMSTRINGARBPROC glProgramStringARB = NULL;
static PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB =
NULL;
static PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB =
NULL;
// This will hold our vertex shader - need to have list for them (can have
per node!)
static GLuint VertexShader;
static GLuint FragmentShader;
void PreRenderFragment(pfTraverser *_trav)
{
glPushMatrix();
// This will load our translation values into program.env[0].
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 0.5f, 0.5f, 0.5f,
1.0f);
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 0, -1, 0, 0 );
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, brightness,
contrast, 0, 0);
// Here we are binding the vertex shader to the hardware after you set
the
// constants.
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, FragmentShader);
// Just like if you would like to have texture, you would need to enable
texturing right?
// Well to use the vertex program you must enable it like so...
glEnable(GL_FRAGMENT_PROGRAM_ARB);
}
void PostRenderFragment(pfTraverser *_trav)
{
// When we are done we disable the vertex program.
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glPopMatrix();
}
void PreRenderShader(pfTraverser *_trav)
{
glPushMatrix();
// This will load our translation values into program.env[0].
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, 1.0f, 10.0f, 10.0f,
0.0f);
pfVec3 epos;
_trav->getChan()->getEye(epos);
// Set position and direction of the sun - relative to viewer
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, epos[0] - 2000,
epos[1] - 2000, 0, 0 );
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 1, 0.14780, -0.9890,
0.2478, 0);
// Here we are binding the vertex shader to the hardware after you set
the
// constants.
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, VertexShader);
// Just like if you would like to have texture, you would need to enable
texturing right?
// Well to use the vertex program you must enable it like so...
glEnable(GL_VERTEX_PROGRAM_ARB);
}
void PostRenderShader(pfTraverser *_trav)
{
// When we are done we disable the vertex program.
glDisable(GL_VERTEX_PROGRAM_ARB);
glPopMatrix();
}
bool Material::Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Clear the screen to black.
glShadeModel(GL_SMOOTH); // Smooth shading in our scenes.
glEnable(GL_DEPTH_TEST); // Enable desth testing for hidden
surface removal.
// With this we will load the list of extensions the hardware this
tutorial is running on
// supports.
char *extension = (char*)glGetString( GL_EXTENSIONS);
// Now that we have all of the extensions the hardware supports lets test
if the
// GL_ARB_vertex_program extension is there.
if(strstr(extension, "GL_ARB_vertex_program") == NULL)
{
MessageBox(NULL, "Your hardware don't support vertex shaders!",
"Shader with GL_ARB_vertex_program is not supported",
MB_OK);
return false;
}
if(strstr(extension, "GL_ARB_fragment_program") == NULL)
{
MessageBox(NULL, "Your hardware don't support fragment shaders!",
"Shader with GL_ARB_fragment_program is not supported",
MB_OK);
return false;
}
// Next we will try to get the address of each of the functions we will
need for this tutorial.
glGenProgramsARB =
(PFNGLGENPROGRAMSARBPROC)wglGetProcAddress("glGenProgramsARB");
glDeleteProgramsARB =
(PFNGLDELETEPROGRAMSARBPROC)wglGetProcAddress("glDeleteProgramsARB");
glProgramStringARB =
(PFNGLPROGRAMSTRINGARBPROC)wglGetProcAddress("glProgramStringARB");
glBindProgramARB =
(PFNGLBINDPROGRAMARBPROC)wglGetProcAddress("glBindProgramARB");
glProgramEnvParameter4fARB =
(PFNGLPROGRAMENVPARAMETER4FARBPROC)wglGetProcAddress("glProgramEnvParameter4
fARB");
glProgramLocalParameter4fARB =
(PFNGLPROGRAMLOCALPARAMETER4FARBPROC)wglGetProcAddress("glProgramLocalParame
ter4fARB");
// We need to do some error checking. We must make sure the functions
are supported.
if(!glGenProgramsARB || !glDeleteProgramsARB || !glProgramStringARB ||
!glBindProgramARB || !glProgramEnvParameter4fARB ||
!glProgramLocalParameter4fARB)
{
MessageBox(NULL, "Error, GL_ARB_vertex_program functions not
supported", "Error...",
MB_OK);
return false;
}
// Now that we know everything is good and that the hardware actually
supports what we want
// to do we can now actually load and create the vertex shader.
// First we generate the vertex program using the ARB function
glGenProgramsARB.
// Next we will bind it to our global Vertex Shader variable called,
VertexShader.
glGenProgramsARB(1, &VertexShader);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, VertexShader);
glGenProgramsARB(1, &FragmentShader);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, FragmentShader);
// Next we will load the source code for the shader into OpenGL. First
we will get the data.
int count = 0;
int fcount = 0;
char *ShaderCode = VERTEX_SHADER_BUFFER;
char *FragmentCode = FRAGMENT_SHADER_BUFFER;
count = strlen(ShaderCode);
fcount = strlen(FragmentCode);
// Error checking...
if(ShaderCode == NULL)
{
MessageBox(NULL, "Error loading vertex shader code", "Error...",
MB_OK);
return false;
}
if(FragmentCode == NULL)
{
MessageBox(NULL, "Error loading fragment shader code", "Error...",
MB_OK);
return false;
}
// Now we take that source code and create the vertex shader out of it.
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
count, ShaderCode);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
fcount, FragmentCode);
// If all went well we return true.
return true;
}
void Material::SetShader(pfNode *node)
{
if(node)
{
node->setTravFuncs(PFTRAV_DRAW, PreShader, PostShader);
}
}
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
This archive was generated by hypermail 2b29 : Mon Apr 26 2004 - 17:18:00 PDT