|
Allegro5 and OpenGL. Problem with drawing Allegro primitives |
Izual
Member #2,756
September 2002
|
Hello. I am trying to learn some OpenGL from https://learnopengl.com/ and i am trying to use Allegro 5 instead of GLFW that the tutorial uses. It seems that i got the OpenGL part working. I can see my triangle on the screen. The problem is when i want to switch back to Allegro primitives drawing functions, they do not work after using OpenGL draw calls. My question are: 1) Is this the correct way of using OpenGL with Allegro? If not is there other way to go about it? I am using: My code: 1#define ALLEGRO_UNSTABLE
2
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "allegro5/allegro.h"
7#include "allegro5/allegro_font.h"
8#include "allegro5/allegro_opengl.h"
9#include "allegro5/allegro_primitives.h"
10
11ALLEGRO_SHADER *as;
12ALLEGRO_DISPLAY *display;
13ALLEGRO_BITMAP *bmp;
14ALLEGRO_FONT *font;
15ALLEGRO_TRANSFORM t;
16ALLEGRO_STATE state;
17
18const char *vertexShaderSource =
19 "#version 330 core\n"
20 "layout (location = 0) in vec3 aPos;\n"
21 "void main()\n"
22 "{\n"
23 " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
24 "}\0";
25
26const char *fragmentShaderSource =
27 "#version 330 core\n"
28 "out vec4 FragColor;\n"
29 "void main()\n"
30 "{\n"
31 "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
32 "}\0";
33
34float vertices[] = { -0.5f, -0.5f, 0.0f,
35 0.5f, -0.5f, 0.0f,
36 0.0f, 0.5f, 0.0f };
37
38GLuint vbo;
39GLuint vao;
40GLuint vshader;
41GLuint fshader;
42GLuint shader_program;
43int glVersion[] = { -1, -1 };
44
45int main()
46 {
47 printf( "OpenGL with Allegro!\n" );
48
49 al_init();
50 al_init_font_addon();
51 al_init_primitives_addon();
52 al_set_new_display_flags( ALLEGRO_OPENGL | ALLEGRO_PROGRAMMABLE_PIPELINE );
53 display = al_create_display( 640, 480 );
54
55// Test bitmap:
56 bmp = al_create_bitmap( 64, 64 );
57 al_set_target_bitmap( bmp );
58 al_clear_to_color( al_map_rgb( 0, 255, 0 ) );
59 al_set_target_backbuffer( display );
60
61// Test font:
62 font = al_create_builtin_font();
63
64// OpenGL version check ( i get v.4.6 ):
65 glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]);
66 glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);
67 printf( "OpenGL %d.%d\n", glVersion[ 0 ], glVersion[ 1 ] );
68
69// Allegro shaders:
70 as = al_create_shader( ALLEGRO_SHADER_GLSL );
71 al_attach_shader_source( as, ALLEGRO_SHADER_GLSL, al_get_default_shader_source( ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER ) );
72 al_attach_shader_source( as, ALLEGRO_SHADER_GLSL, al_get_default_shader_source( ALLEGRO_SHADER_GLSL, ALLEGRO_PIXEL_SHADER ) );
73 al_build_shader( as );
74
75// Store Allegro state, all of it:
76 al_store_state( &state, ALLEGRO_STATE_ALL );
77
78// Custom shaders:
79 vshader = glCreateShader( GL_VERTEX_SHADER );
80 glShaderSource( vshader, 1, &vertexShaderSource, NULL );
81 glCompileShader( vshader );
82
83 fshader = glCreateShader( GL_FRAGMENT_SHADER );
84 glShaderSource( fshader, 1, &fragmentShaderSource, NULL);
85 glCompileShader( fshader);
86
87 shader_program = glCreateProgram();
88 glAttachShader( shader_program, vshader );
89 glAttachShader( shader_program, fshader);
90 glLinkProgram( shader_program);
91
92 glUseProgram( shader_program );
93
94// OpenGL stuff:
95 glViewport(0, 0, 640, 480);
96 glClearColor( 0.2f, 0.3f, 0.3f, 1.0f );
97 glClear( GL_COLOR_BUFFER_BIT );
98
99 glGenBuffers( 1, &vbo );
100 glGenVertexArrays( 1, &vao );
101
102// After commenting out this section Allegro primitives drawing works even
103// without drawing allegro bitmap or allegro text to the backbuffer first:
104 glBindVertexArray( vao );
105 glBindBuffer( GL_ARRAY_BUFFER, vbo );
106 glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
107 glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), ( void* )0 );
108 glEnableVertexAttribArray( 0 );
109 glDrawArrays( GL_TRIANGLES, 0, 3 );
110// End of section
111
112 glDeleteShader( vshader );
113 glDeleteShader( fshader );
114 glDeleteProgram( shader_program );
115
116// Restore Allegro shaders, transform and target backbuffer:
117 al_restore_state( &state );
118
119 al_set_current_opengl_context( display );
120 al_set_target_backbuffer( display );
121 al_use_shader( as );
122
123 al_identity_transform( &t );
124 al_use_transform( &t );
125
126// Disabling this draw bitmap and draw text calls also prevents the primitives
127// to by drawn when drawing with OpenGL. Drawing bitmap or text at least once
128// will fix the primitives drawing problem:
129// al_draw_bitmap( bmp, 64, 64, 0 );
130// al_draw_text( font, al_map_rgb( 0, 128, 255 ), 32, 32, 0, "Allegro text..." );
131
132// Our primitives that refuses to be drawn when using OpenGL:
133 al_draw_circle( 128, 128, 34, al_map_rgb( 128, 255, 255 ), 1.0 );
134 al_draw_line( 0, 0, 256, 256, al_map_rgb( 255, 0, 0 ), 1.0 );
135 al_draw_rectangle( 16, 16, 240, 240, al_map_rgb( 255, 255, 128 ), 1.0 );
136
137 al_flip_display();
138 al_rest( 3 );
139
140 al_destroy_bitmap( bmp );
141 al_destroy_font( font );
142 al_destroy_shader( as );
143
144 return 0;
145 }
Edit: Updated the code to reflect the changes that has been made so far.
|
Dizzy Egg
Member #10,824
March 2009
|
I imagine you want to call al_set_target_backbuffer again after doing your opengl calls. Not sure why calling al_draw_bitmap or al_draw_text does that for you, but that should fix it (I think!)
---------------------------------------------------- |
Edgar Reynaldo
Major Reynaldo
May 2007
|
OpenGL is a state engine. Allegro changes GL state when it does its thing, so things may not be as you left it once allegro touches it. You may need to reset the projection and view transforms. There is also a default shader per bitmap and other things I can't think of or don't know about. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Izual
Member #2,756
September 2002
|
Thank you for the tips. I tried to store and restore entire Allegro state using ALLEGRO_STATE_ALL parameter. I have updated the code in opening post to reflect the changes i made so far.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Store the allegro state before changing opengl stuff and when you're done restore it. I can't tell if you did that or not I don't see any changes in your code. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Dizzy Egg
Member #10,824
March 2009
|
You can also get the primitives to draw by locking the bakbuffer before drawing and unlocking after, so changing your primitive code to this: al_lock_bitmap(al_get_backbuffer(display), ALLEGRO_PIXEL_FORMAT_ANY, 0); al_draw_circle(128, 128, 34, al_map_rgb(128, 255, 255), 1.0); al_draw_line(0, 0, 256, 256, al_map_rgb(255, 0, 0), 1.0); al_draw_rectangle(16, 16, 240, 240, al_map_rgb(255, 255, 128), 1.0); al_unlock_bitmap(al_get_backbuffer(display)); Will work, so there's something happening with the openGL stuff that isn't being released until you either draw a bitmap (or text) to the backbuffer, or lock it before drawing primitives.... ....will need someone with more knowledge on the subject than me to tell you why though!
---------------------------------------------------- |
Izual
Member #2,756
September 2002
|
Thank you Dizzy. Locking the bitmaps allows me to draw the primitives but when the backbuffer is unlocked the drawing does not work again.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
You shouldn't ever have to lock the backbuffer. In fact to draw on it allegro has to unlock it. The projection transform might be getting changed somehow, that would make primitives 'disappear'. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Dizzy Egg
Member #10,824
March 2009
|
Odd that they appear if you draw an image or text first though, leads me to believe it’s more of an fbo issue or similar…
---------------------------------------------------- |
Peter Hull
Member #1,136
March 2001
|
Don't know if this is your problem but the second argument of al_attach_shader_source is a ALLEGRO_SHADER_TYPE not ALLEGRO_SHADER_PLATFORM i.e. should be ALLEGRO_VERTEX_SHADER or ALLEGRO_PIXEL_SHADER [edit] glBindBuffer( GL_ARRAY_BUFFER, 0); round about line 111.
|
Izual
Member #2,756
September 2002
|
Thank you Peter. Fixed the shader stuff. Adding glBindBuffer( GL_ARRAY_BUFFER, 0); causes a Segmentation Fault when trying to use any primitive drawing functions.
|
Dizzy Egg
Member #10,824
March 2009
|
You can get around it by doing your OpenGL drawing onto a buffer, and then drawing that to the display before your primitives: 1#define ALLEGRO_UNSTABLE
2
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "allegro5/allegro.h"
7#include "allegro5/allegro_font.h"
8#include "allegro5/allegro_opengl.h"
9#include "allegro5/allegro_primitives.h"
10
11ALLEGRO_SHADER* as;
12ALLEGRO_DISPLAY* display;
13ALLEGRO_BITMAP* bmp;
14ALLEGRO_BITMAP* buffer;
15ALLEGRO_FONT* font;
16ALLEGRO_STATE state;
17
18const char* vertexShaderSource =
19"#version 330 core\n"
20"layout (location = 0) in vec3 aPos;\n"
21"void main()\n"
22"{\n"
23" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
24"}\0";
25
26const char* fragmentShaderSource =
27"#version 330 core\n"
28"out vec4 FragColor;\n"
29"void main()\n"
30"{\n"
31"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
32"}\0";
33
34float vertices[] = { -0.5f, -0.5f, 0.0f,
35 0.5f, -0.5f, 0.0f,
36 0.0f, 0.5f, 0.0f };
37
38GLuint vbo;
39GLuint vao;
40GLuint vshader;
41GLuint fshader;
42GLuint shader_program;
43int glVersion[] = { -1, -1 };
44
45int main()
46{
47 printf("OpenGL with Allegro!\n");
48
49 al_init();
50 al_init_font_addon();
51 al_init_primitives_addon();
52 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_PROGRAMMABLE_PIPELINE);
53 display = al_create_display(640, 480);
54
55 //OpenGL buffer
56 buffer = al_create_bitmap(640, 480);
57
58 // Test bitmap:
59 bmp = al_create_bitmap(64, 64);
60 al_set_target_bitmap(bmp);
61 al_clear_to_color(al_map_rgb(0, 255, 0));
62
63 // Test font:
64 font = al_create_builtin_font();
65
66 // OpenGL version check ( i get v.4.6 ):
67 glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]);
68 glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);
69 printf("OpenGL %d.%d\n", glVersion[0], glVersion[1]);
70
71 // Allegro shaders:
72 as = al_create_shader(ALLEGRO_SHADER_GLSL);
73 al_attach_shader_source(as, ALLEGRO_VERTEX_SHADER, al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER));
74 al_attach_shader_source(as, ALLEGRO_PIXEL_SHADER, al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_PIXEL_SHADER));
75 al_build_shader(as);
76
77 // Store Allegro state, all of it:
78 al_store_state(&state, ALLEGRO_STATE_ALL);
79
80 //Set OpenGL buffer
81 al_set_target_bitmap(buffer);
82
83 // Custom shaders:
84 vshader = glCreateShader(GL_VERTEX_SHADER);
85 glShaderSource(vshader, 1, &vertexShaderSource, NULL);
86 glCompileShader(vshader);
87
88 fshader = glCreateShader(GL_FRAGMENT_SHADER);
89 glShaderSource(fshader, 1, &fragmentShaderSource, NULL);
90 glCompileShader(fshader);
91
92 shader_program = glCreateProgram();
93 glAttachShader(shader_program, vshader);
94 glAttachShader(shader_program, fshader);
95 glLinkProgram(shader_program);
96
97 glUseProgram(shader_program);
98
99 // OpenGL stuff:
100 glGenBuffers(1, &vbo);
101 glGenVertexArrays(1, &vao);
102
103 glBindVertexArray(vao);
104 glBindBuffer(GL_ARRAY_BUFFER, vbo);
105 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
106 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
107 glEnableVertexAttribArray(0);
108
109 glViewport(0, 0, 640, 480);
110 glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
111 glClear(GL_COLOR_BUFFER_BIT);
112 glDrawArrays(GL_TRIANGLES, 0, 3);
113 // End of section
114
115 // Restore Allegro shaders and state
116 al_restore_state(&state);
117 al_use_shader(as);
118
119 //Use display bitmap
120 al_set_target_backbuffer(display);
121
122 //Draw OpenGL buffer
123 al_draw_bitmap(buffer, 0, 0, 0);
124
125 //Draw primitives
126 al_draw_circle(128, 128, 34, al_map_rgb(128, 255, 255), 1.0);
127 al_draw_line(0, 0, 256, 256, al_map_rgb(255, 0, 0), 1.0);
128 al_draw_rectangle(16, 16, 240, 240, al_map_rgb(255, 255, 128), 1.0);
129
130 al_flip_display();
131 al_rest(3);
132
133 glDeleteShader(vshader);
134 glDeleteShader(fshader);
135 glDeleteProgram(shader_program);
136
137 al_destroy_bitmap(buffer);
138 al_destroy_bitmap(bmp);
139 al_destroy_font(font);
140 al_destroy_shader(as);
141
142 return 0;
143}
---------------------------------------------------- |
Peter Hull
Member #1,136
March 2001
|
I do think this ought to work, it shouldn't need 'getting around'. Unfortunately I can't help much more, mainly because I don't know much about OpenGL and also because it worked for me (on Debian). However, I wonder if it's right to delete the shaders and programs before the screen flip. Doesn't OpenGL batch up graphic operations sometimes? Also, when you say there's a segfault, can you get a backtrace? Where's it coming from? Pete
|
Dizzy Egg
Member #10,824
March 2009
|
If you only unbind the buffer, the al_draw_circle function cases an exception (at least, on Windows). And even if you don't draw the circle, although they don't crash, the other 2 primitives still aren't drawn. It seems you have to unbind the vertext buffer as well, calling glBindVertexArray(0) as well as glBindBuffer(0). Then you have to re-set the display as active. This example works without any workarounds and no locking bitmaps etc: 1#define ALLEGRO_UNSTABLE
2
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "allegro5/allegro.h"
7#include "allegro5/allegro_font.h"
8#include "allegro5/allegro_opengl.h"
9#include "allegro5/allegro_primitives.h"
10
11ALLEGRO_SHADER* as;
12ALLEGRO_DISPLAY* display;
13ALLEGRO_BITMAP* bmp;
14ALLEGRO_FONT* font;
15ALLEGRO_STATE state;
16
17const char* vertexShaderSource =
18"#version 330 core\n"
19"layout (location = 0) in vec3 aPos;\n"
20"void main()\n"
21"{\n"
22" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
23"}\0";
24
25const char* fragmentShaderSource =
26"#version 330 core\n"
27"out vec4 FragColor;\n"
28"void main()\n"
29"{\n"
30"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
31"}\0";
32
33float vertices[] = { -0.5f, -0.5f, 0.0f,
34 0.5f, -0.5f, 0.0f,
35 0.0f, 0.5f, 0.0f };
36
37GLuint vbo;
38GLuint vao;
39GLuint vshader;
40GLuint fshader;
41GLuint shader_program;
42int glVersion[] = { -1, -1 };
43
44int main()
45{
46 printf("OpenGL with Allegro!\n");
47
48 al_init();
49 al_init_font_addon();
50 al_init_primitives_addon();
51 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_PROGRAMMABLE_PIPELINE);
52 display = al_create_display(640, 480);
53
54 // Test bitmap:
55 bmp = al_create_bitmap(64, 64);
56 al_set_target_bitmap(bmp);
57 al_clear_to_color(al_map_rgb(0, 255, 0));
58
59 // Test font:
60 font = al_create_builtin_font();
61
62 // OpenGL version check ( i get v.4.6 ):
63 glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]);
64 glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);
65 printf("OpenGL %d.%d\n", glVersion[0], glVersion[1]);
66
67 // Allegro shaders:
68 as = al_create_shader(ALLEGRO_SHADER_GLSL);
69 al_attach_shader_source(as, ALLEGRO_VERTEX_SHADER, al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER));
70 al_attach_shader_source(as, ALLEGRO_PIXEL_SHADER, al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_PIXEL_SHADER));
71 al_build_shader(as);
72
73 // Store Allegro state, all of it:
74 al_store_state(&state, ALLEGRO_STATE_ALL);
75
76 //Set OpenGL buffer
77 al_set_target_backbuffer(display);
78
79 // Custom shaders:
80 vshader = glCreateShader(GL_VERTEX_SHADER);
81 glShaderSource(vshader, 1, &vertexShaderSource, NULL);
82 glCompileShader(vshader);
83
84 fshader = glCreateShader(GL_FRAGMENT_SHADER);
85 glShaderSource(fshader, 1, &fragmentShaderSource, NULL);
86 glCompileShader(fshader);
87
88 shader_program = glCreateProgram();
89 glAttachShader(shader_program, vshader);
90 glAttachShader(shader_program, fshader);
91 glLinkProgram(shader_program);
92
93 glUseProgram(shader_program);
94
95 // OpenGL stuff:
96 glGenBuffers(1, &vbo);
97 glGenVertexArrays(1, &vao);
98
99 glBindVertexArray(vao);
100 glBindBuffer(GL_ARRAY_BUFFER, vbo);
101 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
102 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
103 glEnableVertexAttribArray(0);
104
105 glViewport(0, 0, 640, 480);
106 glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
107 glClear(GL_COLOR_BUFFER_BIT);
108 glDrawArrays(GL_TRIANGLES, 0, 3);
109 // End of section
110
111 //Unbind vertex/buffer
112 glBindVertexArray(0);
113 glBindBuffer(GL_ARRAY_BUFFER, 0);
114
115 // Restore Allegro shaders and state
116 al_restore_state(&state);
117 al_use_shader(as);
118
119 //Use display bitmap
120 al_set_target_backbuffer(display);
121
122 //Draw primitives
123 al_draw_circle(128, 128, 34, al_map_rgb(128, 255, 255), 1.0);
124 al_draw_line(0, 0, 256, 256, al_map_rgb(255, 0, 0), 1.0);
125 al_draw_rectangle(16, 16, 240, 240, al_map_rgb(255, 255, 128), 1.0);
126
127 al_flip_display();
128 al_rest(3);
129
130 glDeleteShader(vshader);
131 glDeleteShader(fshader);
132 glDeleteProgram(shader_program);
133
134 al_destroy_bitmap(bmp);
135 al_destroy_font(font);
136 al_destroy_shader(as);
137
138 return 0;
139}
---------------------------------------------------- |
Izual
Member #2,756
September 2002
|
Thank You! Calling glBindVertexArray( 0 ) as well as glBindBuffer( 0 ) fixed it! Thank you again.
|
Dizzy Egg
Member #10,824
March 2009
|
You’re very welcome! We got there in the end! I don’t know much about OpenGL but after Peter said about binding the buffer back to 0 I figured it would be a case of getting allegro back to where it was before binding the OpenGL bits. Glad it’s all working, happy coding.
---------------------------------------------------- |
Peter Hull
Member #1,136
March 2001
|
Nice one Dizzy Egg!
|
|