Simple quad program?

BlitzMax Forums/OpenGL Module/Simple quad program?

Who was John Galt?(Posted 2005) [#1]
Can you draw a quad with GL_QUADS without using openGL stuff to set a context (i.e. just draw it on a screen open with the graphics command)?

If so, anyone got some example code; I can't get it to work.


teamonkey(Posted 2005) [#2]
Yes, but if you want to use textures you might have problems.

Graphics sets the viewport to the current screen co-ordinates, remember. The default OpenGL viewport with bglCreateContext is -1,-1 to 1,1.


Who was John Galt?(Posted 2005) [#3]
tea -

why may there be a problem texturing?

I tried drawing a quad using screen coords and couldn't see it. Any ideas?


N(Posted 2005) [#4]
Drawing in Max2D and drawing in 'pure GL' using screen coordinates:
' Mode1 is pretty much the same as Mode2, except in Mode1
' the states are set up for you and transformations are
' performed in DrawRect, no transformations are performed
' in Mode2 for the sake of simplicity

Goto Mode1

' Pure Max2D
#Mode1

Graphics 800,600,0,0

While Not KeyDown(KEY_ESCAPE)
	
	Cls()
	
	SetColor(255,255,255)
	
	DrawRect(GraphicsWidth()*.5-64,GraphicsHeight()*.5-64,128,128)
	
	Flip()
	
	FlushMem
	
Wend

End





' Pure GL
#Mode2

bglCreateContext(800,600,0,0,BGL_BACKBUFFER | BGL_DEPTHBUFFER)

glOrtho(0,800,0,600,-10,10)

While Not KeyDown(KEY_ESCAPE)
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
	
	glBegin(GL_QUADS)
	
	glVertex2f(400-64,300-64)
	glVertex2f(400+64,300-64)
	glVertex2f(400+64,300+64)
	glVertex2f(400-64,300+64)
	
	glEnd()
	
	bglSwapBuffers()
	
	FlushMem
	
Wend

End


The problem you might run into with textures is that Max2D stores its own texture state variables and has its own functions for binding GL textures, but these functions aren't exposed, so basically, if you want to use GL and Max2D, you're screwed.


skidracer(Posted 2005) [#5]
Noel, as was explained to you before, it is simple a case of making sure you preserve the state of the OpenGL machine, if you want to use GLBindTexture in your own code then you need to restore it's previous state at the end of your code if you want to play nicely with Max2D, just like transformation and everything else.


N(Posted 2005) [#6]
skid: Or the functions that would make that much easier could be exposed. What do you think sounds easier?

Edit:
Let's look at your options..

1. Tell users to write code to save the GL state and then restore it afterwards.
2. Remove the line that says 'Private' in the GlMax2D code.
3. Don't respond.

What do you think sounds best in the long run? If you picked 1 or 3, you should seek help immediately. If you picked 2, you win a cookie the instant you make the change.


{cYan|de}(Posted 2005) [#7]
i agree with the one called cower, your not meant to fight the users, your meant to help the users


skidracer(Posted 2005) [#8]
Adding GL specific interfaces would simply pollute GLMax2D in the same way as adding DX specific public functions to DXMax2D. IMHO it is just as simple, more optimal and allows more flexibility for people banging GL directly to learn to restore it's state when sharing with GLMax2D.


GW(Posted 2005) [#9]
I think skidracer has a point. If there is going to be a DX 2d lib (dear god say its true!!) compatability would be good to keep


N(Posted 2005) [#10]
Then how about, instead of making a 2D and 3D modules seperate, you build a base device class that the engine and 2D modules expand upon?

I'm doing this for my engine, and it's not hard.


Dreamora(Posted 2005) [#11]
You mean the driver class which actually exists?


N(Posted 2005) [#12]
skidracer: I do agree with you there (however many times I tried to twist it around as a 'bad thing' in my book, it doesn't work), and thus if (probably worth it to continue reading, 'cause that's a big 'if' there) I decide to continue using Max2D I'll just modify it and expose the functions. Or not use Max2D. Which would probably be easier in the long run as then I wouldn't have to deal with its peculiar nuances.

Dreamora: It's not intended for anything beyond simple 2D application. Look at the source, it's obvious that they weren't thinking ahead when designing Max2D and Max3D as Max3D is going to have -another- device class which will then make the Max2D driver utterly useless to have. So what I think is neccessary is that if Blitz Research are going to use hardware acceleration primarily in their 2D system is to write a device class that has 2D and 3D functionality (general functionality, not full blown engine type but rather like the Direct3D Device class, it has DrawPrimitives, states, and such that can be modified via methods) and then Max2D and Max3D should be written to use this device class instead of depending on their own seperate device (or drivers as Mark calls them) classes.

The aforementioned device class proposed would obviously require writing new math classes which -- assuming Mark wouldn't go insane -- would be there for users to use and abuse the device class(es) with.

On another note (I say that way too much), I've been thinking about deleting Brl's Max2D and GLMax2D modules (and any others that depend on them) just because they aren't worth the trouble and then rewriting it in my own way that isn't as ack basswards and instead mimics a full 2D and 3D device class (similar to the Managed DirectX Direct3D Device class, in a sense). Actually, I've already done the device class, it's still a work in progress though..

Type CDevice Abstract
	Field Indices:Int[]
	Field Vertices:CVertex[]
	
	Field Material:CMaterial
	
	Field Width:Int,Height:Int
	
	Method ClearColor(R#,G#,B#,A#) Abstract
	Method SetViewport(X%,Y%,Width%,Height%) Abstract
	Method GetViewport(X:Int Ptr, Y:Int Ptr, _Width:Int Ptr, _Height:Int Ptr) Abstract
	
	Method DrawPrimitives(PrimitiveType:Int) Abstract
	Method SetVertexData(Indices:Int[],Vertices:CVertex[]) Abstract

	Method Clear(Enum:Int = CBuffers.Color | CBuffers.Depth) Abstract
	Method Present() Abstract
	
	Method SetWorldMatrix(mat:CMatrix) Abstract
	Method SetViewMatrix(mat:CMatrix) Abstract
	Method SetProjectionMatrix(mat:CMatrix) Abstract
	
	Method GetWorldMatrix:CMatrix() Abstract
	Method GetViewMatrix:CMatrix() Abstract
	Method GetProjectionMatrix:CMatrix() Abstract
	
	Method FreeObjectResources(i:Object) Abstract
	Method LoadObjectResources(i:Object) Abstract
	
	Method LoadVertexShader:CVertexShader(path$) Abstract
	Method LoadPixelShader:CPixelShader(path$) Abstract
	
	Method BindShader(i:CShader) Abstract
	Method BindTexture(i:CTexture) Abstract
	
	' Get this.. CEngine_Global_Device is.. PUBLIC!  Oh, my god, Becky.
	
	Method SetActiveDevice()
		CEngine_Global_Device = Self
	End Method
	
	Function GetActiveDevice:CDevice()
		Return CEngine_Global_Device
	End Function
End Type


At the moment, I have that working with OpenGL and I'm working on a software renderer for it now (wrapped SDL's 2D functions and such into a nice neat package so no hardware acceleration is required -- yes folks, I added 'real 2D', it's actually faster than normal Blitz2D/Plus stuff too).


Who was John Galt?(Posted 2005) [#13]
Noel : Thanx for the OGL/Max example.
Skid: Could you give an example or point me in the drection of a thread on restoring the OGL machine state?


skidracer(Posted 2005) [#14]
I'm not exactly experienced with OpenGL but from what I have seen in BlitzMax so far, if you are going to mess with glBindtexture GL_TEXTURE_2D then you need to save and restore the current state like this:
	glGetIntegerv GL_TEXTURE_BINDING_2D,VarPtr old_name

.. your code here

	glBindTexture GL_TEXTURE_2D,old_name


and to save and restore the matrix transformation I beleive you need to use the glPushMatrix and glPopMatrix commands.


teamonkey(Posted 2005) [#15]
I don't agree that Max2D is 'ass-backwards' (because it's clearly not) but it does make it difficult for third parties to make modules that extend it or are based on it. Essentially you have to rewrite the entire driver if you want to do something simple but different. This is a problem when:

* The official Max2D and glMax2D modules are updated
* You want to distribute the modified driver (based on the original driver code) with your module - the BlitzMax licence isn't clear whether you're legally allowed to do that.

Including a state lock/state restore function in Max2D would be wonderful for third-party developers. It doesn't solve all the problems, but it solves a lot of them.

Something like this (not thoroughly tested):
Strict
Import pub.opengl
Import brl.glmax2d

Private

Global lock_gl_texture_2d:Int
Global lock_gl_texture_binding_2d:Int
Global lock_blendstate:Int
Global lock_rgba:Byte[4]

Public

Rem
bbdoc: Locks the gl state so you can use OpenGL functions with glMax2D.
You can use native OpenGL functions between LockGL() and UnlockGL().
All Max2D commands <u>must</u> be called outside of those functions. Be nice
with your OpenGL and clean up after yourself before calling UnlockGL().
These functions rely on Max2D working in a specific way - if the Max2D
internals break, these functions will need to be updated. Note that Graphics()
does not initialise the depth buffer.
End Rem
Function LockGL()
	lock_blendstate = GetBlend()
	
	Local r:Int, g:Int, b:Int, a:Int
	a = GetAlpha()*255#
	If(a>255) Then a=255
	If(a<0) Then a=0
	
	GetColor(r, g, b)
	
	lock_rgba[0] = Byte(r)
	lock_rgba[1] = Byte(g)
	lock_rgba[2] = Byte(b)
	lock_rgba[3] = Byte(a)

	glPushMatrix()
	glGetBooleanv(GL_TEXTURE_2D, Varptr lock_gl_texture_2d)
	glGetIntegerv(GL_TEXTURE_BINDING_2D, Varptr lock_gl_texture_binding_2d)
End Function


Rem
bbdoc: Unlock the OpenGL state so Max2D can use it again
End Rem
Function UnlockGL()
	glBindTexture(GL_TEXTURE_2D,lock_gl_texture_binding_2d)

	If(lock_gl_texture_2d)
		glEnable(GL_TEXTURE_2D)
	Else
		glDisable(GL_TEXTURE_2D)
	EndIf

	glPopMatrix()
	
	SetBlend(lock_blendstate)
	glColor4ubv(lock_rgba)
End Function

That only stores some of the texture functions and the colour/alpha settings though - there's many other state variables that you can store, but many of them are very slow.


Who was John Galt?(Posted 2005) [#16]
Nice one TMonkey - I'll have a play with that later.