Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Weird behavior with Allegro5 and openGL

Credits go to Billybob for helping out!
This thread is locked; no one can reply to it. rss feed Print
Weird behavior with Allegro5 and openGL
Vishiano
Member #12,652
March 2011
avatar

I'm getting some interesting behavior using Allegro 5 with GLTools. I'm learning openGL in my computer graphics class and for a class project I'm creating a quick shooter demo. I've used Allegro 4 before, and since Allegro 5 supports openGL, I've decided to reduce some of the complexity and use Allegro 5. I've copied some code from the OpenGL Superbible 5ed, and want to use a shader to create a moving star background. The book uses GLTools to simplify things and I've got all the GLTools stuff to work, however I cant seem to draw both my sprites and the star background. I can either draw the star background, or I can draw the sprites. When I try to draw both the stars and the sprites the stars get replaced by my sprites in a weird combination. Could someone look at my code and let me know what needs to be fixed? Thanks.

#SelectExpand
1GLuint starFieldShader; // The point sprite shader 2GLint locMVP; // The location of the ModelViewProjection matrix uniform 3GLint locTimeStamp; // The location of the time stamp 4GLint locTexture; // The location of the texture uniform 5 6GLuint starTexture; // The star texture texture object 7GLBatch starsBatch; 8GLFrustum viewFrustum; 9 10int main(int argc, char **argv) 11{ 12 al_init(); 13 al_init_image_addon(); 14 al_install_keyboard(); 15 al_install_mouse(); 16 al_set_new_display_flags(ALLEGRO_OPENGL); 17 ALLEGRO_DISPLAY *display = NULL; 18 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 19 ALLEGRO_TIMER *timer = NULL; 20 display = al_create_display(640, 480); 21 al_clear_to_color(al_map_rgba(0,0,0,0)); 22 23 timer = al_create_timer(1.0 / FPS); 24 25 GLenum err = glewInit(); 26 if (GLEW_OK != err) { 27 fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); 28 return 1; 29 } 30 31 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); 32 ALLEGRO_BITMAP *background; 33 background = al_load_bitmap("blkbackground.bmp"); 34 35 buffer = al_create_bitmap(640, 480); 36 al_set_target_bitmap(buffer); 37 al_clear_to_color(al_map_rgb(0,0,0)); 38 if(background==NULL) 39 cout<<"bad background bitmap"<<endl; 40 al_set_current_opengl_context(display); 41 42 //sprite pointers 43 player *ship; 44 ship = new player(); 45 46 //sprite handler// 47 master = new spritehandler(); 48 master->scrollRate = scrollRate; 49 master->player1 = ship; 50 master->destination = buffer; 51 master->enemy_config(); 52 53 bool redraw = true; 54 55 event_queue = al_create_event_queue(); 56 al_register_event_source(event_queue,al_get_display_event_source(display)); 57 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 58 al_register_event_source(event_queue, al_get_mouse_event_source()); 59 al_register_event_source(event_queue, al_get_keyboard_event_source()); 60 61 glMatrixMode(GL_PROJECTION); 62 glLoadIdentity(); 63 glShadeModel(GL_SMOOTH); 64 al_flip_display(); 65 66 al_start_timer(timer); 67 viewFrustum.SetPerspective(35.0f, float(640)/float(480), 1.0f, 1000.0f); 68 setup_background(); 69 70 while(1) 71 { 72 ALLEGRO_EVENT ev; 73 al_wait_for_event(event_queue, &ev); 74 if(ev.type == ALLEGRO_EVENT_TIMER) 75 { 76 redraw = true; 77 input(master->player1); 78 } 79 if(redraw==true && al_is_event_queue_empty(event_queue)) 80 { 81 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 82 al_set_target_backbuffer(display); 83 al_clear_to_color(al_map_rgb(0, 0, 0)); 84 redraw = false; 85 render(); 86 starsBatch.Draw(); 87//draws sprites, //al_draw_bitmap(buffer, 0, 0, ALLEGRO_VIDEO_BITMAP); 88 //when below is uncommented i get a sprite field instead of a star field 89 //master->update_members(clock(), total_frames, scroll); 90 al_flip_display(); 91 } 92 if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 93 break; 94 95 scroll+=scrollRate; 96 moveZ=scroll; 97//rest of function is not relevant 98 99 /////////////////////// 100void setup_background() 101{ 102 GLfloat fColors[4][4] = {{ 1.0f, 1.0f, 1.0f, 1.0f}, // White 103 { 0.67f, 0.68f, 0.82f, 1.0f}, // Blue Stars 104 { 1.0f, 0.5f, 0.5f, 1.0f}, // Reddish 105 { 1.0f, 0.82f, 0.65f, 1.0f}}; // Orange 106 107 starsBatch.Begin(GL_POINTS, NUM_STARS); 108 for(int i = 0; i < NUM_STARS; i++) 109 { 110 int iColor = 0; // All stars start as white 111 112 // One in five will be blue 113 if(rand() % 5 == 1) 114 iColor = 1; 115 116 // One in 50 red 117 if(rand() % 8 == 1) 118 iColor = 2; 119 120 // One in 100 is amber 121 if(rand() % 10 == 1) 122 iColor = 3; 123 124 125 starsBatch.Color4fv(fColors[iColor]); 126 127 M3DVector3f vPosition; 128 vPosition[0] = float(3000 - (rand() % 6000)) * 0.1f; 129 vPosition[1] = float(3000 - (rand() % 6000)) * 0.1f; 130 vPosition[2] = -float(rand() % 10000)-1.0f; // -1 to -1000.0f 131 132 starsBatch.Vertex3fv(vPosition); 133 } 134 starsBatch.End(); 135 136 starFieldShader = gltLoadShaderPairWithAttributes("SpaceFlight.vp", "SpaceFlight.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex", 137 GLT_ATTRIBUTE_COLOR, "vColor"); 138 139 locMVP = glGetUniformLocation(starFieldShader, "mvpMatrix"); 140 locTexture = glGetUniformLocation(starFieldShader, "starImage"); 141 locTimeStamp = glGetUniformLocation(starFieldShader, "timeStamp"); 142 143 glGenTextures(1, &starTexture); 144 star = al_load_bitmap("star.tga"); 145 al_set_target_bitmap(star); 146 starTexture = al_get_opengl_texture(star); 147 if (starTexture != 0) 148 glBindTexture(GL_TEXTURE_2D, starTexture); 149 else 150 cout<<"get opengl texture FAIL"; 151 cout<<al_get_opengl_fbo(star); 152} 153 154void render(void) 155{ 156 // Clear the window and the depth buffer 157 //glClear(GL_COLOR_BUFFER_BIT); 158 159 // Turn on additive blending 160 glEnable(GL_BLEND); 161 glBlendFunc(GL_ONE, GL_ONE); 162 163 // Let the vertex program determine the point size 164 glEnable(GL_PROGRAM_POINT_SIZE); 165 //glEnable(TEXTURE_2D); 166 167 // Bind to our shader, set uniforms 168 glUseProgram(starFieldShader); 169 glUniformMatrix4fv(locMVP, 1, GL_FALSE, viewFrustum.GetProjectionMatrix()); 170 glUniform1i(locTexture, 0); 171 172 // fTime goes from 0.0 to 999.0 and recycles 173 float fTime = moveZ; 174 glUniform1f(locTimeStamp, fTime*5); 175}

