Graphics3D and GLGraphics

BlitzMax Forums/MiniB3D Module/Graphics3D and GLGraphics

SystemError51(Posted 2012) [#1]
Hi all,

I may be wrong about this one... I guess I'm seeking confirmation from the experts.

I've been revisiting my Shadow Mapping thing for the game, which, as it so turns out, has a few major flaws. To get some pointers in the right direction, I stumbled upon this thing from a while ago:

BM OpenGL Programming: shadow mapping

The code in that posts essentially works, on today's machines even nicely with a 512 shadow map (increase texsize to 512). You can do the minor adjustments required or you leave it, either way the mapping is pretty damn near perfect.

I have been trying to sort of port this to MiniB3D - but I have come to a disconcerting revelation.

It's not working for me so far, only parts of the shadow mapping is working.

If you take the code above and just compile, it'll run pretty smoothly.

However, when you replace

GLGraphics 1024,768,0,60,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER


with

Import "minib3d.bmx"
Graphics3D 1024,768,0,60,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER


(if you use MiniB3D that way, otherwise import the module)

and then run it, it'll be black. BUT! Press "n" on your keyboard to see the shadow map, you will notice that suddenly it runs horribly slow.

So my guess is that it has to do with MiniB3D converting things into a 2D display of sorts (I have not checked the code in that detail), or maybe it has to do with VSync.

Either way I'm pretty concerned about this, any insights into this are highly appreciated.

If MiniB3D has always been this slow I will have no choice as to probably write my own 3D framework.

Please advise.

Thanks,
Marcus

Last edited 2012


jkrankie(Posted 2012) [#2]
Minib3d uses the glmax2ddriver, not glgraphics driver.

Cheers
Charlie


jkrankie(Posted 2012) [#3]
Also, if you want to use raw gl stuff with minib3d your code has to go between renderworld and beginmax2d (if you're using max2d). Don't know if that's exactly what you're doing though.

Cheers
Charlie


SystemError51(Posted 2012) [#4]
Hi Charlie,

thanks for that pointer. I have changed the MiniB3D driver line to use the GLGraphicsDriver - not much seems to have changed. I am making progress though.


SystemError51(Posted 2012) [#5]
Here's a somewhat working modification of the code from the other post, using MiniB3D. Things like TMesh don't yet work as I have to figure out a way to do this.

I need to mention that in this implementation, the ground plane is not rendered - it was only a single face. However when a "closed" plane is used, it renders correctly. (???)

Ah yes, also, the cylinder's "cap" is missing =/

'shadowMap mark2

Import "minib3d.bmx"

'GLGraphics 1024,768,0,60,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER
Graphics3D 1024,768,0,60,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER

Global LIGHT_POS:Float[] = [ -60.0, 25.0, 0.0, 1.0 ]
Global CAMERA_POS:Float[] = [0.0, 100.0, 150.0, 1.0 ]

Global WHITE:Float[] =[ 1.0, 1.0, 1.0, 1.0]
Global BLACK:Float[] =[ 0.0, 0.0, 0.0, 0.0]
Global GREY:Float[] =[ 0.3, 0.3, 0.3, 0.3 ]
Global DARK_GREY:Float[] = [0.1, 0.1, 0.1, 0.1]
Global m_shadowMap:Int
Global   m_bounce:Float = 0.0
Global showShadowMap:Int = False
Global noShadows:Int = False
Global ambientShadowAvailable:Int = False
Global  m_windowHeight = 768
Global  m_windowWidth = 1024
Global sPlane:Float[] = [1.0, 0.0, 0.0, 0.0]
Global tPlane:Float[] = [0.0, 1.0, 0.0, 0.0]
Global rPlane:Float[] = [0.0, 0.0, 1.0, 0.0]
Global qPlane:Float[] = [0.0, 0.0, 0.0, 1.0]
Global m_quadric:Byte Ptr
m_quadric = gluNewQuadric()
gluQuadricNormals(m_quadric, GLU_SMOOTH)
Global modelview:Float[16], projection:Float[16]
Global texsize:Int = 512

' I added this

Global cam:TCamera = CreateCamera() 
PositionEntity cam , 0.0 , 100.0 , 150.0
RotateEntity cam, 20, 0, 0 
'Global light:TLight = CreateLight(2) 
'PositionEntity light , 0 , 500 , 0
'LightRange light, 600 

' This does not show yet
Global plane:TMesh = CreateCube() 
ScaleEntity plane , 50 , 0.01 , 50
PointEntity cam, plane


'****************************************************
init()

'main loop
While Not AppTerminate() And Not KeyDown(KEY_ESCAPE)
update(1) 
RenderWorld()
render() 

Flip
If KeyHit(Key_N) showshadowmap = True
If KeyHit(KEY_m) showshadowmap = False
If KeyHit(KEY_O) noshadows = True
If KeyHit(KEY_P) noshadows = False
Wend

End

'*****************************************************

Function Init()
	
glewinit()
  

  glEnable(GL_DEPTH_TEST)
  glDepthFunc(GL_LEQUAL)

 
  glGenTextures(1, Varptr m_shadowMap)
  glBindTexture(GL_TEXTURE_2D, m_shadowMap)

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
  glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE)

  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
  glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
  glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)

  glEnable(GL_LIGHT0)
  glEnable(GL_COLOR_MATERIAL)
  glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)

  glPolygonOffset(4.0, 0.0)

 
End Function
'****************************************************************

Function SetupProjection(width:Int, height:Int)
	
	glViewport( 0, 0, width, height )

'	// set up a perspective projection
	glMatrixMode( GL_PROJECTION )
	glLoadIdentity()
	gluPerspective( 45.0, Float(width)/Float(height), 1.0, 1000.0 )
End Function
'*****************************************************************
Function Update( dt:Float )

  m_bounce :+ 10 * dt
End Function
'*****************************************************************

Function Render() 

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
  GenerateShadowMap()

  '// Track camera angle
  glMatrixMode(GL_PROJECTION)
  glLoadIdentity()
  gluPerspective(45.0, 1.0, 1.0, 1000.0)
  glMatrixMode(GL_MODELVIEW)
  glLoadIdentity()
  gluLookAt(CAMERA_POS[0], CAMERA_POS[1], CAMERA_POS[2],0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
  glViewport(0, 0, 1024,768)

  '// Track light position
  glLightfv(GL_LIGHT0, GL_POSITION, LIGHT_POS)

  '// Clear the window with current clearing color
  glClear(GL_DEPTH_BUFFER_BIT)

  If showShadowMap = True Then
  
   ' // Display shadow map For educational purposes
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glMatrixMode(GL_TEXTURE)
    glPushMatrix()
    glLoadIdentity()
    glEnable(GL_TEXTURE_2D)
    glDisable(GL_LIGHTING)
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    '// Show the shadowMap at its actual size relative To window
    glBegin(GL_QUADS)
    glTexCoord2f(0.0, 0.0)
    glVertex2f(-1.0, -1.0)
    glTexCoord2f(1.0, 0.0)
    glVertex2f((Float(texsize)/Float(1024))*2.0-1.0,-1.0)
    glTexCoord2f(1.0, 1.0)
    glVertex2f((Float(texsize)/Float(1024))*2.0-1.0,Float(texsize)/Float(768)*2.0-1.0)
    glTexCoord2f(0.0, 1.0)
    glVertex2f(-1.0,Float(texsize)/Float(768)*2.0-1.0)
    glEnd()
    glDisable(GL_TEXTURE_2D)
    glEnable(GL_LIGHTING)
    glPopMatrix()
    glMatrixMode(GL_PROJECTION)
    gluPerspective(45.0, 1.0, 1.0, 1000.0)
    glMatrixMode(GL_MODELVIEW)
  
  Else If noShadows = True
  
   ' // Set up some simple lighting
    glLightfv(GL_LIGHT0, GL_AMBIENT, GREY)
   glLightfv(GL_LIGHT0, GL_DIFFUSE, WHITE)

    '// Draw objects in the scene
   RenderObjects(False)
  
  Else
  
      If ambientShadowAvailable = False Then
    
    
      '// Because there is no support For an "ambient"
      '// shadow compare fail value, we'll have to
      '// draw an ambient pass first...
      glLightfv(GL_LIGHT0, GL_AMBIENT, GREY)
      glLightfv(GL_LIGHT0, GL_DIFFUSE, DARK_GREY)

      '// Draw objects in the scene
      RenderObjects(False)
      '// Enable alpha test so that shadowed fragments are discarded
      glAlphaFunc(GL_GREATER, 0.9)
      glEnable(GL_ALPHA_TEST)
    EndIf

    glLightfv(GL_LIGHT0, GL_AMBIENT, grey)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, WHITE)

    '// Set up shadow comparison
    glEnable(GL_TEXTURE_2D)
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,GL_COMPARE_R_TO_TEXTURE)

  
    '// Set up the eye plane For projecting the shadow map on the scene
    glEnable(GL_TEXTURE_GEN_S)
    glEnable(GL_TEXTURE_GEN_T)
    glEnable(GL_TEXTURE_GEN_R)
    glEnable(GL_TEXTURE_GEN_Q)
    glTexGenfv(GL_S, GL_EYE_PLANE, sPlane)
    glTexGenfv(GL_T, GL_EYE_PLANE, tPlane)
    glTexGenfv(GL_R, GL_EYE_PLANE, rPlane)
    glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane)

    '// Draw objects in the scene
    RenderObjects(False)
    glDisable(GL_ALPHA_TEST)
    glDisable(GL_TEXTURE_2D)
    glDisable(GL_TEXTURE_GEN_S)
    glDisable(GL_TEXTURE_GEN_T)
    glDisable(GL_TEXTURE_GEN_R)
    glDisable(GL_TEXTURE_GEN_Q)
  
EndIf

End Function
'********************************************************************
Function RenderObjects(isShadowPass:Int)

  glPushMatrix()
  glColor3f(0.2, 0.9, 0.3)
  glTranslatef(0.0, 5 + 5 * Sin(m_bounce), 0.0)
  glRotatef(-90.0, 1.0, 0.0, 0.0)
  gluCylinder(m_quadric, 10, 0, 20, 20, 20)

  glPopMatrix()

  glPushMatrix()
  glColor3f(0.75, 0.2, 0.1)
  glTranslatef(15.0, 5.0, 12 * Cos(m_bounce/3.0))
  glusphere(M_quadric,5,20,20)

  glPopMatrix()

  glPushMatrix()
  glColor3f(0.5, 0.1, 0.9)
  glTranslatef(28.0, 6.0, -24.0)
  glRotatef(30.0, 0.0, 1.0, 0.0)
  glucylinder(m_quadric,6, 6, 20, 20, 20)
  glPopMatrix()

glDisable(GL_LIGHTING)
	glPushMatrix()
	glColor3f(1,1,1)	
	glTranslatef(light_pos[0],light_pos[1],light_pos[2])
	glusphere(m_quadric,1,20,20)
	glPopMatrix()
	
glEnable(GL_LIGHTING)	

	
  glPushMatrix()
glColor3f(.75,.75,.95)

For Local i = -50 To 50 Step 20
For Local j = -50 To 50 Step 20
glBegin(GL_QUADS)
glNormal3f(0 , 1 , 0) 

    glVertex3f( 50.0, 1.0,-50.0)'	// Top Right Of The Quad (Top)
    glVertex3f(-50.0, 1.0,-50.0)'	// Top Left Of The Quad (Top)
    glVertex3f(-50.0, 1.0, 50.0)'	// Bottom Left Of The Quad (Top)
    glVertex3f( 50.0, 1.0, 50.0)'	// Bottom Right Of The Quad (Top)
    glVertex3f( 50.0,-1.0, 50.0)'	// Top Right Of The Quad (Bottom)
    glVertex3f(-50.0,-1.0, 50.0)'	// Top Left Of The Quad (Bottom)
    glVertex3f(-50.0,-1.0,-50.0)'	// Bottom Left Of The Quad (Bottom)
    glVertex3f( 50.0,-1.0,-50.0)'	// Bottom Right Of The Quad (Bottom)
    glVertex3f( 50.0, 1.0, 50.0)'	// Top Right Of The Quad (Front)
    glVertex3f(-50.0, 1.0, 50.0)'	// Top Left Of The Quad (Front)
    glVertex3f(-50.0,-1.0, 50.0)'	// Bottom Left Of The Quad (Front)
    glVertex3f( 50.0,-1.0, 50.0)'	// Bottom Right Of The Quad (Front)
    glVertex3f( 50.0,-1.0,-50.0)'	// Top Right Of The Quad (Back)
    glVertex3f(-50.0,-1.0,-50.0)'	// Top Left Of The Quad (Back)
    glVertex3f(-50.0, 1.0,-50.0)'	// Bottom Left Of The Quad (Back)
    glVertex3f( 50.0, 1.0,-50.0)'	// Bottom Right Of The Quad (Back)
    glVertex3f(-50.0, 1.0, 50.0)'	// Top Right Of The Quad (Left)
    glVertex3f(-50.0, 1.0,-50.0)'	// Top Left Of The Quad (Left)
    glVertex3f(-50.0,-1.0,-50.0)'	// Bottom Left Of The Quad (Left)
    glVertex3f(-50.0,-1.0, 50.0)'	// Bottom Right Of The Quad (Left)
    glVertex3f( 50.0, 1.0,-50.0)'	// Top Right Of The Quad (Right)
    glVertex3f( 50.0, 1.0, 50.0)'	// Top Left Of The Quad (Right)
    glVertex3f( 50.0,-1.0, 50.0)'	// Bottom Left Of The Quad (Right)
    glVertex3f( 50.0,-1.0,-50.0)'	// Bottom Right Of The Quad (Right)
'glVertex3f(i + 10 , 0 , j + 10) 
'glVertex3f(i + 10 , 1 , j + 10) 
'glVertex3f(i - 10 , 0 , j + 10) 
'glVertex3f(i - 10 , 1 , j + 10) 
'glVertex3f(i - 10 , 0 , j - 10) 
'glVertex3f(i - 10 , 1 , j - 10) 
'glVertex3f(i + 10 , 0 , j - 10) 
'glVertex3f(i + 10 , 1 , j - 10) 

glEnd()
Next
Next
glPopMatrix() 

End Function
'*************************************************************
Function GenerateShadowMap()

  Local lightToSceneDistance:Float, nearPlane:Float, fieldOfView:Float
  Local lightModelview:Float[16], lightProjection:Float [16]

  '// Save the depth precision For where it's useful
  lightToSceneDistance = Sqr(LIGHT_POS[0]*LIGHT_POS[0]+LIGHT_POS[1]*LIGHT_POS[1]+LIGHT_POS[2]*LIGHT_POS[2])
  nearPlane = lightToSceneDistance - 150.0
  If nearPlane < 50.0  nearPlane = 50.0
  '// Keep the scene filling the depth texture
  fieldOfView = 17000.0 / lightToSceneDistance



 glViewport(0, 0, texsize, texsize)
  glMatrixMode(GL_PROJECTION)
  glLoadIdentity()
  'glFrustum(-12.0, 12.0, -20.0, 5.0, 13.0, 150.0)
 gluPerspective( 60,1, 13, 1000 )
	glGetFloatv(GL_PROJECTION_MATRIX, lightProjection)
  '// Switch To light's point of view
  glMatrixMode(GL_MODELVIEW)
  glLoadIdentity()
  gluLookAt(LIGHT_POS[0], LIGHT_POS[1], LIGHT_POS[2],0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
  glGetFloatv(GL_MODELVIEW_MATRIX, lightModelview)

  '// Clear the window with current clearing color
  glClear(GL_DEPTH_BUFFER_BIT)

  '// All we care about here is resulting depth values
  glShadeModel(GL_FLAT)
  glDisable(GL_LIGHTING)
  glDisable(GL_COLOR_MATERIAL)
  glDisable(GL_NORMALIZE)
  glColorMask(0, 0, 0, 0)

  '// Overcome imprecision
  glEnable(GL_POLYGON_OFFSET_FILL)

  '// Draw objects in the scene
  RenderObjects(True)

  '// Copy depth values into depth texture
  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,0, 0, texsize, texsize, 0)

  '// Restore normal drawing state
  glShadeModel(GL_SMOOTH)
  glEnable(GL_LIGHTING)
  glEnable(GL_COLOR_MATERIAL)
  glEnable(GL_NORMALIZE)
  glColorMask(1, 1, 1, 1)
  glDisable(GL_POLYGON_OFFSET_FILL)

  '// Set up texture matrix For shadow map projection
  glMatrixMode(GL_TEXTURE)
  glLoadIdentity()
  glTranslatef(0.5, 0.5, 0.5)
  glScalef(0.5, 0.5, 0.5)
  glMultMatrixf(lightProjection)
  glMultMatrixf(lightModelview)

End Function
'********************************************************


Last edited 2012


kfprimm(Posted 2012) [#6]
I believe the issue is caused by how you invoke Graphics3D.

Function Graphics3D(width:Int,height:Int,depth:Int=0,mode:Int=0,rate:Int=60,flags:Int=-1) 'SMALLFIXES added flags
TGlobal.Graphics3D(width,height,depth,mode,rate,flags)
End Function


It is compatible with Blitz3D, not the new BlitzMax graphics system.

Currently, you are setting the hertz value to, I believe, three.

It should be,
'GLGraphics 1024,768,0,60,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER
Graphics3D 1024,768,0,0,60,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER



SystemError51(Posted 2012) [#7]
I'll be damned :D haha - how could I have missed that


KronosUK(Posted 2012) [#8]
I've looked at getting shadow mapping into minib3d before but didn't get very far. I can say that I don't think you'll be able to do it "externally" you'll have to integrate it properly into the minib3d render process.

Looking at klepto's minib3dextnew mod to see how he fit his stencil shadow system into the minib3d framework might be instructive (but please don't use stencil shadows). It might give a few clues as to where the intercept points should be.

ps I find just using "Graphics3D 1024,768" is pretty fast for some reason


SystemError51(Posted 2012) [#9]
I was looking at implementing those stencil shadows... but it came at a prize. While the shadows do work, it messes up the rest. So that's not an option. I really want the code from that post I found.

Seems I have two options - either try to implement it somehow, or adapt my engine around the code with the shadows. I don't want to do the latter... but maybe I don't have a choice. I want my game to be really nice-looking


AdamRedwoods(Posted 2012) [#10]
this is where minib3d needs an update, to handle shader and fbo tricks and to isolate rendering of specific objects tied to specific cameras.
i have my own in progress, but monkey+minib3d has priority for now.


SystemError51(Posted 2012) [#11]
I'm looking at different approaches for Shadow Mapping at this point. I'll let you know if I have anything worth showing.