Hello 3D Graphics!
GLHello is a desktop application that integrates views with 3D graphics along with other interface controls. The source code is in the /demo/glhello
folder of the SDK distribution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
/* GLDemo Application */ #include "nappgui.h" #include "glhello.h" #include "res_glhello.h" #include <ogl3d/ogl3d.h> #include "ogl1.h" #include "ogl2.h" #include "ogl3.h" typedef struct _app_t App; struct _app_t { Window *window; Panel *glpanel; View *glview; Label *errlabel; real32_t ptscale; OGL1 *ogl1; OGL2 *ogl2; OGL3 *ogl3; uint32_t api; real32_t angle; real32_t scale; Pixbuf *texdata; }; static App *APP = NULL; /*---------------------------------------------------------------------------*/ static void i_destroy_gl_apps(App *app) { if (app->ogl1 != NULL) ogl1_destroy(&app->ogl1); if (app->ogl2 != NULL) ogl2_destroy(&app->ogl2); if (app->ogl3 != NULL) ogl3_destroy(&app->ogl3); } /*---------------------------------------------------------------------------*/ static void i_set_glcontext(App *app, const uint32_t index) { if (index != app->api) { String *err = NULL; app->api = index; i_destroy_gl_apps(app); switch (index) { case 0: { oglerr_t glerr; app->ogl1 = ogl1_create(app->glview, &glerr); if (app->ogl1 == NULL) err = str_printf("Error creating OpenGL 1.1 context\n%s", ogl3d_err_str(glerr)); break; } case 1: { oglerr_t glerr; app->ogl2 = ogl2_create(app->glview, &glerr); if (app->ogl2 == NULL) err = str_printf("Error creating OpenGL 2.1 context\n%s", ogl3d_err_str(glerr)); break; } case 2: { oglerr_t glerr; app->ogl3 = ogl3_create(app->glview, &glerr); if (app->ogl3 == NULL) err = str_printf("Error creating OpenGL 3.3 context\n%s", ogl3d_err_str(glerr)); break; } case 3: err = str_printf("Error creating OpenGL 4.3 context\n%s", "Not available"); break; case 4: err = str_printf("Error creating DirectX 9 context\n%s", "Not available"); break; case 5: err = str_printf("Error creating DirectX 9.c context\n%s", "Not available"); break; case 6: err = str_printf("Error creating DirectX 10 context\n%s", "Not available"); break; case 7: err = str_printf("Error creating DirectX 11 context\n%s", "Not available"); break; case 8: err = str_printf("Error creating DirectX 12 context\n%s", "Not available"); break; case 9: err = str_printf("Error creating Vulkan context\n%s", "Not available"); break; case 10: err = str_printf("Error creating Metal context\n%s", "Not available"); break; } if (err == NULL) { panel_visible_layout(app->glpanel, 0); } else { label_text(app->errlabel, tc(err)); str_destroy(&err); panel_visible_layout(app->glpanel, 1); } panel_update(app->glpanel); view_update(app->glview); } } /*---------------------------------------------------------------------------*/ static void i_OnSelect(App *app, Event *e) { const EvButton *p = event_params(e, EvButton); i_set_glcontext(app, p->index); } /*---------------------------------------------------------------------------*/ static void i_OnDraw(App *app, Event *e) { const EvDraw *p = event_params(e, EvDraw); /* Some displays (macOS Retina) have double-scaled pixels */ real32_t width = p->width * app->ptscale; real32_t height = p->height * app->ptscale; switch (app->api) { case 0: ogl1_draw(app->ogl1, width, height, app->angle, app->scale); break; case 1: ogl2_draw(app->ogl2, width, height, app->angle, app->scale); break; case 2: ogl3_draw(app->ogl3, width, height, app->angle, app->scale); break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; case 9: break; case 10: break; } } /*---------------------------------------------------------------------------*/ static void i_OnSize(App *app, Event *e) { const EvSize *p = event_params(e, EvSize); real32_t width = p->width * app->ptscale; real32_t height = p->height * app->ptscale; switch (app->api) { case 0: ogl1_resize(app->ogl1, width, height); break; case 1: ogl2_resize(app->ogl2, width, height); break; case 2: ogl3_resize(app->ogl3, width, height); break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; case 9: break; case 10: break; } } /*---------------------------------------------------------------------------*/ static void i_OnAngle(App *app, Event *e) { const EvSlider *p = event_params(e, EvSlider); app->angle = p->pos; view_update(app->glview); } /*---------------------------------------------------------------------------*/ static void i_OnScale(App *app, Event *e) { const EvSlider *p = event_params(e, EvSlider); app->scale = 2 * p->pos; view_update(app->glview); } /*---------------------------------------------------------------------------*/ static Panel *i_gl_panel(App *app) { Panel *panel = panel_create(); View *view = view_create(); Label *label = label_multiline(); Font *font = font_system(20, ekFNORMAL); Layout *layout1 = layout_create(1, 1); Layout *layout2 = layout_create(1, 1); view_size(view, s2df(512, 512)); view_OnDraw(view, listener(app, i_OnDraw, App)); view_OnSize(view, listener(app, i_OnSize, App)); layout_view(layout1, view, 0, 0); label_font(label, font); label_align(label, ekCENTER); layout_label(layout2, label, 0, 0); layout_hsize(layout2, 0, 512); layout_vsize(layout2, 0, 512); layout_halign(layout2, 0, 0, ekCENTER); layout_valign(layout2, 0, 0, ekTOP); font_destroy(&font); panel_layout(panel, layout1); panel_layout(panel, layout2); app->errlabel = label; app->glpanel = panel; app->glview = view; view_point_scale(app->glview, &app->ptscale); return panel; } /*---------------------------------------------------------------------------*/ static Layout *i_rlayout(App *app) { Layout *layout = layout_create(1, 3); Panel *panel = i_gl_panel(app); Slider *slider1 = slider_create(); Slider *slider2 = slider_create(); slider_OnMoved(slider1, listener(app, i_OnAngle, App)); slider_OnMoved(slider2, listener(app, i_OnScale, App)); slider_value(slider2, .5f); layout_panel(layout, panel, 0, 0); layout_slider(layout, slider1, 0, 1); layout_slider(layout, slider2, 0, 2); layout_vmargin(layout, 0, 10); layout_vexpand(layout, 0); return layout; } /*---------------------------------------------------------------------------*/ static Panel *i_panel(App *app) { Panel *panel = panel_create(); Layout *layout1 = layout_create(2, 1); ListBox *listbox = listbox_create(); Layout *layout2 = i_rlayout(app); listbox_add_elem(listbox, "OpenGL 1.1/Fixed", NULL); listbox_add_elem(listbox, "OpenGL 2.1/GLSL", NULL); listbox_add_elem(listbox, "OpenGL 3.3", NULL); listbox_add_elem(listbox, "OpenGL 4", NULL); listbox_add_elem(listbox, "DirectX 9/Fixed", NULL); listbox_add_elem(listbox, "DirectX 9.c/HLSL", NULL); listbox_add_elem(listbox, "DirectX 10", NULL); listbox_add_elem(listbox, "DirectX 11", NULL); listbox_add_elem(listbox, "DirectX 12", NULL); listbox_add_elem(listbox, "Vulkan", NULL); listbox_add_elem(listbox, "Metal", NULL); listbox_select(listbox, 0, TRUE); listbox_OnSelect(listbox, listener(app, i_OnSelect, App)); listbox_size(listbox, s2df(150, 300)); layout_listbox(layout1, listbox, 0, 0); layout_layout(layout1, layout2, 1, 0); panel_layout(panel, layout1); layout_valign(layout1, 0, 0, ekTOP); layout_hsize(layout1, 0, 150); layout_hexpand(layout1, 1); layout_margin(layout1, 10); layout_hmargin(layout1, 0, 10); return panel; } /*---------------------------------------------------------------------------*/ static Window *i_window(App *app) { Panel *panel = i_panel(app); Window *window = window_create(ekWINDOW_STDRES); window_panel(window, panel); window_title(window, "Hello 3D Render"); i_set_glcontext(app, 0); return window; } /*---------------------------------------------------------------------------*/ static void i_OnClose(App *app, Event *e) { unref(app); unref(e); osapp_finish(); } /*---------------------------------------------------------------------------*/ static App *i_create(void) { App *app = NULL; app = heap_new0(App); APP = app; ogl3d_start(); app->api = UINT32_MAX; app->window = i_window(app); app->angle = 0; app->scale = 1; window_origin(app->window, v2df(500.f, 200.f)); window_OnClose(app->window, listener(app, i_OnClose, App)); window_show(app->window); return app; } /*---------------------------------------------------------------------------*/ static void i_destroy(App **app) { cassert_no_null(app); cassert_no_null(*app); i_destroy_gl_apps(*app); window_destroy(&(*app)->window); if ((*app)->texdata != NULL) pixbuf_destroy(&(*app)->texdata); ogl3d_finish(); heap_delete(app, App); } /*---------------------------------------------------------------------------*/ void glhello_texdata(const byte_t **texdata, uint32_t *texwidth, uint32_t *texheight, pixformat_t *texformat) { if (APP->texdata == NULL) { ResPack *pack = res_glhello_respack(""); APP->texdata = image_pixels(image_from_resource(pack, WALL_PNG), ekFIMAGE); respack_destroy(&pack); } *texdata = pixbuf_data(APP->texdata); *texwidth = pixbuf_width(APP->texdata); *texheight = pixbuf_height(APP->texdata); *texformat = pixbuf_format(APP->texdata); } /*---------------------------------------------------------------------------*/ #include "osmain.h" osmain(i_create, i_destroy, "", App) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
/* OpenGL 1 Demo */ #include "ogl1.h" #include "glhello.h" #include <ogl3d/ogl3d.h> #include <sewer/cassert.h> #include <core/heap.h> #include <gui/view.h> #include "nowarn.hxx" #include <ogl3d/glew.h> #include "warn.hxx" struct _ogl1_t { OGLCtx *ctx; GLboolean init; GLuint texture; }; /*---------------------------------------------------------------------------*/ OGL1 *ogl1_create(View *view, oglerr_t *err) { void *nview = view_native(view); OGLCtx *ctx = NULL; OGLProps props; props.api = ekOGL_1_1; props.hdaccel = TRUE; props.color_bpp = 32; props.depth_bpp = 0; props.stencil_bpp = 0; props.aux_buffers = 0; props.transparent = FALSE; props.shared = NULL; ctx = ogl3d_context(&props, nview, err); if (ctx != NULL) { OGL1 *ogl = heap_new0(OGL1); ogl->ctx = ctx; ogl->init = GL_FALSE; return ogl; } return NULL; } /*---------------------------------------------------------------------------*/ void ogl1_destroy(OGL1 **ogl) { cassert_no_null(ogl); cassert_no_null(*ogl); ogl3d_begin_draw((*ogl)->ctx); if ((*ogl)->init == GL_TRUE) { GLenum err; glBindTexture(GL_TEXTURE_2D, 0); glDeleteTextures(1, &(*ogl)->texture); cassert((err = glGetError()) == GL_NO_ERROR); unref(err); } ogl3d_end_draw((*ogl)->ctx); ogl3d_destroy(&(*ogl)->ctx); heap_delete(ogl, OGL1); } /*---------------------------------------------------------------------------*/ /* Data to be stored in GPU memory */ static void i_device_data(OGL1 *ogl) { const byte_t *texdata = NULL; uint32_t texwidth, texheight; pixformat_t texformat; glhello_texdata(&texdata, &texwidth, &texheight, &texformat); cassert(texformat == ekRGB24); glGenTextures(1, &ogl->texture); cassert(glGetError() == GL_NO_ERROR); glBindTexture(GL_TEXTURE_2D, ogl->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)texwidth, (GLsizei)texheight, 0, GL_RGB, GL_UNSIGNED_BYTE, (const void *)texdata); cassert(glGetError() == GL_NO_ERROR); } /*---------------------------------------------------------------------------*/ void ogl1_draw(OGL1 *ogl, const real32_t width, const real32_t height, const real32_t angle, const real32_t scale) { GLenum err; cassert_no_null(ogl); ogl3d_begin_draw(ogl->ctx); if (ogl->init == GL_FALSE) { i_device_data(ogl); ogl->init = GL_TRUE; } glViewport(0, 0, (GLsizei)width, (GLsizei)height); glClearColor(.8f, .8f, .8f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(scale, scale, 0); glRotatef(angle * 360, 0, 0, 1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ogl->texture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); /* Not in GL 1.1 */ /* glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); */ /* glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); */ cassert((err = glGetError()) == GL_NO_ERROR); glBegin(GL_TRIANGLES); glColor3f(1, 0, 0); glTexCoord2f(.5, 0); glVertex3f(0, 1, 0); glColor3f(0, 1, 0); glTexCoord2f(0, 1); glVertex3f(-1, -1, 0); glColor3f(0, 0, 1); glTexCoord2f(1, 1); glVertex3f(1, -1, 0); glEnd(); unref(err); ogl3d_end_draw(ogl->ctx); } /*---------------------------------------------------------------------------*/ void ogl1_resize(OGL1 *ogl, const real32_t width, const real32_t height) { cassert_no_null(ogl); ogl3d_set_size(ogl->ctx, (uint32_t)width, (uint32_t)height); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
/* OpenGL 2 Demo */ #include "ogl2.h" #include "glhello.h" #include <ogl3d/ogl3d.h> #include <sewer/bmath.h> #include <sewer/cassert.h> #include <core/heap.h> #include <gui/view.h> #include "nowarn.hxx" #include <ogl3d/glew.h> #include "warn.hxx" struct _ogl2_t { OGLCtx *ctx; GLboolean init; GLuint texture; GLuint vbo; GLuint ibo; GLuint pshader; GLint pos_vertex; GLint col_vertex; GLint tex_vertex; GLint mvp_uniform; GLint tex_uniform; }; /*---------------------------------------------------------------------------*/ static const GLchar *i_VS = "#version 120\n" "uniform mat4 uMVP;\n" "attribute vec3 vPos;\n" "attribute vec3 vColor;\n" "attribute vec2 vTex;\n" "varying vec3 outColor;\n" "varying vec2 texCoord;\n" "void main(void) {\n" " gl_Position = uMVP * vec4(vPos.xyz, 1);\n" " outColor = vColor;\n" " texCoord = vTex;\n" "}\n "; static const GLchar *i_FS = "#version 120\n" "varying vec3 outColor;\n" "varying vec2 texCoord;\n" "uniform sampler2D uTexture;\n" "void main (void) {\n" " gl_FragColor = vec4(outColor.xyz, 1.0);\n" " gl_FragColor *= texture2D(uTexture, texCoord);\n" "}\n"; /*---------------------------------------------------------------------------*/ OGL2 *ogl2_create(View *view, oglerr_t *err) { void *nview = view_native(view); OGLCtx *ctx = NULL; OGLProps props; props.api = ekOGL_2_1; props.hdaccel = TRUE; props.color_bpp = 32; props.depth_bpp = 0; props.stencil_bpp = 0; props.aux_buffers = 0; props.transparent = FALSE; props.shared = NULL; ctx = ogl3d_context(&props, nview, err); if (ctx != NULL) { OGL2 *ogl = heap_new0(OGL2); ogl->ctx = ctx; ogl->init = GL_FALSE; return ogl; } return NULL; } /*---------------------------------------------------------------------------*/ void ogl2_destroy(OGL2 **ogl) { cassert_no_null(ogl); cassert_no_null(*ogl); ogl3d_begin_draw((*ogl)->ctx); /* Delete all objects in device (GPU) space */ if ((*ogl)->init == GL_TRUE) { GLenum err; /* Unset all device objects */ glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glUseProgram(0); /* Delete the texture */ if ((*ogl)->texture != 0) { glDeleteTextures(1, &(*ogl)->texture); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->texture = 0; } /* Delete the shader */ if ((*ogl)->pshader != 0) { glDeleteProgram((*ogl)->pshader); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->pshader = 0; } /* Delete the Vertex Buffer Object */ if ((*ogl)->vbo != 0) { glDeleteBuffers(1, &(*ogl)->vbo); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->vbo = 0; } /* Delete the Index(Element) Buffer Object */ if ((*ogl)->ibo != 0) { glDeleteBuffers(1, &(*ogl)->ibo); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->ibo = 0; } unref(err); } ogl3d_end_draw((*ogl)->ctx); ogl3d_destroy(&(*ogl)->ctx); heap_delete(ogl, OGL2); } /*---------------------------------------------------------------------------*/ /* Data to be stored in GPU memory */ static void i_device_data(OGL2 *ogl) { float vertices[] = { 0, 1, 0, 1, 0, 0, .5f, 0, /* v0 pos, color, tex */ -1, -1, 0, 0, 1, 0, 0, 1, /* v1 pos, color, tex */ 1, -1, 0, 0, 0, 1, 1, 1}; /* v2 pos, color, tex */ uint32_t indices[] = {0, 1, 2}; const byte_t *texdata; uint32_t texwidth, texheight; pixformat_t texformat; GLuint vshader; GLuint fshader; GLint status; GLenum err; char info[512]; const char *version = cast_const(glGetString(GL_VERSION), char); const char *renderer = cast_const(glGetString(GL_RENDERER), char); unref(version); unref(renderer); /* Texture */ glhello_texdata(&texdata, &texwidth, &texheight, &texformat); cassert(texformat == ekRGB24); glGenTextures(1, &ogl->texture); cassert(glGetError() == GL_NO_ERROR); glBindTexture(GL_TEXTURE_2D, ogl->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)texwidth, (GLsizei)texheight, 0, GL_RGB, GL_UNSIGNED_BYTE, (const void *)texdata); cassert(glGetError() == GL_NO_ERROR); /* Vertex Buffer Object */ glGenBuffers(1, &ogl->vbo); glBindBuffer(GL_ARRAY_BUFFER, ogl->vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); /* Index Buffer */ glGenBuffers(1, &ogl->ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ogl->ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); /* Vertex Shader */ vshader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vshader, 1, &i_VS, NULL); glCompileShader(vshader); glGetShaderiv(vshader, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(vshader, 512, NULL, info); cassert(status != 0); /* Pixel Shader */ fshader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fshader, 1, &i_FS, NULL); glCompileShader(fshader); glGetShaderiv(fshader, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(fshader, 512, NULL, info); cassert(status != 0); /* Shader Program */ ogl->pshader = glCreateProgram(); glAttachShader(ogl->pshader, vshader); glAttachShader(ogl->pshader, fshader); /* The association between an attribute variable name and a generic attribute index can be specified at any time by calling glBindAttribLocation. Attribute bindings do not go into effect until glLinkProgram is called. After a program object has been linked successfully, the index values for attribute variables remain fixed until the next link command occurs. The attribute values can only be queried after a link if the link was successful. glGetAttribLocation returns the binding that actually went into effect the last time glLinkProgram was called for the specified program object. Attribute bindings that have been specified since the last link operation are not returned by glGetAttribLocation. */ glBindAttribLocation(ogl->pshader, 0, "vPos"); cassert((err = glGetError()) == GL_NO_ERROR); glBindAttribLocation(ogl->pshader, 1, "vColor"); cassert((err = glGetError()) == GL_NO_ERROR); glBindAttribLocation(ogl->pshader, 2, "vTex"); cassert((err = glGetError()) == GL_NO_ERROR); glLinkProgram(ogl->pshader); glGetProgramiv(ogl->pshader, GL_LINK_STATUS, &status); glGetProgramInfoLog(ogl->pshader, 512, NULL, info); cassert(status != 0); /* Shader Parameters */ ogl->pos_vertex = glGetAttribLocation(ogl->pshader, "vPos"); cassert((err = glGetError()) == GL_NO_ERROR); cassert(ogl->pos_vertex == 0); ogl->col_vertex = glGetAttribLocation(ogl->pshader, "vColor"); cassert((err = glGetError()) == GL_NO_ERROR); cassert(ogl->col_vertex == 1); ogl->tex_vertex = glGetAttribLocation(ogl->pshader, "vTex"); cassert((err = glGetError()) == GL_NO_ERROR); cassert(ogl->tex_vertex == 2); ogl->mvp_uniform = glGetUniformLocation(ogl->pshader, "uMVP"); cassert((err = glGetError()) == GL_NO_ERROR); ogl->tex_uniform = glGetUniformLocation(ogl->pshader, "uTexture"); cassert((err = glGetError()) == GL_NO_ERROR); /* Delete vertex and pixel shared already linked */ glDeleteShader(vshader); cassert((err = glGetError()) == GL_NO_ERROR); glDeleteShader(fshader); cassert((err = glGetError()) == GL_NO_ERROR); unref(err); } /*---------------------------------------------------------------------------*/ static void i_scale_rotate_Z(GLfloat *m, const real32_t a, const real32_t s) { real32_t ca = bmath_cosf(a); real32_t sa = bmath_sinf(a); m[0] = s * ca; m[1] = s * sa; m[2] = 0; m[3] = 0; m[4] = -s * sa; m[5] = s * ca; m[6] = 0; m[7] = 0; m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; } /*---------------------------------------------------------------------------*/ void ogl2_draw(OGL2 *ogl, const real32_t width, const real32_t height, const real32_t angle, const real32_t scale) { GLfloat m[16]; GLenum err; cassert_no_null(ogl); ogl3d_begin_draw(ogl->ctx); if (ogl->init == GL_FALSE) { i_device_data(ogl); ogl->init = GL_TRUE; } glViewport(0, 0, (GLsizei)width, (GLsizei)height); glClearColor(.8f, .8f, 0.8f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); /* Set the texture */ glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ogl->texture); cassert((err = glGetError()) == GL_NO_ERROR); /* Set vertex buffer */ glBindBuffer(GL_ARRAY_BUFFER, ogl->vbo); cassert((err = glGetError()) == GL_NO_ERROR); /* Set index buffer */ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ogl->ibo); cassert((err = glGetError()) == GL_NO_ERROR); /* Enable vertex attributes */ glVertexAttribPointer((GLuint)ogl->pos_vertex, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0); cassert((err = glGetError()) == GL_NO_ERROR); glEnableVertexAttribArray((GLuint)ogl->pos_vertex); cassert((err = glGetError()) == GL_NO_ERROR); glVertexAttribPointer((GLuint)ogl->col_vertex, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float))); cassert((err = glGetError()) == GL_NO_ERROR); glEnableVertexAttribArray((GLuint)ogl->col_vertex); cassert((err = glGetError()) == GL_NO_ERROR); glVertexAttribPointer((GLuint)ogl->tex_vertex, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float))); cassert((err = glGetError()) == GL_NO_ERROR); glEnableVertexAttribArray((GLuint)ogl->tex_vertex); cassert((err = glGetError()) == GL_NO_ERROR); /* Set the shader */ glUseProgram(ogl->pshader); cassert((err = glGetError()) == GL_NO_ERROR); /* Model-View-Projection and draw */ i_scale_rotate_Z(m, angle * 2 * kBMATH_PIf, scale); glUniformMatrix4fv(ogl->mvp_uniform, 1, GL_FALSE, m); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); cassert((err = glGetError()) == GL_NO_ERROR); ogl3d_end_draw(ogl->ctx); } /*---------------------------------------------------------------------------*/ void ogl2_resize(OGL2 *ogl, const real32_t width, const real32_t height) { cassert_no_null(ogl); ogl3d_set_size(ogl->ctx, (uint32_t)width, (uint32_t)height); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
/* OpenGL 3 Demo */ #include "ogl3.h" #include "glhello.h" #include <ogl3d/ogl3d.h> #include <sewer/bmath.h> #include <sewer/cassert.h> #include <core/heap.h> #include <gui/view.h> #include "nowarn.hxx" #include <ogl3d/glew.h> #include "warn.hxx" struct _ogl3_t { OGLCtx *ctx; GLboolean init; GLuint texture; GLuint vbo; GLuint vao; GLuint ibo; GLuint pshader; GLint mvp_uniform; GLint tex_uniform; }; /*---------------------------------------------------------------------------*/ static const GLchar *i_VS = "#version 330\n" "uniform mat4 uMVP;\n" "layout(location = 0) in vec3 vPos;\n" "layout(location = 1) in vec3 vColor;\n" "layout(location = 2) in vec2 vTex;\n" "out vec3 outColor;\n" "out vec2 texCoord;\n" "void main(void) {\n" " gl_Position = uMVP * vec4(vPos.xyz, 1);\n" " outColor = vColor;\n" " texCoord = vTex;\n" "}\n"; static const char_t *i_FS = "#version 330\n" "in vec3 outColor;\n" "in vec2 texCoord;\n" "out vec4 fragColor;\n" "uniform sampler2D uTexture;\n" "void main (void) {\n" " fragColor = vec4(outColor.xyz, 1.0);\n" " fragColor *= texture(uTexture, texCoord);\n" "}\n"; /*---------------------------------------------------------------------------*/ OGL3 *ogl3_create(View *view, oglerr_t *err) { void *nview = view_native(view); OGLCtx *ctx = NULL; OGLProps props; props.api = ekOGL_3_3; props.hdaccel = TRUE; props.color_bpp = 32; props.depth_bpp = 0; props.stencil_bpp = 0; props.aux_buffers = 0; props.transparent = FALSE; props.shared = NULL; ctx = ogl3d_context(&props, nview, err); if (ctx != NULL) { OGL3 *ogl = heap_new0(OGL3); ogl->ctx = ctx; ogl->init = GL_FALSE; return ogl; } return NULL; } /*---------------------------------------------------------------------------*/ void ogl3_destroy(OGL3 **ogl) { cassert_no_null(ogl); cassert_no_null(*ogl); ogl3d_begin_draw((*ogl)->ctx); /* Delete all objects in device (GPU) space */ if ((*ogl)->init == GL_TRUE) { GLenum err; /* Unset all device objects */ glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); glUseProgram(0); /* Delete the texture */ if ((*ogl)->texture != 0) { glDeleteTextures(1, &(*ogl)->texture); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->texture = 0; } /* Delete the shader */ if ((*ogl)->pshader != 0) { glDeleteProgram((*ogl)->pshader); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->pshader = 0; } /* Delete the Vertex Buffer Object */ if ((*ogl)->vbo != 0) { glDeleteBuffers(1, &(*ogl)->vbo); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->vbo = 0; } /* Delete the Vertex Array Object */ if ((*ogl)->vao != 0) { glDeleteVertexArrays(1, &(*ogl)->vao); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->vao = 0; } /* Delete the Index(Element) Buffer Object */ if ((*ogl)->ibo != 0) { glDeleteBuffers(1, &(*ogl)->ibo); cassert((err = glGetError()) == GL_NO_ERROR); (*ogl)->ibo = 0; } unref(err); } ogl3d_end_draw((*ogl)->ctx); ogl3d_destroy(&(*ogl)->ctx); heap_delete(ogl, OGL3); } /*---------------------------------------------------------------------------*/ /* Data to be stored in GPU memory */ static void i_device_data(OGL3 *ogl) { const float vertices[] = { 0, 1, 0, 1, 0, 0, .5f, 0, /* v0 pos, color, tex */ -1, -1, 0, 0, 1, 0, 0, 1, /* v1 pos, color, tex */ 1, -1, 0, 0, 0, 1, 1, 1}; /* v2 pos, color, tex */ uint32_t indices[] = {0, 1, 2}; const byte_t *texdata = NULL; uint32_t texwidth, texheight; pixformat_t texformat; GLuint vshader; GLuint fshader; GLint status; GLenum err; char info[512]; const char *version = cast_const(glGetString(GL_VERSION), char); const char *renderer = cast_const(glGetString(GL_RENDERER), char); unref(version); unref(renderer); /* Texture */ glhello_texdata(&texdata, &texwidth, &texheight, &texformat); cassert(texformat == ekRGB24); glGenTextures(1, &ogl->texture); cassert(glGetError() == GL_NO_ERROR); glBindTexture(GL_TEXTURE_2D, ogl->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)texwidth, (GLsizei)texheight, 0, GL_RGB, GL_UNSIGNED_BYTE, cast_const(texdata, void)); cassert(glGetError() == GL_NO_ERROR); /* Vertex Array Object */ glGenVertexArrays(1, &ogl->vao); glBindVertexArray(ogl->vao); cassert((err = glGetError()) == GL_NO_ERROR); /* Vertex Buffer Object */ glGenBuffers(1, &ogl->vbo); glBindBuffer(GL_ARRAY_BUFFER, ogl->vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); cassert((err = glGetError()) == GL_NO_ERROR); /* Enable vertex attributes */ /* 0 = layout(location = 0) vPos */ glVertexAttribPointer(0 /* vPos */, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0); cassert((err = glGetError()) == GL_NO_ERROR); glEnableVertexAttribArray(0 /* vPos */); cassert((err = glGetError()) == GL_NO_ERROR); /* 1 = layout(location = 1) vColor */ glVertexAttribPointer(1 /* vColor */, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float))); cassert((err = glGetError()) == GL_NO_ERROR); glEnableVertexAttribArray(1 /* vColor */); cassert((err = glGetError()) == GL_NO_ERROR); /* 2 = layout(location = 2) vTex */ glVertexAttribPointer(2 /* vTex */, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float))); cassert((err = glGetError()) == GL_NO_ERROR); glEnableVertexAttribArray(2 /* vTex */); cassert((err = glGetError()) == GL_NO_ERROR); /* Index Buffer */ glGenBuffers(1, &ogl->ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ogl->ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); cassert((err = glGetError()) == GL_NO_ERROR); /* Vertex Shader */ vshader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vshader, 1, &i_VS, NULL); glCompileShader(vshader); glGetShaderiv(vshader, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(vshader, 512, NULL, info); cassert(status != 0); /* Pixel Shader */ fshader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fshader, 1, &i_FS, NULL); glCompileShader(fshader); glGetShaderiv(fshader, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(fshader, 512, NULL, info); cassert(status != 0); /* Shader Program */ ogl->pshader = glCreateProgram(); glAttachShader(ogl->pshader, vshader); glAttachShader(ogl->pshader, fshader); glLinkProgram(ogl->pshader); glGetProgramiv(ogl->pshader, GL_LINK_STATUS, &status); glGetProgramInfoLog(ogl->pshader, 512, NULL, info); cassert(status != 0); /* Shader uniform access */ ogl->mvp_uniform = glGetUniformLocation(ogl->pshader, "uMVP"); cassert((err = glGetError()) == GL_NO_ERROR); ogl->tex_uniform = glGetUniformLocation(ogl->pshader, "uTexture"); cassert((err = glGetError()) == GL_NO_ERROR); /* Delete vertex and pixel shared already linked */ glDeleteShader(vshader); cassert((err = glGetError()) == GL_NO_ERROR); glDeleteShader(fshader); cassert((err = glGetError()) == GL_NO_ERROR); unref(err); } /*---------------------------------------------------------------------------*/ static void i_scale_rotate_Z(GLfloat *m, const real32_t a, const real32_t s) { real32_t ca = bmath_cosf(a); real32_t sa = bmath_sinf(a); m[0] = s * ca; m[1] = s * sa; m[2] = 0; m[3] = 0; m[4] = -s * sa; m[5] = s * ca; m[6] = 0; m[7] = 0; m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; } /*---------------------------------------------------------------------------*/ void ogl3_draw(OGL3 *ogl, const real32_t width, const real32_t height, const real32_t angle, const real32_t scale) { GLfloat m[16]; GLenum err; cassert_no_null(ogl); ogl3d_begin_draw(ogl->ctx); if (ogl->init == GL_FALSE) { i_device_data(ogl); ogl->init = GL_TRUE; } glViewport(0, 0, (GLsizei)width, (GLsizei)height); glClearColor(.8f, .8f, 0.8f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); /* Set the texture */ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ogl->texture); cassert((err = glGetError()) == GL_NO_ERROR); /* Set vertex array object */ glBindVertexArray(ogl->vao); cassert((err = glGetError()) == GL_NO_ERROR); /* Set index buffer object */ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ogl->ibo); cassert((err = glGetError()) == GL_NO_ERROR); /* Set the shader */ glUseProgram(ogl->pshader); cassert((err = glGetError()) == GL_NO_ERROR); /* Model-View-Projection and draw */ i_scale_rotate_Z(m, angle * 2 * kBMATH_PIf, scale); glUniformMatrix4fv(ogl->mvp_uniform, 1, GL_FALSE, m); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); cassert((err = glGetError()) == GL_NO_ERROR); ogl3d_end_draw(ogl->ctx); } /*---------------------------------------------------------------------------*/ void ogl3_resize(OGL3 *ogl, const real32_t width, const real32_t height) { cassert_no_null(ogl); ogl3d_set_size(ogl->ctx, (uint32_t)width, (uint32_t)height); } |