|
Weird behavior with Allegro5 and openGL |
Vishiano
Member #12,652
March 2011
|
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. 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. -- |
Vishiano
Member #12,652
March 2011
|
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
|
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); 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
|
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. 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
|
Commenting out the following lines lets me see my sprites in setup_background() in render() 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 Hopefully the above will undo everything and make Allegro happy.
|
Vishiano
Member #12,652
March 2011
|
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 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 And thank you for posting the working code, most people forget to post their solutions
|
|