Help trying to get reflections to work

Game Engine, Players & Web Plug-in, Virtual Reality, support for other engines

Moderators: jesterKing, stiv

Posts: 129
Joined: Fri Oct 18, 2002 1:35 am
Location: Oceanside, California

Help trying to get reflections to work

Postby Sutabi » Fri Apr 04, 2003 8:54 am

Ok here is how I figured things, If I still am reading the game engine and tring to implent somthing I dont know how to do yet I fugred i'd try it outside of blender, using Ghost lib:
With that said I failed big time. I just cant seem to get reflection in opengl....I had someone that uses opengl help me outand well its really just a proplem with how I have ghost set up but not sure how to fix it... Can anyone help? as soon as I can get this the soon blender will have reflections in the game engine ^_^.

Code: Select all

#include <stdlib.h>
#include <stdio.h>
#include <GHOST_C-api.h>
#include <GL/gl.h>
#include <GL/glu.h>
static GHOST_SystemHandle ghost_system;
static GHOST_WindowHandle win;
static GHOST_WindowHandle full_screen_window;
static GHOST_EventConsumerHandle consumer;
static GHOST_TimerTaskHandle timer;

static GLuint box;
static int exit_requested = 0;

static GLfloat xrot = 0.0;
static GLfloat yrot = 0.0;
static GLfloat zrot = 0.0;

// Light Parameters
static GLfloat   LightAmb[] = {0.7f, 0.7f, 0.7f, 1.0f};            // Ambient Light
static GLfloat   LightDif[] = {1.0f, 1.0f, 1.0f, 1.0f};            // Diffuse Light
static GLfloat   LightPos[] = {4.0f, 4.0f, 6.0f, 1.0f};            // Light Position

GLUquadricObj   *q;                              // Quadratic For Drawing A Sphere

GLfloat      xrotspeed   =  0.0f;                  // X Rotation Speed
GLfloat      yrotspeed   =  0.0f;                  // Y Rotation Speed
GLfloat      zoom      = -7.0f;                  // Depth Into The Screen
GLfloat      height      =  2.0f;                  // Height Of Ball From Floor

void DrawObject(void) {
   glColor3f(1.0f, 1.0f, 1.0f);                  // Set Color To White
   gluSphere(q, 0.35f, 32, 16);                  // Draw First Sphere

   glColor4f(1.0f, 1.0f, 1.0f, 0.4f);               // Set Color To White With 40% Alpha
   glEnable(GL_BLEND);                           // Enable Blending
   glBlendFunc(GL_SRC_ALPHA, GL_ONE);               // Set Blending Mode To Mix Based On SRC Alpha

   gluSphere(q, 0.35f, 32, 16);                  // Draw Another Sphere Using New Texture
void DrawFloor(void)                              // Draws The Floor
   glBegin(GL_QUADS);                           // Begin Drawing A Quad
      glNormal3f(0.0, 1.0, 0.0);                  // Normal Pointing Up
         glVertex3f(-2.0, 0.0, 2.0);               // Bottom Left Corner Of Floor
         glVertex3f(-2.0, 0.0,-2.0);               // Top Left Corner Of Floor
         glVertex3f( 2.0, 0.0,-2.0);               // Top Right Corner Of Floor

         glVertex3f( 2.0, 0.0, 2.0);               // Bottom Right Corner Of Floor
   glEnd();                                 // Done Drawing The Quad

int InitGL(GLvoid)                              // All Setup For OpenGL Goes Here

   glShadeModel(GL_SMOOTH);                     // Enable Smooth Shading
   glClearColor(0.2f, 0.5f, 1.0f, 1.0f);            // Background
   glClearDepth(1.0f);                           // Depth Buffer Setup
   glClearStencil(0);                           // Clear The Stencil Buffer To 0
   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
   glEnable(GL_TEXTURE_2D);                     // Enable 2D Texture Mapping

   glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);         // Set The Ambient Lighting For Light0
   glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);         // Set The Diffuse Lighting For Light0
   glLightfv(GL_LIGHT0, GL_POSITION, LightPos);      // Set The Position For Light0

   glEnable(GL_LIGHT0);                        // Enable Light 0
   glEnable(GL_LIGHTING);                        // Enable Lighting

   q = gluNewQuadric();                        // Create A New Quadratic
   gluQuadricNormals(q, GL_SMOOTH);               // Generate Smooth Normals For The Quad

   return 1;                              // Initialization Went OK

void DrawGLScene(void) {

   // Clip Plane Equations
   double eqr[] = {0.0f,-1.0f, 0.0f, 0.0f};         // Plane Equation To Use For The Reflected Objects

   // Clear Screen, Depth Buffer & Stencil Buffer

   glLoadIdentity();                           // Reset The Modelview Matrix
   glTranslatef(0.0f, -0.6f, zoom);               // Zoom And Raise Camera Above The Floor (Up 0.6 Units)
   glColorMask(0,0,0,0);                        // Set Color Mask
   glEnable(GL_STENCIL_TEST);                     // Enable Stencil Buffer For "marking" The Floor
   glStencilFunc(GL_ALWAYS, 1, 1);                  // Always Passes, 1 Bit Plane, 1 As Mask
   glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);         // We Set The Stencil Buffer To 1 Where We Draw Any Polygon
                                          // Keep If Test Fails, Keep If Test Passes But Buffer Test Fails
                                          // Replace If Test Passes
   glDisable(GL_DEPTH_TEST);                     // Disable Depth Testing
   DrawFloor();                              // Draw The Floor (Draws To The Stencil Buffer)
                                          // We Only Want To Mark It In The Stencil Buffer
   glEnable(GL_DEPTH_TEST);                     // Enable Depth Testing
   glColorMask(1,1,1,1);                        // Set Color Mask to TRUE, TRUE, TRUE, TRUE
   glStencilFunc(GL_EQUAL, 1, 1);                  // We Draw Only Where The Stencil Is 1
                                          // (I.E. Where The Floor Was Drawn)
   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);            // Don't Change The Stencil Buffer
   glEnable(GL_CLIP_PLANE0);                     // Enable Clip Plane For Removing Artifacts
                                          // (When The Object Crosses The Floor)
   glClipPlane(GL_CLIP_PLANE0, eqr);               // Equation For Reflected Objects
   glPushMatrix();                              // Push The Matrix Onto The Stack
      glScalef(1.0f, -1.0f, 1.0f);               // Mirror Y Axis
      glLightfv(GL_LIGHT0, GL_POSITION, LightPos);   // Set Up Light0
      glTranslatef(0.0f, height, 0.0f);            // Position The Object
      glRotatef(xrot, 1.0f, 0.0f, 0.0f);            // Rotate Local Coordinate System On X Axis
      glRotatef(yrot, 0.0f, 1.0f, 0.0f);            // Rotate Local Coordinate System On Y Axis
      DrawObject();                           // Draw The Sphere (Reflection)
   glPopMatrix();                              // Pop The Matrix Off The Stack
   glDisable(GL_CLIP_PLANE0);                     // Disable Clip Plane For Drawing The Floor
   glDisable(GL_STENCIL_TEST);                     // We Don't Need The Stencil Buffer Any More (Disable)
   glLightfv(GL_LIGHT0, GL_POSITION, LightPos);      // Set Up Light0 Position
   glEnable(GL_BLEND);                           // Enable Blending (Otherwise The Reflected Object Wont Show)
   glDisable(GL_LIGHTING);                        // Since We Use Blending, We Disable Lighting
   glColor4f(1.0f, 1.0f, 1.0f, 0.8f);               // Set Color To White With 80% Alpha
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   // Blending Based On Source Alpha And 1 Minus Dest Alpha
   DrawFloor();                              // Draw The Floor To The Screen
   glEnable(GL_LIGHTING);                        // Enable Lighting
   glDisable(GL_BLEND);                        // Disable Blending
   glTranslatef(0.0f, height, 0.0f);               // Position The Ball At Proper Height
   glRotatef(xrot, 1.0f, 0.0f, 0.0f);               // Rotate On The X Axis
   glRotatef(yrot, 0.0f, 1.0f, 0.0f);               // Rotate On The Y Axis
   DrawObject();                              // Draw The Ball
   xrot += xrotspeed;                           // Update X Rotation Angle By xrotspeed
   yrot += yrotspeed;                           // Update Y Rotation Angle By yrotspeed
   glFlush();                                 // Flush The GL Pipeline
   return 1;                              // Everything Went OK                              // Flush The GL Pipeline


 * This invalidates a window so that the WindowUpdate
 * event will be generated for the window
void invalidate_window(void) {
    if (GHOST_GetFullScreen(ghost_system))
    else {
        if (GHOST_ValidWindow(ghost_system, win))

 * the procedure to run when the timer goes off
void timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) {

 * does the initial OpenGL setup of the main window
void setup_window(GHOST_WindowHandle win) {
    GHOST_RectangleHandle rect = NULL;
    GLfloat w, h, aspect;

    rect = GHOST_GetClientBounds(win);

    w = (GLfloat)GHOST_GetWidthRectangle(rect);
    h = (GLfloat)GHOST_GetHeightRectangle(rect);
    aspect = w / h;

    glViewport(0, 0, w, h);
    glFrustum(-aspect, aspect, -1.0, 1.0, 5.0, 60.0);
    glTranslatef(0.0, 0.0, -12.0);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

 * this handles the events as they are generated by the GHOST system
int process_event(GHOST_EventHandle event, GHOST_TUserDataPtr data) {
    int handled = 0;
    GHOST_TEventKeyData *key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(event);
    /* all the entries need to be in the switch to make the compiler shut up */
    switch (GHOST_GetEventType(event)) {
        case GHOST_kEventUnknown:
        case GHOST_kEventCursorMove:
        case GHOST_kEventButtonDown:
        case GHOST_kEventButtonUp:
        case GHOST_kEventKeyUp:
        case GHOST_kEventWindowActivate:
        case GHOST_kEventWindowDeactivate:
        case GHOST_kEventWindowSize:
        case GHOST_kNumEventTypes:

        case GHOST_kEventWheel:
                GHOST_TEventWheelData *wheel = (GHOST_TEventWheelData *)GHOST_GetEventData(event);

                if (wheel->z > 0)
                    xrot += 2;
                    xrot -= 2;


        case GHOST_kEventWindowUpdate:
                GHOST_WindowHandle win_handle = GHOST_GetEventWindow(event);
                if (!GHOST_ValidWindow(ghost_system, win_handle))

        case GHOST_kEventQuit:
        case GHOST_kEventWindowClose:
            exit_requested = 1;
            handled = 1;

        case GHOST_kEventKeyDown:
            if (key_data) {
                if (key_data->key == GHOST_kKeyQ) {
                    exit_requested = 1;
                    handled = 1;
                } else if (key_data->key == GHOST_kKeyR) {


                } else if (key_data->key == GHOST_kKeyT) {
                    if (!timer)
                        timer = GHOST_InstallTimer(ghost_system, 0, 10, timer_proc, NULL);
                    else {
                        GHOST_RemoveTimer(ghost_system, timer);
                        timer = NULL;

                } else if (key_data->key == GHOST_kKeyF) {
                    if (GHOST_GetFullScreen(ghost_system)) {
                        full_screen_window = NULL;
                     } else {
                        GHOST_DisplaySetting setting;
                        setting.bpp = 16;
                        setting.frequency = 65;
                        setting.xPixels = 640;
                        setting.yPixels = 480;

                        full_screen_window = GHOST_BeginFullScreen(ghost_system, &setting, 0);
    return handled;

int main(int argc, char ** argv) {

    // create the system
    ghost_system = GHOST_CreateSystem();
    if (!ghost_system) {
        printf("Coun't not create the system, dying\n");

    // create the event consumer and add to the system
    consumer = GHOST_CreateEventConsumer(process_event, NULL);
    if (!consumer) {
        printf("Failed to create consumer\n");
    GHOST_AddEventConsumer(ghost_system, consumer);

    // make the main window
    win = GHOST_CreateWindow(ghost_system, "Realtime Reflection-or", 10, 64, 320, 200,
                GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, 0);
    if (!win) {
        printf("Couldn't not create window\n");

    /* the event loop */
    while(!exit_requested) {
       // could sleep if there are no events, but hey i'm cruel, heh.
       GHOST_ProcessEvents(ghost_system, 0);

    /* exit full screen if we are in it */
    if (GHOST_GetFullScreen(ghost_system))

    /* delete the timer */
    if (timer)
        GHOST_RemoveTimer(ghost_system, timer);

    /* clean it all up */
    if (GHOST_ValidWindow(ghost_system, win))
        GHOST_DisposeWindow(ghost_system, win);

    return 0;

Posts: 86
Joined: Tue Mar 04, 2003 7:55 pm

Postby Panther » Mon Apr 07, 2003 6:27 pm

Hi Sutabi,

Unfortunately, I don't have an answer to your question, but the best person to speak to may be Erwin ( you can find him through this forum ).

On a side note...

It's good to see someone else who is willing to improve the GameEngine - So well done, and good luck ;-)

Personally, I think it would be nice to have real-time shadows in the GameEngine too !!!

Posts: 1522
Joined: Wed Oct 16, 2002 2:38 am


Postby z3r0_d » Tue Apr 08, 2003 3:27 am

I am not sure, but could opengl think it can't have a stencil buffer or something?

(it is hard to read that there, now pasted into mvc6)

I don't have much of an idea (not having used stencil testing), but other than code problems which aren't ghost specific I have no more guesses

Posts: 1522
Joined: Wed Oct 16, 2002 2:38 am

Postby z3r0_d » Tue Apr 08, 2003 5:41 am


I think the problem was that your spheres are being placed in the same spot.
It would probably be prefered that your draw code called the DrawObject function AFTER changing the matrix and blendmode settings so that your DrawObject function a) didn't have to b) would draw only one object c) this part of your code made sense.

I added a couple lines, this is the resulting DrawObject function

Code: Select all

void DrawObject(void) {
  glColor3f(1.0f, 0.5f, 0.5f);            // Set Color
  gluSphere(q, 0.35f, 32, 16);            // Draw First Sphere

// begin change
  glTranslatef(0.0f, -1.0f, 0.0f);
// end change

  glColor4f(1.0f, 1.0f, 1.0f, 0.4f);          // Set Color To White With 40% Alpha
  glEnable(GL_BLEND);                  // Enable Blending
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);          // Set Blending Mode To Mix Based On SRC Alpha

  gluSphere(q, 0.35f, 32, 16);            // Draw Another Sphere Using New Texture

a hack, but it works (I also changed the height to .5f at the begining of the code)
(and I am using sdl not ghost)

image at


the method you use will work, but it will be limited to planar reflections.

still good to see someone working for improvement of the game engine

I am thinking (this second) about [realtime] reflection and refraction in this method:
render the scene without the water
using your render as a texture, render the refraction
render the reflections using a [precalculated?] cube environment map of the scene, and
also use a fresnel shader on the latter

Note that the last 3 steps are mostly combined into one using texture combination [extensions?]

it has been done
new thought:
why does it seem that so many people want technical improvements to the game engine that could quickly sacrifice the 'for the artist' nature that it was (and hopefully still is) intended to convey?

admittedly the game engine does have a learning curve, but it would be much steeper if the artist had to code the colisions and more themselves (after first deciding to use gameblender, then learning to code).

I think the improvements should be directed in this manner
*get it working
*fix bugs
*add features to improve speed
*and features to aide in the art (a partial-runtime mode?) of development
*add features to aide in runtime (graphics I guess, like

... looses thought

/steps off soapbox and presses the submit button

Return to “Interactive 3d”

Who is online

Users browsing this forum: No registered users and 0 guests