Billybob
Member #3,136
January 2003

I'm having trouble deciphering all your code, but it definitely sounds like a state issue, and probably related to the texture state.

For example, you only bind the starTexture once. It needs to be bound every time before you use it (render something that uses it).

EDIT: I'm going to take a wild guess and suggest you add glBindTexture(GL_TEXTURE_2D, starTexture); near the bottom of the render function.

Elias
Member #358
May 2000

I'm also having a hard time keeping track of the OpenGL state looking just at the code snippet. I'd try getting rid of the al_set_target_bitmap() and al_set_current_opengl_context() calls unless you know exactly why you need them and what they do.

--
"Either help out or stop whining" - Evert

Vishiano
Member #12,652
March 2011
avatar

Billybob, adding glBindTexture does remove the issue of the shader getting all screwed up, thanks. The example I took the code from only calls glBindTexture once, any idea why its different in Allegro?

Elias, I had al_set_target_bitmap() and al_set_current_opengl_context() in the code as an attempt to solve the issue, including them or excluding them doesn't seem to do anything. I added them in because I figured I wasn't being explicit enough in setting what opengl should use.

I still cant get my sprites to appear over the star field. Commenting out render() and starbatch.draw() gives me a blank screen, well commenting out setup_background(), lets me see me see my sprites. This would seem to indicate to me something in setup_background is the issue, but I really don't see anything in their that would cause my sprites not to be drawn.

thank you for the replies

Billybob
Member #3,136
January 2003

Vishiano said:

The example I took the code from only calls glBindTexture once, any idea why its different in Allegro?

glBindTexture tells OpenGL what texture to use for all the OpenGL calls following it, until another glBindTexture is called. i.e.

glBindTexture(someTexture1);
...
a bunch of OpenGL calls
(all of this will be drawn using someTexture1)
...
glBindTexture(someTexture2);
...
more OpenGL calls
(all of this will be drawn using someTexture2)
...

Now, al_draw_bitmap, internally, must call glBindTexture on the bitmap being drawn, so that it can ... well, draw it! So ...

al_draw_bitmap(some_awesome_image);
...
a bunch of OpenGL calls
(all of these will be drawn using some_awesome_image)
...
glBindTexture(someTexture2);
...
more OpenGL calls
(all of these will be drawn using someTexture2)

So, as you can see, by calling al_draw_bitmap, you've changed what texture is currently being used by OpenGL.

Quote:

