It's not very difficult to draw a texture mapped quad in 2D the same as you would in software. I am not sure why you thought it would be difficult. There are a few things to set up but then it's pretty straight forward.
Have a look at BRL's OpenGL Max2D module sourcecode and see how they do it there.
There are 5 basic steps.
1. Set up your orthogrpahic projection and viewport
a) GlOrtho2D() 'pass the window dimensions
b) glViewport() 'pass the window dimensions
2. Set up your texture and upload it from main memory to OpenGL
a) Set up the data transfer
b) Generate a new texture ID
c) Bind (select) the texture
c) Upload the texture image
d) Set the texture's filtering
3. Switch on texture mapping
a) glEnable(GL_TEXTURE_2D)
4. Define a quad, which comprises:
a) A call to glBegin(GL_QUADS) 'at the start
b) A call to glColor4ub(Red,Green,Blue,Alpha) 'for each vertex
c) A call to glTexCoord2f(TextureX,TextureY) 'for each vertex
d) A call to glVertex2i(X,Y) 'for each vertex
5. Finish the quad with glEnd() 'at the end
Texture coordinates range from 0 to 1 across a texture. The corners are at 0,0 - 0,1 - 1,0 and 1,1. Depending on what values you set up your orthographic projection with, you might then define vertex coords the same as pixel coords.
Optimizations:
If you could put multiple images or frames of an animation on a single texture image and then use texture coordinates which identify `windows` within an image to use as the source for pixels, then you could a) avoid switching to a different texture for each image which is quite a costly operation and b) render multiple quads within a single call to glBegin() which is also normally a costly operation if used for single objects. Also once you get multiple images onto a single texture you can then start using vertex arrays or vertex buffers to render multiple quads in a single function call - reduces function call overhead and speeds up rendering. Max2D doesn't do any of this.
What I did in my own higher level 2D library, based on OpenGL, is to create a glMultiBegin() function which keeps track of what type of primitives are currently being defined and if you want to define more of them it skips doing the glBegin()/GlEnd() calls. Then I draw my own quads more efficiently. When I'm done I do a glMultiEnd().
Also OpenGL has `display lists` which are like pre-compiled rendering instructions for things you want to draw the same many times. You can put all sorts of stuff into the list rather than it having effect immediately, and then call it later. You can put things like state changes, changes to matrices, geometry, etc in there. It will convert the function calls into a lower level of code understandable by the hardware, ie map to the hardware interface, and then when you call the list it can skip the overhead of the API calls etc. This all helps speed things up, even in OpenGL 1.1
I think Max2D has little option but to be DirectX compatible as well because a) there are far more Windows users with an opinion and b) on some machines DirectX is faster than OpenGL and c) on some machines the OpenGL driver is poor, non-existent, or needs updating to be hardware accelerated. I don't see that this really holds back Max2D, since most of what you could exploit from OpenGL would be doable in DirectX also. It's more a matter of motivation or planning from BRL.
Have a look at BRL's OpenGL Max2D module sourcecode and see how they do it there.
There are 5 basic steps.
1. Set up your orthogrpahic projection and viewport
a) GlOrtho2D() 'pass the window dimensions
b) glViewport() 'pass the window dimensions
2. Set up your texture and upload it from main memory to OpenGL
a) Set up the data transfer
b) Generate a new texture ID
c) Bind (select) the texture
c) Upload the texture image
d) Set the texture's filtering
3. Switch on texture mapping
a) glEnable(GL_TEXTURE_2D)
4. Define a quad, which comprises:
a) A call to glBegin(GL_QUADS) 'at the start
b) A call to glColor4ub(Red,Green,Blue,Alpha) 'for each vertex
c) A call to glTexCoord2f(TextureX,TextureY) 'for each vertex
d) A call to glVertex2i(X,Y) 'for each vertex
5. Finish the quad with glEnd() 'at the end
Texture coordinates range from 0 to 1 across a texture. The corners are at 0,0 - 0,1 - 1,0 and 1,1. Depending on what values you set up your orthographic projection with, you might then define vertex coords the same as pixel coords.
Optimizations:
If you could put multiple images or frames of an animation on a single texture image and then use texture coordinates which identify `windows` within an image to use as the source for pixels, then you could a) avoid switching to a different texture for each image which is quite a costly operation and b) render multiple quads within a single call to glBegin() which is also normally a costly operation if used for single objects. Also once you get multiple images onto a single texture you can then start using vertex arrays or vertex buffers to render multiple quads in a single function call - reduces function call overhead and speeds up rendering. Max2D doesn't do any of this.
What I did in my own higher level 2D library, based on OpenGL, is to create a glMultiBegin() function which keeps track of what type of primitives are currently being defined and if you want to define more of them it skips doing the glBegin()/GlEnd() calls. Then I draw my own quads more efficiently. When I'm done I do a glMultiEnd().
Also OpenGL has `display lists` which are like pre-compiled rendering instructions for things you want to draw the same many times. You can put all sorts of stuff into the list rather than it having effect immediately, and then call it later. You can put things like state changes, changes to matrices, geometry, etc in there. It will convert the function calls into a lower level of code understandable by the hardware, ie map to the hardware interface, and then when you call the list it can skip the overhead of the API calls etc. This all helps speed things up, even in OpenGL 1.1
I think Max2D has little option but to be DirectX compatible as well because a) there are far more Windows users with an opinion and b) on some machines DirectX is faster than OpenGL and c) on some machines the OpenGL driver is poor, non-existent, or needs updating to be hardware accelerated. I don't see that this really holds back Max2D, since most of what you could exploit from OpenGL would be doable in DirectX also. It's more a matter of motivation or planning from BRL.