Hi,
i tried to port the stencil shadow tutorial (lesson 27) from nehe to SDL.
Its working fine on linux but on windows it doesnt draw any shadow, but the framerate drops.
I tried resetting the stencil buffer to 0, so that the rectangle drawed by the end will cover the whole screen. Thats the case on linux, but not on windows.
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, &i) delivers i = 8 on windows, so it’s been set up correctly.
Any ideas on our problem are very appreciated. You will find a link to the sourcecode and project files at the bottom.
Thanks!
For all those, who dont want to download anything, this is our main.cpp:
Code:
/*
-
This code has been created by Banu Octavian aka Choko - 20 may 2000
-
and uses NeHe tutorials as a starting point (window initialization,
-
texture loading, GL initialization and code for keypresses) - very good
-
tutorials, Jeff. If anyone is interested about the presented algorithm
-
please e-mail me at boct at romwest.ro
-
Attention!!! This code is not for beginners.
*/
#include <stdlib.h> // For malloc, free
#include <math.h> // Math Library Header File
#include <stdio.h> // Header File For Standard Input/Output
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#include “SDL/SDL.h”
#include
#include
#include “3Dobject.h”
/* screen width, height, and bit depth */
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 16
/* This is our SDL surface */
SDL_Surface *surface;
typedef float GLvector4f[4]; // Typedef’s For VMatMult Procedure
typedef float GLmatrix16f[16]; // Typedef’s For VMatMult Procedure
bool active= true;
bool fullscreen= false;
glObject obj; // Object
GLfloat xrot=0, xspeed=0; // X Rotation & X Speed
GLfloat yrot=0, yspeed=0; // Y Rotation & Y Speed
float LightPos[] = { 0.0f, 5.0f,-4.0f, 1.0f}; // Light Position
float LightAmb[] = { 0.2f, 0.2f, 0.2f, 1.0f}; // Ambient Light Values
float LightDif[] = { 0.6f, 0.6f, 0.6f, 1.0f}; // Diffuse Light Values
float LightSpc[] = {-0.2f, -0.2f, -0.2f, 1.0f}; // Specular Light Values
float MatAmb[] = {0.4f, 0.4f, 0.4f, 1.0f}; // Material - Ambient Values
float MatDif[] = {0.2f, 0.6f, 0.9f, 1.0f}; // Material - Diffuse Values
float MatSpc[] = {0.0f, 0.0f, 0.0f, 1.0f}; // Material - Specular Values
float MatShn[] = {0.0f}; // Material - Shininess
float ObjPos[] = {-2.0f,-2.0f,-5.0f}; // Object Position
GLUquadricObj *q; // Quadratic For Drawing A Sphere
float SpherePos[] = {-4.0f,-5.0f,-6.0f};
void VMatMult(GLmatrix16f M, GLvector4f v)
{
GLfloat res[4]; // Hold Calculated Results
res[0]=M[ 0]*v[0]+M[ 4]*v[1]+M[ 8]*v[2]+M[12]*v[3];
res[1]=M[ 1]*v[0]+M[ 5]*v[1]+M[ 9]*v[2]+M[13]*v[3]; res[2]=M[ 2]*v[0]+M[ 6]*v[1]+M[10]*v[2]+M[14]*v[3];
res[3]=M[ 3]*v[0]+M[ 7]*v[1]+M[11]*v[2]+M[15]*v[3];
v[0]=res[0]; // Results Are Stored Back In v[]
v[1]=res[1];
v[2]=res[2];
v[3]=res[3]; // Homogenous Coordinate
}
GLvoid ResizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.001f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
int InitGLObjects() // Initialize Objects
{
if (!ReadObject(“Data/Object2.txt”, &obj)) // Read Object2 Into obj
{
return 0; // If Failed Return False
}
SetConnectivity(&obj); // Set Face To Face Connectivity
for (unsigned int i=0;i<obj.nPlanes;i++) // Loop Through All Object Planes
CalcPlane(obj, &(obj.planes[i])); // Compute Plane Equations For All Faces
return 1; // Return True
}
int InitGL() // All Setup For OpenGL Goes Here
{
if (!InitGLObjects()) return 0; // Function For Initializing Our Object(s)
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glClearStencil(0); // Stencil Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glLightfv(GL_LIGHT1, GL_POSITION, LightPos); // Set Light1 Position
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmb); // Set Light1 Ambience
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDif); // Set Light1 Diffuse
glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpc); // Set Light1 Specular
glEnable(GL_LIGHT1); // Enable Light1
glEnable(GL_LIGHTING); // Enable Lighting
glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb); // Set Material Ambience
glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDif); // Set Material Diffuse
glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc); // Set Material Specular
glMaterialfv(GL_FRONT, GL_SHININESS, MatShn); // Set Material Shininess
glCullFace(GL_BACK); // Set Culling Face To Back Face
glEnable(GL_CULL_FACE); // Enable Culling
glClearColor(0.1f, 1.0f, 0.5f, 1.0f); // Set Clear Color (Greenish Color)
q = gluNewQuadric(); // Initialize Quadratic
gluQuadricNormals(q, GL_SMOOTH); // Enable Smooth Normal Generation
gluQuadricTexture(q, GL_FALSE); // Disable Auto Texture Coords
return 1; // Initialization Went OK
}
void DrawGLRoom() // Draw The Room (Box)
{
glBegin(GL_QUADS); // Begin Drawing Quads
// Floor
glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
glVertex3f(-10.0f,-10.0f,-20.0f); // Back Left
glVertex3f(-10.0f,-10.0f, 20.0f); // Front Left
glVertex3f( 10.0f,-10.0f, 20.0f); // Front Right
glVertex3f( 10.0f,-10.0f,-20.0f); // Back Right
// Ceiling
glNormal3f(0.0f,-1.0f, 0.0f); // Normal Point Down
glVertex3f(-10.0f, 10.0f, 20.0f); // Front Left
glVertex3f(-10.0f, 10.0f,-20.0f); // Back Left
glVertex3f( 10.0f, 10.0f,-20.0f); // Back Right
glVertex3f( 10.0f, 10.0f, 20.0f); // Front Right
// Front Wall
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Away From Viewer
glVertex3f(-10.0f, 10.0f,-20.0f); // Top Left
glVertex3f(-10.0f,-10.0f,-20.0f); // Bottom Left
glVertex3f( 10.0f,-10.0f,-20.0f); // Bottom Right
glVertex3f( 10.0f, 10.0f,-20.0f); // Top Right
// Back Wall
glNormal3f(0.0f, 0.0f,-1.0f); // Normal Pointing Towards Viewer
glVertex3f( 10.0f, 10.0f, 20.0f); // Top Right
glVertex3f( 10.0f,-10.0f, 20.0f); // Bottom Right
glVertex3f(-10.0f,-10.0f, 20.0f); // Bottom Left
glVertex3f(-10.0f, 10.0f, 20.0f); // Top Left
// Left Wall
glNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
glVertex3f(-10.0f, 10.0f, 20.0f); // Top Front
glVertex3f(-10.0f,-10.0f, 20.0f); // Bottom Front
glVertex3f(-10.0f,-10.0f,-20.0f); // Bottom Back
glVertex3f(-10.0f, 10.0f,-20.0f); // Top Back
// Right Wall
glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
glVertex3f( 10.0f, 10.0f,-20.0f); // Top Back
glVertex3f( 10.0f,-10.0f,-20.0f); // Bottom Back
glVertex3f( 10.0f,-10.0f, 20.0f); // Bottom Front
glVertex3f( 10.0f, 10.0f, 20.0f); // Top Front
glEnd(); // Done Drawing Quads
}
void DrawGLScene() // Main Drawing Routine
{
GLmatrix16f Minv;
GLvector4f wlp, lp;
// Clear Color Buffer, Depth Buffer, Stencil Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity(); // Reset Modelview Matrix
glTranslatef(0.0f, 0.0f, -20.0f); // Zoom Into Screen 20 Units
glLightfv(GL_LIGHT1, GL_POSITION, LightPos); // Position Light1
glTranslatef(SpherePos[0], SpherePos[1], SpherePos[2]); // Position The Sphere
gluSphere(q, 1.5f, 32, 16); // Draw A Sphere
// calculate light’s position relative to local coordinate system
// dunno if this is the best way to do it, but it actually works
// if u find another aproach, let me know
// we build the inversed matrix by doing all the actions in reverse order
// and with reverse parameters (notice -xrot, -yrot, -ObjPos[], etc.)
glLoadIdentity(); // Reset Matrix
glRotatef(-yrot, 0.0f, 1.0f, 0.0f); // Rotate By -yrot On Y Axis
glRotatef(-xrot, 1.0f, 0.0f, 0.0f); // Rotate By -xrot On X Axis
glGetFloatv(GL_MODELVIEW_MATRIX,Minv); // Retrieve ModelView Matrix (Stores In Minv)
lp[0] = LightPos[0]; // Store Light Position X In lp[0]
lp[1] = LightPos[1]; // Store Light Position Y In lp[1]
lp[2] = LightPos[2]; // Store Light Position Z In lp[2]
lp[3] = LightPos[3]; // Store Light Direction In lp[3]
VMatMult(Minv, lp); // We Store Rotated Light Vector In ‘lp’ Array
glTranslatef(-ObjPos[0], -ObjPos[1], -ObjPos[2]); // Move Negative On All Axis Based On ObjPos[] Values (X, Y, Z)
glGetFloatv(GL_MODELVIEW_MATRIX,Minv); // Retrieve ModelView Matrix From Minv
wlp[0] = 0.0f; // World Local Coord X To 0
wlp[1] = 0.0f; // World Local Coord Y To 0
wlp[2] = 0.0f; // World Local Coord Z To 0
wlp[3] = 1.0f;
VMatMult(Minv, wlp); // We Store The Position Of The World Origin Relative To The
// Local Coord. System In ‘wlp’ Array
lp[0] += wlp[0]; // Adding These Two Gives Us The
lp[1] += wlp[1]; // Position Of The Light Relative To
lp[2] += wlp[2]; // The Local Coordinate System
glColor4f(0.7f, 0.4f, 0.0f, 1.0f); // Set Color To An Orange
glLoadIdentity(); // Reset Modelview Matrix
glTranslatef(0.0f, 0.0f, -20.0f); // Zoom Into The Screen 20 Units
DrawGLRoom(); // Draw The Room
glTranslatef(ObjPos[0], ObjPos[1], ObjPos[2]); // Position The Object
glRotatef(xrot, 1.0f, 0.0f, 0.0f); // Spin It On The X Axis By xrot
glRotatef(yrot, 0.0f, 1.0f, 0.0f); // Spin It On The Y Axis By yrot
DrawGLObject(obj); // Procedure For Drawing The Loaded Object
CastShadow(&obj, lp); // Procedure For Casting The Shadow Based On The Silhouette
glColor4f(0.7f, 0.4f, 0.0f, 1.0f); // Set Color To Purplish Blue
glDisable(GL_LIGHTING); // Disable Lighting
glDepthMask(GL_FALSE); // Disable Depth Mask
glTranslatef(lp[0], lp[1], lp[2]); // Translate To Light’s Position
// Notice We’re Still In Local Coordinate System
gluSphere(q, 0.2f, 16, 8); // Draw A Little Yellow Sphere (Represents Light)
glEnable(GL_LIGHTING); // Enable Lighting
glDepthMask(GL_TRUE); // Enable Depth Mask
xrot += xspeed;
yrot += yspeed;
glFlush();
SDL_GL_SwapBuffers();
}
void KeyFunc(unsigned char key, int x, int y)
{
switch(key) {
// Adjust Light’s Position
case ‘L’:
case ‘l’:
LightPos[0] += 0.05f; // ‘L’ Moves Light Right
break;
case ‘J’:
case ‘j’:
LightPos[0] -= 0.05f; // ‘J’ Moves Light Left
break;
case ‘I’:
case ‘i’:
LightPos[1] += 0.05f; // ‘I’ Moves Light Up
break;
case ‘K’:
case ‘k’:
LightPos[1] -= 0.05f; // ‘K’ Moves Light Down
break;
case ‘O’:
case ‘o’:
LightPos[2] += 0.05f; // ‘O’ Moves Light Toward Viewer
break;
case ‘U’:
case ‘u’:
LightPos[2] -= 0.05f; // ‘U’ Moves Light Away From Viewer
break;
// Adjust Object's Position
case ‘6’:
ObjPos[0] += 0.05f; // ‘Numpad6’ Move Object Right
break;
case ‘4’:
ObjPos[0] -= 0.05f; // ‘Numpad4’ Move Object Left
break;
case ‘8’:
ObjPos[1] += 0.05f; // ‘Numpad8’ Move Object Up
break;
case ‘5’:
ObjPos[1] -= 0.05f; // ‘Numpad5’ Move Object Down
break;
case ‘9’:
ObjPos[2] += 0.05f; // ‘Numpad9’ Move Object Toward Viewer
break;
case ‘7’:
ObjPos[2] -= 0.05f; // ‘Numpad7’ Move Object Away From Viewer
break;
// Adjust Ball's Position
case ‘D’:
case ‘d’:
SpherePos[0] += 0.05f; // ‘D’ Move Ball Right
break;
case ‘A’:
case ‘a’:
SpherePos[0] -= 0.05f; // ‘A’ Move Ball Left
break;
case ‘W’:
case ‘w’:
SpherePos[1] += 0.05f; // ‘W’ Move Ball Up
break;
case ‘S’:
case ‘s’:
SpherePos[1] -= 0.05f; // ‘S’ Move Ball Down
break;
case ‘E’:
case ‘e’:
SpherePos[2] += 0.05f; // ‘E’ Move Ball Toward Viewer
break;
case ‘Q’:
case ‘q’:
SpherePos[2] -= 0.05f; // ‘Q’ Move Ball Away From Viewer
break;
case 27: //Escape key
exit(0);
default:
break;
}
}
/* function to release/destroy our resources and restoring the old desktop /
void Quit( int returnCode )
{
/ clean up the window */
SDL_Quit( );
/* and exit appropriately */
exit( returnCode );
}
void handleKeyPress( SDL_keysym *keysym )
{
}
void Resize(int width, int height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
// initialize everything and enter the main loop
int main(int argc, char** argv)
{
/* Flags to pass to SDL_SetVideoMode /
int videoFlags;
/ main loop variable /
int done = false;
/ used to collect events /
SDL_Event event;
/ this holds some info about our display */
const SDL_VideoInfo videoInfo;
/ whether or not the window is active */
int isActive = true;
/* initialize SDL */
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
fprintf( stderr, "Video initialization failed: %s\n",
SDL_GetError( ) );
Quit( 1 );
}
/* Fetch the video info */
videoInfo = SDL_GetVideoInfo( );
if ( !videoInfo )
{
fprintf( stderr, "Video query failed: %s\n",
SDL_GetError( ) );
Quit( 1 );
}
/* the flags to pass to SDL_SetVideoMode */
videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */
videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */
videoFlags |= SDL_RESIZABLE; /* Enable window resizing */
/* This checks if hardware blits can be done */
if ( videoInfo->blit_hw )
videoFlags |= SDL_HWACCEL;
/* Sets up OpenGL double buffering */
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
/* get a SDL surface */
surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
videoFlags );
/* Verify there is a surface */
if ( !surface )
{
fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) );
Quit( 1 );
}
/* initialize OpenGL */
InitGL( );
/* resize the initial window */
Resize( SCREEN_WIDTH, SCREEN_HEIGHT );
/* wait for events */
while ( !done )
{
/* handle the events in the queue */
while ( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_ACTIVEEVENT:
/* Something's happend with our focus
* If we lost focus or we are iconified, we
* shouldn't draw the screen
*/
if ( event.active.gain == 0 )
isActive = false;
else
isActive = true;
break;
case SDL_VIDEORESIZE:
/* handle resize event */
surface = SDL_SetVideoMode( event.resize.w,
event.resize.h,
16, videoFlags );
if ( !surface )
{
fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
Quit( 1 );
}
Resize( event.resize.w, event.resize.h );
break;
case SDL_KEYDOWN:
/* handle key presses */
handleKeyPress( &event.key.keysym );
break;
case SDL_QUIT:
/* handle quit requests */
done = true;
break;
default:
break;
}
}
/* draw the scene */
if ( isActive )
DrawGLScene( );
}
/* clean ourselves up and exit */
Quit( 0 );
/* Should never get here */
return( 0 );
}