I still cant get my sprites to appear over the star field.

You'll have to assist me in deciphering the specifics of your code. Is master->update_members the call that draws your sprites? or is it al_draw_bitmap(buffer, 0, 0, ALLEGRO_VIDEO_BITMAP)

Vishiano
Member #12,652
March 2011
avatar

My spritehandler class takes a pointer to an allegro bitmap and all the sprites it handles draw to that bitmap. In this case the allegro bitmap "buffer" is the destination. master->update_members(clock(), total_frames, scroll); runs through all the sprites and updates them, which includes drawing the sprite to the "buffer". Then after everything is placed on the "buffer", its drawn on the screen with al_draw_bitmap(buffer, 0, 0, ALLEGRO_VIDEO_BITMAP);

Thank you again for the reply.

Billybob
Member #3,136
January 2003

Would you mind showing the code for update_members? Do you call:

al_set_target_bitmap(buffer);
At the top of update_members?

If you don't, that's the problem. Or do this, if master doesn't have buffer in its scope:

al_set_target_bitmap(buffer);
master->update_members(clock(), total_frames, scroll);

Also, I don't think ALLEGRO_VIDEO_BITMAP is a valid flag for al_draw_bitmap. It should probably just be:

al_draw_bitmap(buffer, 0, 0, 0);

Vishiano
Member #12,652
March 2011
avatar

The spritehandler class doesn't do the drawing itself, it iterates through the sprites and calls draw for each sprite, which is derived from the sprite parent class.

#SelectExpand
1void sprite::draw(ALLEGRO_BITMAP *dest) 2 al_set_target_bitmap(dest); 3 al_draw_bitmap(image, (int)x-wOffset, (int)y-hOffset, 0); 4}

So the destination bitmap is set in the code. I'm pretty sure its not an issue with spritehandler since I can get my sprites to draw, just not when my shader batch is drawn. I did try your suggestion, but no luck.

I fixed the flags, I think I got them messed up with another allegro function. It did not break/fix anything, but thanks for the heads up.

Billybob
Member #3,136
January 2003

Well if setup_background is indeed causing the trouble, try commenting out pieces of setup_background one by one to narrow it down. I, too, can't see anything in there that would mess up the OpenGL state.

And just to double check, you commented out all of the starfield rendering related code, except for setup_background, and it displayed a black screen? But then also commenting out setup_background fixed it?

Vishiano
Member #12,652
March 2011
avatar

Commenting out the following lines lets me see my sprites

in setup_background()
starsBatch.Color4fv(fColors[iColor]);
starsBatch.Vertex3fv(vPosition);

in render()
glUseProgram(starFieldShader);

if any of those are not commented out, I just get a blank screen. I have no clue why this is.

Billybob
Member #3,136
January 2003

Okay, this is going to be fun!

Try doing this before drawing your sprites:

glDisableVertexAttribArray(GLT_ATTRIBUTE_VERTEX);
glDisableVertexAttribArray(GLT_ATTRIBUTE_COLOR);
glDisableVertexAttribArray(GLT_ATTRIBUTE_NORMAL);
glDisableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0);
glDisableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE1);
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

If you call Color4fv, or Vertex3fv on a GLBatch, it will muck with OpenGL's state. And obviously glUseProgram will tell OpenGL to use the shading program, even while calling al_draw_bitmap :P Hopefully the above will undo everything and make Allegro happy.

Vishiano
Member #12,652
March 2011
avatar

Yup that did it :) !!! Thanks a ton billybob. Just so if anyone else has any issues with GLTools or GLBatch or shaders, I'll copy my final "drawing" code and post it below

#SelectExpand
1if(redraw==true && al_is_event_queue_empty(event_queue)) 2 { 3 al_set_target_backbuffer(display); 4 al_clear_to_color(al_map_rgb(0, 0, 0)); 5 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 6 redraw = false; 7 render(); 8 starsBatch.Draw(); 9 glDisableVertexAttribArray(GLT_ATTRIBUTE_VERTEX); 10 glDisableVertexAttribArray(GLT_ATTRIBUTE_COLOR); 11 glDisableVertexAttribArray(GLT_ATTRIBUTE_NORMAL); 12 glDisableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0); 13 glDisableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE1); 14 glUseProgram(0); 15 glBindBuffer(GL_ARRAY_BUFFER, 0); 16 al_set_target_backbuffer(display); //draw to display 17 al_draw_bitmap(buffer, 0, 0, 0);//make sure is has alpha 18 al_set_target_bitmap(buffer);//set bitmap 19 al_clear_to_color(al_map_rgba(0,0,0,0));//clear bitmap 20 master->update_members(clock(), total_frames, scroll);//draw to bitmap "buffer" 21 al_flip_display(); //send to screen :) 22 }

Billybob
Member #3,136
January 2003

Vishiano said:

Yup that did it

Thank goodness! I'm glad you got it working 8-) And thank you for posting the working code, most people forget to post their solutions :P

Go to: