Author Topic: Useing OpenGL's Stencil Buffer for Reflections?  (Read 5642 times)

0 Members and 1 Guest are viewing this topic.

Offline ScottyBrosious

  • C= 64
  • **
  • Posts: 25
  • Karma: 3
    • View Profile
Could someone please show me how to use
OpenGL's Stencil buffer for doing reflections?

A small example program would be very helpful
not only to me but for other that come to this site just like
so many other programs before help is sometimes needed in codeing things up.

Thanks
Scotty B.

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #1 on: July 01, 2007 »
hi scotty the best thing to do when wanting to do a new effect is to have a goggle for it thats what i do then if its in c try a port to fb its quite easy then if you have trouble post up your broken code and we can try to help  ;)
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #2 on: July 01, 2007 »
Amen :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #3 on: July 02, 2007 »
I'd love to help, but there's no such thing as a 'small stencil buffer example'.  It's pretty complicated stuff and would take a good while to make a sample unless you'd already got some working code.
NeHe have great OpenGL samples, reflections are dealt with here
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=26

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #4 on: July 03, 2007 »
This is a very very crude example and it doesn't even use the stencil buffer but might give you a little bit of an idea how that sort of reflections work:

Code: [Select]
option explicit

'$include once: 'GL/glfw.bi'
#include "fbgfx.bi"

type vertex
    as single x,y,z
    as single r,g,b
end type

type object
    as integer num_verts
    as vertex pointer vertex_list
end type

sub initialise_opengl(byval wwidth as integer,byval height as integer)
    screen 19,32,2,GFX_OPENGL
glMatrixMode GL_PROJECTION                 '' Select The Projection Matrix
glLoadIdentity                             '' Reset The Projection Matrix
gluPerspective 45.0, wwidth/height, 1.0, 64000.0   '' Calculate The Aspect Ratio Of The Window
    gldepthrange(0.0,1.0)
glMatrixMode GL_MODELVIEW                  '' Select The Modelview Matrix
glLoadIdentity                             '' Reset The Projection Matrix
glShadeModel(GL_SMOOTH)                             '' Enables Smooth Color Shading
glClearColor(0.0, 0.0, 0.0, 0.0)                    '' This Will Clear The Background Color To Black
glClearDepth(1.0)
    glDepthFunc(GL_LESS)
    glenable(gl_depth_test)
    glcullface(gl_front)
    glenable(gl_cull_face)
    gldisable(gl_lighting)
    glfrontface(gl_cw)
end sub

cube_data:
data 36
data -1,-1,-1,-1,-1,1,-1,1,1
data -1,1,1,-1,1,-1,-1,-1,-1
data -1,-1,1,1,-1,1,1,1,1
data 1,1,1,-1,1,1,-1,-1,1
data 1,-1,1,1,-1,-1,1,1,-1
data 1,1,-1,1,1,1,1,-1,1
data 1,-1,-1,-1,-1,-1,-1,1,-1
data -1,1,-1,1,1,-1,1,-1,-1
data -1,1,-1,-1,1,1,1,1,1
data 1,1,1,1,1,-1,-1,1,-1
data 1,-1,-1,1,-1,1,-1,-1,1
data -1,-1,1,-1,-1,-1,1,-1,-1

function create_cube()as object pointer
    dim as object pointer cube=callocate(len(object))
    dim as integer i
    restore cube_data
    read cube->num_verts
    cube->vertex_list=callocate(len(vertex)*cube->num_verts)
    for i=0 to cube->num_verts-1
        read cube->vertex_list[i]->x,cube->vertex_list[i]->y,cube->vertex_list[i]->z
        cube->vertex_list[i]->r=rnd
        cube->vertex_list[i]->g=rnd
        cube->vertex_list[i]->b=rnd
    next
    return cube
end function

'draw an object, if reflection=-1 then it is drawn upsidedown below the alpha plane
sub draw_object(object as object pointer,x as single,y as single,z as single,reflection as single=1.0)

    'in a reflection the winding of tris is reversed
    if reflection=-1.0 then
        glcullface(gl_back)
    else
        glcullface(gl_front)
    end if
   
    glloadidentity()
    gltranslatef(x,y*reflection,z)
    dim as integer i
    dim as vertex pointer current_vertex
    glbegin(gl_triangles)
    for i=0 to object->num_verts-1
        current_vertex=@object->vertex_list[i]
        glcolor3f(current_vertex->r,current_vertex->g,current_vertex->b)
        glvertex3f(current_vertex->x,current_vertex->y*reflection,current_vertex->z)
    next
    glend()
end sub

'draw an alpha blended quad
sub draw_alpha_plane()
    glloadidentity()
    glcullface(gl_front)
    glenable(gl_blend)
    glblendfunc(gl_src_alpha,gl_one_minus_src_alpha)
    glbegin(gl_quads)
    glcolor4f(.4,.4,1.0,0.9)
    glvertex3f(-30.0,0.0,-30.0)
    glvertex3f(-30.0,0.0, 30.0)
    glvertex3f( 30.0,0.0, 30.0)
    glvertex3f( 30.0,0.0,-30.0)
    glend()
    gldisable(gl_blend)
end sub

   
sub main()
   
    initialise_opengl(640,480)
   
    'make 2 cubes and give them coordinates
    dim cube1 as object pointer=create_cube()
    dim as single x1=0.0,y1=4.9,z1=-10.0,vy1=0.0
    dim cube2 as object pointer=create_cube()
    dim as single x2=5.0,y2=2.5,z2=-7.0,vy2=0.0
   
    'setup the camera
    dim as single h
    glMatrixMode GL_PROJECTION
    gltranslatef(0.0,-1.0,0.0)
    glMatrixMode GL_MODELVIEW     
       
    do
       
        'draw cubes (the ones in the reflection... -1)
        draw_object(cube1,x1,y1,z1,-1)
        draw_object(cube2,x2,y2,z2,-1)
       
        'draw the surface they're reflected on
        draw_alpha_plane()
       
        'draw the actual cubes
        draw_object(cube1,x1,y1,z1)
        draw_object(cube2,x2,y2,z2)
       
        'control the cubes bouncing
        vy1+=.006
        y1-=vy1
        if y1<1.0 then
            y1=2.0-y1
            vy1=-vy1
        end if
        vy2+=.006
        y2-=vy2
        if y2<1.0 then
            y2=2.0-y2
            vy2=-vy2
        end if
       
        'control the camera
        glMatrixMode GL_PROJECTION
        gltranslatef(0.2,-0.06*sin(h),0.0)
        glrotatef(1.0,0.0,1.0,0.0)
        glMatrixMode GL_MODELVIEW     
        h+=0.05
       
        flip
        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
        sleep 10
    loop while inkey$=""

end sub

main

In this case I am really cheating and it can't handle the objects being rotated or anything but reflections are basically the same objects drawn (sort of the other way round, left becomes right or up becomes down) on the other side of the reflective plane. The stencil buffer can be used with this process to mask the areas of the screen where the reflection would be seen.
« Last Edit: July 04, 2007 by Stonemonkey »

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #5 on: July 03, 2007 »
Another thing I should've mentioned is that instead of positioning the objects on the other side of the reflection plane it's possible to position the camera on the other side looking back through and render from there instead of repositioning all the objects. How you do that though depends on how you're doing your geometry.

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #6 on: July 05, 2007 »
I've been thinking a little more about this (or reflections in general).

There are a few ways to achieve this type of reflection effect, either by reflecting all or most of the geometry to the other side of the plane or by having reversed copies of the geometry there. It could also be renderd into a texture for blurring or other effects. That's all ok for fairly limited planar reflections.

Another method of doing reflections is cubemapping with each side of the cube being rendered to with a camera pointing out in the direction of each face of the cube and then mapping that onto an object using some vector reflection calcs at every vertex to find the vector for the cubemap coords.

Maybe some sort of sphere mapping could also be used in a similar way, I'm not really sure.

Are there any other methods? (other than my dodgy way of rendering from a camera placed inside the object pointing back at the main camera with a wide angle)
« Last Edit: July 05, 2007 by Stonemonkey »

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #7 on: July 06, 2007 »
thats some cool reflection ideas and im coming up for learning reflections so i might try them out cheers.
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #8 on: July 06, 2007 »
I'm trying to think back to doing the dot3 mapping and wondering if that could be combined with reflective cubemapping (with fixed function, I imagine it'd be possible with shaders).

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #9 on: July 06, 2007 »
I'm coming to the conclusion, probably not. Btw, what are 4d texture coords?

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #10 on: July 06, 2007 »
The 3rd coordinate (r) is reserved for 3d textures.
The 4th coordinate is used to calculate a second perspective correction on the texture (apparently for lighting, or if the original texture wasn't linear in the first place).

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Useing OpenGL's Stencil Buffer for Reflections?
« Reply #11 on: July 06, 2007 »
Thanks Jim, been thinking about it from a software point of view now and for cubemapping I reckon that triangles to be drawn would have to be chopped up where different faces of the cube are mapped onto different areas of each single tri which would be pretty cool and I might give it a go but if I was to use normal mapping it'd be a slightly different story and I'd have to work out which cubemap texture to use for every pixel, anyone know if I'm on the right track or know anything about how it would be dealt with with shaders as in can a shader be set up to read from a cubemap just given a vector or do you have to do that stuff yourself in glsl?