Dark Bit Factory & Gravity

GENERAL => Projects => Topic started by: jace_stknights on March 16, 2012

Title: [Cube] my project! (have changed the topic!)
Post by: jace_stknights on March 16, 2012
Hi all,

I've began some test in opengl this afternoon. For the moment I'm using Purebasic.

There's something I really don't understand. How can I match the pixels of screen with the space axis positions? I explain:

if I'm trying to put a 32*32 pixel gfx onto screen, and that I want it to be displayed truely in 32*32pixels, how can it be done?
This is usefull for retro remakes, as the logos, fonts should be displayed like in the original way.

In my example, I've made a simple scrolltext. After playing with the values of glTranslatef, I've found "good" value to display it but it is NOT the good one that make it like the original size.

here is the part of the code, the bitmap texture is 640*300 bmp includebinary, the fonts are 64*50 pixels

Code: [Select]
   cco = 0

  For cc = 0 To 11

   
    letter = (Asc(UCase(Mid(t.s, tptr+cc, 1)))-32)
    xf = ((letter % 10)*64)
    x.f = xf/640 ; find the x postion in matrix
    yf = (5-((letter - (letter%10))/10))*50
    y.f = yf/300 ; find the x position in matrix

    larg.f = 64*1/640  ; find the size of the font in matrix depth
    haut.f = 50*1/300

    glLoadIdentity_() ;Reset The Current Matrix
   
    glTranslatef_((cco+sco)-10.0,0,-20.0) ;Center On X, Y, Z Axis
   
    glPushMatrix_()
 
    glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select Our Texture
      glBegin_(#GL_QUADS)
   
        glTexCoord2f_(x, y) : glVertex3f_(-1.0,-1.0, 0.0) ;Bottom Left Of The Texture and Quad
        glTexCoord2f_((x+larg), y) : glVertex3f_( 1.0,-1.0, 0.0) ;Bottom Right Of The Texture and Quad
        glTexCoord2f_((x+larg), (y+haut)) : glVertex3f_( 1.0, 1.0, 0.0) ;Top Right Of The Texture and Quad
        glTexCoord2f_(x, (y+haut)) : glVertex3f_(-1.0, 1.0, 0.0) ;Top Left Of The Texture and Quad
      glEnd_()
    glPopMatrix_()
   
    cco = cco + 2 ; here is the problem : why it works with 2 ???   dunno...
  Next
 
  sco-0.2
  If sco<=-2.0
    sco = 0.0
    tptr+1
    If tptr > (Len(t.s)-12)
      tptr = 1
    EndIf
  EndIf
 

Title: Re: My first Opengl intro
Post by: Raizor on March 16, 2012
When working with 3D in OpenGL, it's common to use perspective projection and have the screen bounds range from -1 to +1. You can use Orthographic projection to set the screen bounds from 0 - 640 and 0 - 480 (or any other sizes you like), which is useful for situations where you want to use exact 2D coordinates.

I found this on a Nehe tutorial (http://nehe.gamedev.net/tutorial/radial_blur__rendering_to_a_texture/18004/). Hopefully it will help:

void ViewOrtho()                            // Set Up An Ortho View
{
    glMatrixMode(GL_PROJECTION);                    // Select Projection
    glPushMatrix();                         // Push The Matrix
    glLoadIdentity();                       // Reset The Matrix
    glOrtho( 0, 640 , 480 , 0, -1, 1 );             // Select Ortho Mode (640x480)
    glMatrixMode(GL_MODELVIEW);                 // Select Modelview Matrix
    glPushMatrix();                         // Push The Matrix
    glLoadIdentity();                       // Reset The Matrix
}
 
void ViewPerspective()                          // Set Up A Perspective View
{
    glMatrixMode( GL_PROJECTION );                  // Select Projection
    glPopMatrix();                          // Pop The Matrix
    glMatrixMode( GL_MODELVIEW );                   // Select Modelview
    glPopMatrix();                          // Pop The Matrix
}

Give that a whirl, changing the 640,480 to whatever scale you need. When drawing your vertices, you can then specify the coordinates in 2D space. Here's the official glOrtho docs (http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml) too, probably worth a read.

Also, this is kinda related to what you're trying to do (http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL) .

I often do something similar when doing render to texture type stuff.
Title: Re: My first Opengl intro
Post by: jace_stknights on March 16, 2012
thank you Raizor!!!  :cheers:
Title: Re: My first Opengl intro
Post by: jace_stknights on March 16, 2012
hmmm two things:

my first version (in perpective mode) runs with no vsync on my laptop (it has been made on my job computer and runs fine on it)... WTF?!?

and after some mods using the tricks you gave me, nothing runs on screen:

iInitGL()
Code: [Select]

 glEnable_(#GL_TEXTURE_2D) ;Enable Texture Mapping ( NEW )
 glClearColor_(0.0,0.0,0.0,0.5) ;Black Background
 glMatrixMode_(GL_PROJECTION)
 glPushMatrix_()
 glLoadIdentity_()
 glOrtho_(0, xres, xres, 0, -1, 1)
 glDisable_(GL_DEPTH_TEST)
 glMatrixMode_(GL_MODELVIEW)
 glPushMatrix_()
 glLoadIdentity_()

in DrawGLScene()
Code: [Select]
  glClear_(GL_COLOR_BUFFER_BIT)
 
  cco = 0

  ;For cc = 0 To 11

   
    ;letter = (Asc(UCase(Mid(t.s, tptr+cc, 1)))-32)
    ;x = ((letter % 10)*64)
    ;y = ((letter - (letter%10))/10)*50
 
    glLoadIdentity_() ;Reset The Current Matrix
   
   
    glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select Our Texture
   
    glBegin_(#GL_QUADS)
       glTexCoord2f_(0.0, 0.0) : glVertex2f_(cco,0)
       glTexCoord2f_(0.5, 0.0) : glVertex2f_(cco+64,0)
       glTexCoord2f_(0.5, 0.5) : glVertex2f_(cco+64,50)
       glTexCoord2f_(0.0, 0.5) : glVertex2f_(cco,50)
    glEnd_()

this sould display a 64*50 pixel textured at screen????
Title: Re: My first Opengl intro
Post by: Raizor on March 16, 2012
If you draw an untextured quad, does it work?
Title: Re: My first Opengl intro
Post by: jace_stknights on March 16, 2012
if I do this:
Code: [Select]

   glColor3f_(255, 128, 64)
    glBegin_(#GL_QUADS)
    glVertex2f_(cco,0)
    glVertex2f_(cco+64,0)
    glVertex2f_(cco+64,50)
    glVertex2f_(cco,50)
    glEnd_()
I still got a black screen  :-[
Title: Re: My first Opengl intro
Post by: Raizor on March 16, 2012
Can you upload the project please Jace? I'll have a look and see if I can figure out what's going on.
Title: Re: My first Opengl intro
Post by: Jim on March 17, 2012
Try
 glCullMode_(GL_NONE)

Your polygon is clockwise which is back-facing.

Jim
 
Title: Re: My first Opengl intro
Post by: jace_stknights on March 17, 2012
Try
 glCullMode_(GL_NONE)

Your polygon is clockwise which is back-facing.

Jim

glCullMode_  seems not be supported! :(

and I've changed the polygon  to counter-clockwise and still nothing...

I've attached the project...
Title: Re: My first Opengl intro
Post by: Jim on March 17, 2012
My apologies, it's glCullFace_
Jim
Title: Re: My first Opengl intro
Post by: jace_stknights on March 17, 2012
My apologies, it's glCullFace_
Jim
hehe  ;D

still not working (also tried with GL_FRONT GL_BACK) ??? ??? ??? ??? ??? ??? ??? :
Code: [Select]
    glLoadIdentity_() ;Reset The Current Matrix
   
    glCullFace_(GL_FRONT_AND_BACK)
       
    glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select Our Texture
    glColor3f_(255, 128, 6)
    glBegin_(#GL_QUADS)
    glTexCoord2f_(0.0, 0.0)
    glVertex2f_(cco,0)
    glTexCoord2f_(0.5, 0.0)
    glVertex2f_(cco,50)
    glTexCoord2f_(0.5, 0.5)
    glVertex2f_(cco+64,50)
    glTexCoord2f_(0.0, 0.5)
    glVertex2f_(cco+64,0)
    glEnd_()
Title: Re: My first Opengl intro
Post by: jace_stknights on March 17, 2012
Ok found the problem!

first I've forgotten the # before the commands!
Second : all values MUST be floats!!!

Code: [Select]
   glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select Our Texture
    glColor3f_(1.0, 1.0, 1.0)
    glBegin_(#GL_QUADS)
    glTexCoord2f_(0.0, 0.0) : glVertex2f_(0.0,0.0)
    glTexCoord2f_(0.5, 0.0) : glVertex2f_(64.0,0.0)
    glTexCoord2f_(0.5, 0.5) : glVertex2f_(64.0,50.0)
    glTexCoord2f_(0.0, 0.5) : glVertex2f_(0.0,50.0)
    glEnd_()

that's work now... well let's code again  ;D
Title: Re: My first Opengl intro
Post by: Raizor on March 17, 2012
Ok found the problem!

first I've forgotten the # before the commands!
Second : all values MUST be floats!!!

Code: [Select]
   glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select Our Texture
    glColor3f_(1.0, 1.0, 1.0)
    glBegin_(#GL_QUADS)
    glTexCoord2f_(0.0, 0.0) : glVertex2f_(0.0,0.0)
    glTexCoord2f_(0.5, 0.0) : glVertex2f_(64.0,0.0)
    glTexCoord2f_(0.5, 0.5) : glVertex2f_(64.0,50.0)
    glTexCoord2f_(0.0, 0.5) : glVertex2f_(0.0,50.0)
    glEnd_()

that's work now... well let's code again  ;D

Cool :)

You can probably use glVertex2i_ if you want to use ints rather than floats.
Title: Re: My first Opengl intro
Post by: jace_stknights on March 17, 2012
You can probably use glVertex2i_ if you want to use ints rather than floats.

 ;) I didn't now it was existing!

By the way, got it working, but there is still a problem: vsync ! The scrolltext is running 3000x to fast! I remember the tutorial from Stormbringer about this (http://www.dbfinteractive.com/forum/index.php?topic=4118.0). If I have understood on some cards, the vsync is not set. Ok But how to fix it in PureBasic???

Title: Re: My first Opengl intro
Post by: Raizor on March 17, 2012
You can either use delta timing to control movement (looks like this is covered in Stormbringer's tutorial), or the wglSwapIntervalEXT OpenGL extension. Have a look at this (http://stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl) for some more info on wglSwapIntervalEXT.

So far, I've been using delta timing. I get the system time each frame and then compare to the system time from the previous frame to determine how much time has elapsed between frames. I then use this 'difference' to determine how far to move things such as scrolltext etc.  For scrolltext, you can just determine the scroll offset using the elapsed time since the intro started. Something like scrollPosX = -timeTicks*someAmount. That's always worked reasonably well for me.

wglSwapIntervalEXT may well give a smoother result though (sometimes my scroller looks a little jerky when using delta timing, but that could just be me).
Title: Re: My first Opengl intro
Post by: hellfire on March 17, 2012
You can either use delta timing to control movement or the wglSwapIntervalEXT OpenGL extension.
It's always a good idea to enable vsync but it's not a reliable alternative to delta timing.
Title: Re: My first Opengl intro
Post by: jace_stknights on March 17, 2012
@Raizor, thank you, will take a look at this...

But I have tested some demo, and lot of them don't runat 60fps (with the vsync). For example, your wireframe scrolltext intro runs as fast as mine, about 500000 fps!  :o So even your technique seems not to work on my computer.

I've also saw that in stormbringer remakes, the option screen is running at 60fps, and not the remake itself... So perhaps my computer got a problem?
Title: Re: My first Opengl intro
Post by: Raizor on March 17, 2012
@Raizor, thank you, will take a look at this...

But I have tested some demo, and lot of them don't runat 60fps (with the vsync). For example, your wireframe scrolltext intro runs as fast as mine, about 500000 fps!  :o So even your technique seems not to work on my computer.

I've also saw that in stormbringer remakes, the option screen is running at 60fps, and not the remake itself... So perhaps my computer got a problem?

Normally your gfx card driver has a global vsync option. Something along the lines of "application controlled / force on / force off". That wireframe scroller was a bit of a mess. I did some nasty manual loop to eat up frame time until it had taken 16 ms per frame or something - a very hacky fix ;)
Title: Re: My first Opengl intro
Post by: jace_stknights on March 17, 2012
Hmmm I'm installing VC++ on my laptop (it was previoulsy on the ol done wich has broken down two month ago). I will compil STormy tutos and hope they work fine here.
This will be time to start with C++ code  ;D
Title: Re: My first Opengl intro
Post by: jace_stknights on March 18, 2012
after a lok at Stormy code, I found that he was also using "wglSwapIntervalEXT" to set the number of swap between two frames.
So I've tried this: (wglGetProcAddress_ is already imported by OpenGl32.lib)

Code: [Select]
   Protected wglSwapIntervalEXT.l
   wglSwapIntervalEXT = wglGetProcAddress_("wglSwapIntervalEXT")
   If wglSwapIntervalEXT
     CallFunctionFast(wglSwapIntervalEXT, 1)
     Debug "ok"
   Else
     Debug "wglSwapIntervalEXT not found"
   EndIf 

The function is present (debug ouput "ok") but still nothing  >:(
Title: Re: My first Opengl intro
Post by: Raizor on March 18, 2012
What gfx card do you have Jace? Maybe it doesn't support vsync, or it's set to "force off". Either way, probably time to look at delta timing :)
Title: Re: My first Opengl intro
Post by: jace_stknights on March 19, 2012
Hmm I'm discovering the obscur world of OpenGl...

Yep I think I will try the delta timing trick to force 1 swapbuffer between 2 frames.

Thank you for the help...
Title: Re: My first Opengl intro
Post by: jace_stknights on March 20, 2012
Could someone test the v2 version for the vsync (still in "3D" mode). I've put a delay() in the loop just before the swapbuffer(). Thank you!
Title: Re: My first Opengl intro
Post by: Raizor on March 20, 2012
Could someone test the v2 version for the vsync (still in "3D" mode). I've put a delay() in the loop just before the swapbuffer(). Thank you!

Tested on Nvidia GTX580, works with Vsync set to "App controlled", "Force On" and "Force Off".  The scroller seems a bit jerky though. Seems to skip a bit every second or so.
Title: Re: My first Opengl intro
Post by: jace_stknights on March 20, 2012
Tested on Nvidia GTX580, works with Vsync set to "App controlled", "Force On" and "Force Off".  The scroller seems a bit jerky though. Seems to skip a bit every second or so.
ok Thank you raizor...  hmmmmm jerky even if "force on" is set?
I have set off mine too (forgot it was possible  :-[) and have change the delay method. Got now a jerk because  of frame interlacing.... but it is running good... (see first_v3.zip)
Title: Re: My first Opengl intro
Post by: Raizor on March 20, 2012
v3 seems the same as v2 to me matey.
Title: Re: My first Opengl intro
Post by: jace_stknights on March 21, 2012
hum... I'm very disapointed...

OK you know what?? I will let down purebasic for opengl remake!!! :telloff:

EDIT: found a pearl here : http://www.purebasic.fr/english/viewtopic.php?t=28835 (http://www.purebasic.fr/english/viewtopic.php?t=28835) it seems it makes all for you and vsync is running!!!
Title: Re: My first Opengl intro
Post by: jace_stknights on April 23, 2012
Okay here I am again...

I've took a look at the SWOF example quoted in the last post. Hmmm I understand now the "way" the objects are taking place in the scene! (yep sorry, I was still in a global xyz wokring, like in the good old time)

In fact when you want to put something somewhere, you have to rotate, move the scene to the wanted position, put the object like it was a new 0,0,0 xyz axis and then move to the new position for the next object and so on.
So the simplest way is to translate and rotate back to the old position (with a negative action) and then make the new rotation and translation for the next object for example...

I really thought it was a bit different-> each object got its own translation and rotation, and the whole scene got it own also...

Title: Re: [Cube] my project! (have changed the topic!)
Post by: jace_stknights on April 26, 2012
Okay, I've changed the topic, coz I'm trying to make an opengl thing for the Cube Challenge!
But got some problems: If I'm trying to display hundred of cubes, it is really sloooowwwwww... I've tried to create a glNewList with #COMPILED option and display it, no way... still so slooow...

Someone got an idea?
Title: Re: [Cube] my project! (have changed the topic!)
Post by: Raizor on April 26, 2012
The problem is that you're sending the cube data to the GPU each frame, which gets rather slow when you have a lot of cubes (or other objects). I'd suggest looking into vertex buffer objects (VBOs). These allow you to create a buffer on the GPU to store your cube data, and then you just draw the cubes each frame using the data that's in the buffer on the GPU.

So, instead of saying to the GPU:
"Draw a cube at position X" 500 times

You first upload the cube data:
"GPU, here's the data for all my cubes, store it in a VBO buffer in GPU memory for me."

And each frame:
"GPU, draw that data I sent you before."

You're just uploading the data once, and then drawing the data each frame from the buffer on the GPU rather than sending it across again and again to the GPU.

It's gets a little complicated if you want to start animating the cubes as the data in the buffer needs to be updated if you're going to move things around individually. I'm doing something similar in my intro.  My solution was to store transformation data for the cubes in a texture coordinate VBO. For each cube vertex, I store a start and end position (and rotation) for the vertex and then draw everything using a custom shader. The shader looks up the associated texture coordinates (which I'm using to store position info) for each vertex and uses a time value fed into the shader to transition the vertex location between the start and end points stored in the texture coordinates. This allows me to animate lots of cubes without resending loads of data to the GPU each frame. From memory, I think I've got about 65,000 blocks or so flying about.

As well as drawing all the vertices in the vbo, you can just draw a section of the data (first 24 vertices, vertices 24 to 48 etc). This is what I was doing previously. I uploaded all my cube data into a VBO without transformations, and then drew the data in chunks of 24 vertices (1 cubes worth). In each iteration of the loop, I used glTranslate and glRotate to handle the position and rotation for the cube. This worked reasonably well, but is much, much slower than the method mentioned above. I think I was maxing out at around 5,000 cubes. It worked like this (excuse bad pseudo code):

for i = 0 to numCubes do

  // translate/rotate according to cube position/angle
  glTranslate (cube(i).translation)
  glRotate(cube(i).rotation)

  // draw 24 cube vertices at origin 0,0,0
  DrawCube()

  // undo translate/rotate ready for next cube draw
  glRotate(-cube(i).rotation)
  glTranslate (-cube(i).translation)

next i

That's probably not helped massively, but hopefully you get the gist a little. I had quite a job getting my VBO stuff working and understanding the concepts, so bear with it.

If you like, I'll package up my work-in-progress entry and send it to you. The code is quite messy, but may be of some use...

EDIT: Goddamn BBCode :P
Title: Re: [Cube] my project! (have changed the topic!)
Post by: Raizor on April 26, 2012
Here's some links from my bookmarks that I found useful when getting into this before:

Instancing in OpenGL (http://sol.gfxile.net/instancing.html)

OpenGL Vertex Buffer Objects (http://www.ozone3d.net/tutorials/opengl_vbo.php)

OpenGL Vertex Buffer Object (VBO) (http://www.songho.ca/opengl/gl_vbo.html)

OpenGL Vertex Buffer Objects (VBOs): A Simple Tutorial (http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html)

Vertex Buffer Object (OpenGL.org) (http://www.opengl.org/wiki/Vertex_Buffer_Object)
Title: Re: [Cube] my project! (have changed the topic!)
Post by: jace_stknights on April 27, 2012
Raizoooooor MY HERO!!!!!!!  :cheers: :cheers: :cheers: :cheers: :cheers: :cheers: :cheers: :cheers:

Ok I'm taking a STRONG look at all this!!!

EDIT: Hmmm gonna have a headache...
Title: Re: [Cube] my project! (have changed the topic!)
Post by: Raizor on April 27, 2012
Try getting a VBO to just draw a quad or a single triangle first. Once that's working you can beef it up.

My code looks something like this:

// vboVerts is a GLuint, this asks OpenGL to create me a buffer (VBO) and save the ID number in vboVerts
glGenBuffersARB(1, &vboVerts);

// ** upload vertex data to vbo
// bind to our VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboVerts);
// upload the vertex data from our verts4 pointer location. A vertex 4 is a vertex with X,Y,Z,W coords, we have 24 vertices per block as this is a cube.
// you could use just a 3 point vertex (X,Y,Z), I use 4 so I can store the vertex index in W for doing lookups in the shader later.
// vertex4 is just a custom struct type with x,y,z,w float values.
glBufferDataARB(GL_ARRAY_BUFFER_ARB, numblocks*24*sizeof(vertex4), &verts4[0], GL_STATIC_DRAW_ARB);
// unbind the VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

// and to draw the stuff
// tell OpenGL we want to enable vertex arrays to draw vertices
glEnableClientState(GL_VERTEX_ARRAY);   
// bind our VBO containing our vertices
glBindBufferARB( GL_ARRAY_BUFFER, vboVerts );
// Set pointer to vertex data fro drawing. The 4 is there because we have 4 points per vertex. The first 0 is stride (how many entries to skip after each vertex,
// sometimes we store vertex, color and normal data together in a chunk. If we do that we need to use stride to get GL to skip over the color and normal data for
// each entry in order to get to the next vertex. Since vboVerts contains only vertices, our stride is 0). The second 0 is used to point to a pointer containing the
// vertex data. Since we're using a VBO and we just bound it, we can provide 0 as the pointer and GL will use the VBO we just bound.
glVertexPointer(4, GL_FLOAT, 0, 0);

That's the basics. If you want to use VBOs for color and normal data, you create the VBOs in the same was as above and use the glEnableClientState with GL_NORMAL_ARRAY and GL_COLOR_ARRAY arguments. Bind them in the same way and use:

// set pointer to normal data. Normal data is always 3 points (x,y,z), so no size specified.
glNormalPointer(GL_FLOAT, 0, 0);
// same with color. here we're using 4 parts for color (r,g,b,a).
glColorPointer(4, GL_FLOAT, 0, 0);

When you've done your drawing, remember to disable any client states you enabled above:

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);

I'll leave the texcoord stuff until later as it will get confusing otherwise...




Title: Re: [Cube] my project! (have changed the topic!)
Post by: jace_stknights on April 27, 2012
thanx :D  will try this week-end if got some spare time -> the monsters have come back home!!!
Title: Re: [Cube] my project! (have changed the topic!)
Post by: Jim on May 01, 2012
Quote
In fact when you want to put something somewhere, you have to rotate, move the scene to the wanted position, put the object like it was a new 0,0,0 xyz axis and then move to the new position for the next object and so on.
So the simplest way is to translate and rotate back to the old position (with a negative action) and then make the new rotation and translation for the next object for example...
You don't need to do that.

Use the projection matrix to set up the view/camera matrix, then for each object
glPushMatrix()
glTranslate()
glRotate()
glPopMatrix()
no need to back-out with 'negative actions', glPush/PopMatrix are a stack of remembered matrices.

Jim
Title: Re: [Cube] my project! (have changed the topic!)
Post by: jace_stknights on May 02, 2012
thank you, i've discovered this when making my code... :P