File: lightmap.c/****************************************************/
/* Light mapping */
/* An OpenGL demo by A.P.Gardner */
/* Ported to Cpw by Jim Mathies */
/****************************************************/
/*
Cpw link options:
#define CPW_EXTERN - link to the static lib
#define CPWDLL_EXTERN - link to the release dll's stub
#define CPWDLLDBG_EXTERN - link to the debug dll's stub
#define CPWEXTDLL_EXTERN - link to the release dll with cpw addons
*/
#define CPWDLL_EXTERN
#include <cpw.h>
#include "../../library/addons/glextensions/cpwext_glextensions.h"
/* extension support info */
static GLExtensionSupport glExtInfo;
/* store of texture references */
static GLuint texName[2];
static CpwImage images[2];
static double rot = 0;
/****************************************************/
/* Load texture function */
/****************************************************/
bool registerTexture( pCpw cpw, char * filename, uint_32 id )
{
/* load the bitmap */
if ( !cpwLoadImage( cpw, &images[id], CPW_IMAGEFORMAT_BMP, filename, true ) ) {
printf( "File not found: %s\n", filename );
return false;
}
/* create texture object */
glBindTexture( GL_TEXTURE_2D, texName[id] );
/* set up wrap & filter params */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
/* load the texture into gl */
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, images[id].width, images[id].height,
0, GL_RGB, GL_UNSIGNED_BYTE, images[id].data );
return true;
}
/****************************************************/
/* Init */
/****************************************************/
bool init(pCpw cpw)
{
/* set background colour */
glClearColor(0.0, 0.0, 0.0, 0.0);
/* initialise viewing parameters */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.1, 0.9, 0.1, 0.9, -1.0, 1.0);
/* generate texture names */
texName[0] = 0;
texName[1] = 0;
glGenTextures( 2, texName );
/* load textures */
if ( !registerTexture( cpw, "textures/light.bmp", 0 ) ) return false;
if ( !registerTexture( cpw, "textures/wall2.bmp", 1 ) ) return false;
/* enable texturing & set texturing function */
glEnable(GL_TEXTURE_2D);
/* init gl extensions we might use if they exists */
cpwextInitOpenGLExtensions( cpw, &glExtInfo );
if ( glExtInfo.ARB_multitexture ) {
printf( "Using ARB_multitexture extension.\n" );
} else {
printf( "No ARB_multitexture support, using multipass rendering.\n" );
}
return true;
}
/****************************************************/
/* Cleanup texture memory */
/****************************************************/
void cleanup(void)
{
/* delete texture objects */
glDeleteTextures(2, texName);
}
/****************************************************/
/* Timer Event callback */
/****************************************************/
void timer( pCpw cpw, uint_32 id )
{
rot = rot + .1;
cpwPostWindowRedisplay( cpw, 1 );
}
void display_arbmultitexture( void )
{
/* move the lightmap texture around in a circle */
glActiveTextureARB( GL_TEXTURE0_ARB );
glBindTexture( GL_TEXTURE_2D, texName[0] );
glEnable( GL_TEXTURE_2D );
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glTranslated( sin(rot)*.05, cos(rot)*.05, 0 );
glActiveTextureARB( GL_TEXTURE1_ARB );
glBindTexture( GL_TEXTURE_2D, texName[1] );
glEnable( GL_TEXTURE_2D );
/* just draw the wall texture - no movement */
glMatrixMode( GL_MODELVIEW );
/* draw both the lightmap and the wall at the same time */
/* The ARB_multitexture extension does not add any new texture
blending modes. The standard OpenGL 1.1 blending modes are supported
in a pipelined manner; the result of the first texture environment
feeds into the second texture environment as the fragment color. */
glBegin( GL_QUADS );
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0.0, 0.0 );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0.0, 0.0 );
glVertex3d(0.0, 0.0, 0.0);
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1.0, 0.0 );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1.0, 0.0 );
glVertex3d(1.0, 0.0, 0.0);
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1.0, 1.0 );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1.0, 1.0 );
glVertex3d(1.0, 1.0, 0.0);
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0.0, 1.0 );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0.0, 1.0 );
glVertex3d(0.0, 1.0, 0.0);
glEnd();
}
void display_standardpipeline( void )
{
/* bind light map texture */
glBindTexture(GL_TEXTURE_2D, texName[0]);
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glTranslated( sin(rot)*.05, cos(rot)*.05, 0 );
/* draw the light map quad */
glBegin(GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3d(1.0, 0.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3d(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3d(0.0, 1.0, 0.0);
glEnd();
glMatrixMode( GL_MODELVIEW );
/* enable blending */
glEnable(GL_BLEND);
/* set blend function to multiply SRC & DST colours */
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
/* bind wall texture */
glBindTexture(GL_TEXTURE_2D, texName[1]);
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
/* draw the wall quad */
glBegin(GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3d(1.0, 0.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3d(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3d(0.0, 1.0, 0.0);
glEnd();
/* disable blending */
glDisable(GL_BLEND);
}
/****************************************************/
/* Window Draw Event callback */
/****************************************************/
void display( pCpw cpw, uint_32 winid )
{
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
/* clear all pixels in colour buffer */
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
/* display */
if ( glExtInfo.ARB_multitexture ) {
display_arbmultitexture();
} else {
display_standardpipeline();
}
cpwFpsDraw( cpw, true );
cpwSwapWindowBuffers( cpw, winid );
}
/****************************************************/
/* Window Resize Event callback */
/****************************************************/
void reshape( pCpw cpw, uint_32 winid, uint_32 width, uint_32 height )
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.1, 0.9, 0.1, 0.9, -1.0, 1.0);
glViewport( 0, 0, width, height );
}
/****************************************************/
/* Main */
/****************************************************/
#ifdef _WINDOWS
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
#elif _CONSOLE
int main(int argc, char* argv[])
#endif
{
pCpw cpw = null;
cpwInitContext( &cpw );
cpwInitDisplayMode( cpw, CPW_SURFACE_DOUBLE | CPW_SURFACE_RGB );
cpwInitWindowProperty( cpw, CPW_WINDOWPROP_POSITION, 100, 100 );
cpwInitWindowProperty( cpw, CPW_WINDOWPROP_SIZE, 200, 200 );
cpwCreateWindow(cpw,"OpenGL Demo - Light Mapping (Multipass)");
if ( !init(cpw) ) {
cpwFreeContext( &cpw );
return false;
}
cpwReshapeCallback( cpw, reshape );
cpwDisplayCallback(cpw,display);
cpwTimerCallback(cpw,1,1,true,timer);
cpwFpsInit(cpw);
cpwMainLoop(cpw);
cleanup();
return 0;