// --------------------------------------------------------------------------- // // @file TwGLCoreSDL.c // @brief An example that uses AntTweakBar with OpenGL Core Profile // and SDL 1.3. // // AntTweakBar: http://anttweakbar.sourceforge.net/doc // OpenGL: http://www.opengl.org // SDL: http://www.libsdl.org // // @author Philippe Decaudin // // --------------------------------------------------------------------------- #include #ifdef _WIN32 // MiniSDL13.h is provided to avoid the need of having SDL installed to // recompile this example. Do not use it in your own programs, better // install and use the actual SDL library SDK. # define USE_MINI_SDL #endif //#define GL3_PROTOTYPES 1 //// //#include //// #ifdef USE_MINI_SDL # include "../src/MiniSDL13.h" #else # include #endif #include #include #include #ifdef _WIN32 # include // required by gl.h #endif #include #include // In this example, we draw a simple rotating square using the OpenGL core profile // (which requires much more code than with the compatibility profile). // A tweak bar is created to allow the user to change the color of the // rectangle and see its rotation. // Part of OpenGL core interface is not directly accessible from the common // OpenGL header and library (at least on windows) so we have to retrieve the // core functions using glGetProcAddress. These functions are prefixed by // underscore to avoid possible confict if a modified gl.h has been installed. #ifdef _WIN32 # define glGetProcAddress wglGetProcAddress #else # define GLX_GLXEXT_LEGACY # include # define glGetProcAddress glXGetProcAddressARB #endif #ifndef APIENTRY # define APIENTRY #endif typedef GLuint (APIENTRY *PFNGLCreateShader)(GLenum type); typedef void (APIENTRY *PFNGLDeleteShader)(GLuint shader); typedef void (APIENTRY *PFNGLShaderSource)(GLuint shader, GLsizei count, const char* *str, const GLint *length); typedef void (APIENTRY *PFNGLCompileShader)(GLuint shader); typedef void (APIENTRY *PFNGLAttachShader)(GLuint program, GLuint shader); typedef GLuint (APIENTRY *PFNGLCreateProgram)(void); typedef void (APIENTRY *PFNGLLinkProgram)(GLuint program); typedef void (APIENTRY *PFNGLUseProgram)(GLuint program); typedef void (APIENTRY *PFNGLDeleteProgram)(GLuint program); typedef void (APIENTRY *PFNGLGenBuffers)(GLsizei n, GLuint *buffers); typedef void (APIENTRY *PFNGLBindBuffer)(GLenum target, GLuint buffer); typedef void (APIENTRY *PFNGLVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRY *PFNGLEnableVertexAttribArray)(GLuint index); typedef void (APIENTRY *PFNGLGenVertexArrays)(GLsizei n, GLuint *arrays); typedef void (APIENTRY *PFNGLBindVertexArray)(GLuint array); typedef void (APIENTRY *PFNGLDeleteVertexArrays)(GLsizei n, const GLuint *arrays); typedef GLint (APIENTRY *PFNGLGetAttribLocation)(GLuint program, const char *name); typedef GLint (APIENTRY *PFNGLGetUniformLocation)(GLuint program, const char *name); typedef void (APIENTRY *PFNGLUniform1f)(GLint location, GLfloat v0); typedef void (APIENTRY *PFNGLUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRY *PFNGLBufferData)(GLenum target, ptrdiff_t size, const GLvoid *data, GLenum usage); typedef void (APIENTRY *PFNGLDeleteBuffers)(GLsizei n, const GLuint *buffers); PFNGLCreateShader _glCreateShader; PFNGLDeleteShader _glDeleteShader; PFNGLShaderSource _glShaderSource; PFNGLCompileShader _glCompileShader; PFNGLAttachShader _glAttachShader; PFNGLCreateProgram _glCreateProgram; PFNGLLinkProgram _glLinkProgram; PFNGLUseProgram _glUseProgram; PFNGLDeleteProgram _glDeleteProgram; PFNGLGenBuffers _glGenBuffers; PFNGLBindBuffer _glBindBuffer; PFNGLVertexAttribPointer _glVertexAttribPointer; PFNGLEnableVertexAttribArray _glEnableVertexAttribArray; PFNGLGenVertexArrays _glGenVertexArrays; PFNGLBindVertexArray _glBindVertexArray; PFNGLDeleteVertexArrays _glDeleteVertexArrays; PFNGLGetAttribLocation _glGetAttribLocation; PFNGLGetUniformLocation _glGetUniformLocation; PFNGLUniform1f _glUniform1f; PFNGLUniform3f _glUniform3f; PFNGLBufferData _glBufferData; PFNGLDeleteBuffers _glDeleteBuffers; #ifndef GL_ARRAY_BUFFER # define GL_ARRAY_BUFFER 0x8892 #endif #ifndef GL_STATIC_DRAW # define GL_STATIC_DRAW 0x88E4 #endif #ifndef GL_VERTEX_SHADER # define GL_VERTEX_SHADER 0x8B31 #endif #ifndef GL_FRAGMENT_SHADER # define GL_FRAGMENT_SHADER 0x8B30 #endif int LoadGLCoreFunctions() { _glCreateShader = (PFNGLCreateShader)glGetProcAddress("glCreateShader"); _glDeleteShader = (PFNGLDeleteShader)glGetProcAddress("glDeleteShader"); _glShaderSource = (PFNGLShaderSource)glGetProcAddress("glShaderSource"); _glCompileShader = (PFNGLCompileShader)glGetProcAddress("glCompileShader"); _glAttachShader = (PFNGLAttachShader)glGetProcAddress("glAttachShader"); _glCreateProgram = (PFNGLCreateProgram)glGetProcAddress("glCreateProgram"); _glLinkProgram = (PFNGLLinkProgram)glGetProcAddress("glLinkProgram"); _glUseProgram = (PFNGLUseProgram)glGetProcAddress("glUseProgram"); _glDeleteProgram = (PFNGLDeleteProgram)glGetProcAddress("glDeleteProgram"); _glGenBuffers = (PFNGLGenBuffers)glGetProcAddress("glGenBuffers"); _glBindBuffer = (PFNGLBindBuffer)glGetProcAddress("glBindBuffer"); _glVertexAttribPointer = (PFNGLVertexAttribPointer)glGetProcAddress("glVertexAttribPointer"); _glEnableVertexAttribArray = (PFNGLEnableVertexAttribArray)glGetProcAddress("glEnableVertexAttribArray"); _glGenVertexArrays = (PFNGLGenVertexArrays)glGetProcAddress("glGenVertexArrays"); _glBindVertexArray = (PFNGLBindVertexArray)glGetProcAddress("glBindVertexArray"); _glDeleteVertexArrays = (PFNGLDeleteVertexArrays)glGetProcAddress("glDeleteVertexArrays"); _glGetAttribLocation = (PFNGLGetAttribLocation)glGetProcAddress("glGetAttribLocation"); _glGetUniformLocation = (PFNGLGetUniformLocation)glGetProcAddress("glGetUniformLocation"); _glUniform1f = (PFNGLUniform1f)glGetProcAddress("glUniform1f"); _glUniform3f = (PFNGLUniform3f)glGetProcAddress("glUniform3f"); _glBufferData = (PFNGLBufferData)glGetProcAddress("glBufferData"); _glDeleteBuffers = (PFNGLDeleteBuffers)glGetProcAddress("glDeleteBuffers"); if (_glCreateShader == NULL || _glDeleteShader == NULL || _glShaderSource == NULL || _glCompileShader == NULL || _glAttachShader == NULL || _glCreateProgram == NULL || _glLinkProgram == NULL || _glUseProgram == NULL || _glDeleteProgram == NULL || _glGenBuffers == NULL || _glBindBuffer == NULL || _glVertexAttribPointer == NULL || _glEnableVertexAttribArray == NULL || _glGenVertexArrays == NULL || _glBindVertexArray == NULL || _glDeleteVertexArrays == NULL || _glGetAttribLocation == NULL || _glGetUniformLocation == NULL || _glUniform1f == NULL || _glUniform3f == NULL || _glBufferData == NULL || _glDeleteBuffers == NULL) return 0; else return 1; } // Shaders globals GLuint vshader, fshader, program, varray, buffer; GLint cosa, sina, colorloc; float angle = 0, quat[4]; float color[] = {0.8f, 1.0f, 0.2f}; float FLOAT_PI = 3.14159265f; void InitRender() { // Vertex shader char *vsource[] = { "#version 150 core\n" "uniform float cosa, sina;" "in vec3 vertex;" "void main() { gl_Position = vec4(cosa*vertex.x-sina*vertex.y, sina*vertex.x+cosa*vertex.y, 0, 1); }" }; // Fragment shader char *fsource[] = { "#version 150 core\n" "uniform vec3 color;" "out vec4 fcolor;" "void main() { fcolor = vec4(color, 1); }" }; // Geometry vertex array GLfloat vertices[] = { -0.5f, 0.5f, 0, -0.5f, -0.5f, 0, 0.5f, 0.5f, 0, 0.5f, -0.5f, 0 }; GLint vlocation; // Compile and bind shaders vshader = _glCreateShader(GL_VERTEX_SHADER); fshader = _glCreateShader(GL_FRAGMENT_SHADER); program = _glCreateProgram(); _glShaderSource(vshader, 1, vsource, NULL); _glShaderSource(fshader, 1, fsource, NULL); _glCompileShader(vshader); _glCompileShader(fshader); _glAttachShader(program, vshader); _glAttachShader(program, fshader); _glLinkProgram(program); _glUseProgram(program); cosa = _glGetUniformLocation(program, "cosa"); sina = _glGetUniformLocation(program, "sina"); colorloc = _glGetUniformLocation(program, "color"); // Create and bind vertex buffer _glGenVertexArrays(1, &varray); _glBindVertexArray(varray); _glGenBuffers(1, &buffer); _glBindBuffer(GL_ARRAY_BUFFER, buffer); _glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); vlocation = _glGetAttribLocation(program, "vertex"); _glVertexAttribPointer(vlocation, 3, GL_FLOAT, GL_TRUE, 0, NULL); _glEnableVertexAttribArray(vlocation); // GL states glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); } void UninitRender() { _glDeleteProgram(program); _glDeleteShader(fshader); _glDeleteShader(vshader); _glDeleteBuffers(1, &buffer); _glDeleteVertexArrays(1, &varray); } void Render() { _glUniform1f(cosa, (float)cos(angle)); _glUniform1f(sina, (float)sin(angle)); _glUniform3f(colorloc, color[0], color[1], color[2]); _glBindVertexArray(varray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } TwBar *CreateTweakBar() { TwBar *bar; // Create a tweak bar bar = TwNewBar("TweakBar"); TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with SDL and OpenGL Core Profile.\n' "); // Message added to the help bar. // Add variables TwAddVarRW(bar, "Rotation", TW_TYPE_QUAT4F, &quat, " opened=true help='Rectangle rotation' "); TwAddVarRW(bar, "Color", TW_TYPE_COLOR3F, &color, " opened=true help='Rectangle color' "); return bar; } // SDL redefines main #ifdef main # undef main #endif int main() { const SDL_VideoInfo* video = NULL; int width = 480, height = 480; int bpp, flags; int quit = 0; // Initialize SDL, then get the current video mode and use it to create a SDL window. if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } video = SDL_GetVideoInfo(); if (!video) { fprintf(stderr, "Video query failed: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } // Request GL context to be OpenGL 3.2 Core Profile SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); // Other GL attributes SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); //SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); bpp = video->vfmt->BitsPerPixel; flags = SDL_OPENGL | SDL_HWSURFACE; if (!SDL_SetVideoMode(width, height, bpp, flags)) { fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } SDL_WM_SetCaption("AntTweakBar example using OpenGL Core Profile and SDL", "AntTweakBar+GLCore+SDL"); // Enable SDL unicode and key-repeat SDL_EnableUNICODE(1); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // Load some OpenGL core functions if (!LoadGLCoreFunctions()) { fprintf(stderr, "OpenGL 3.2 not supported.\n"); SDL_Quit(); exit(1); } // Initialize AntTweakBar if (!TwInit(TW_OPENGL_CORE, NULL)) { fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError()); SDL_Quit(); exit(1); } // Tell the window size to AntTweakBar TwWindowSize(width, height); // Create a tweak bar CreateTweakBar(); // Set OpenGL viewport glViewport(0, 0, width, height); // Prepare GL shaders and programs for drawing InitRender(); // Main loop: // - Draw scene // - Process events while (!quit) { SDL_Event event; int handled; GLenum error; // Clear screen glClearColor(0.5f, 0.75f, 0.8f, 1); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Update angle and draw geometry angle = (float)SDL_GetTicks()/25.0f * (FLOAT_PI/180.0f); quat[0] = quat[1] = 0; quat[2] = (float)sin(angle/2.0f); quat[3] = (float)cos(angle/2.0f); Render(); // Draw tweak bars TwDraw(); // Present frame buffer SDL_GL_SwapBuffers(); // Process incoming events while (SDL_PollEvent(&event)) { // Send event to AntTweakBar handled = TwEventSDL(&event, SDL_MAJOR_VERSION, SDL_MINOR_VERSION); // If event has not been handled by AntTweakBar, process it if (!handled) { switch (event.type) { case SDL_QUIT: // Window is closed quit = 1; break; case SDL_VIDEORESIZE: // Window size has changed // Resize SDL video mode width = event.resize.w; height = event.resize.h; if (!SDL_SetVideoMode(width, height, bpp, flags)) fprintf(stderr, "WARNING: Video mode set failed: %s\n", SDL_GetError()); // Resize OpenGL viewport glViewport(0, 0, width, height); // Restore OpenGL states InitRender(); // TwWindowSize has been called by TwEventSDL, // so it is not necessary to call it again here. break; } } } while ((error = glGetError()) != GL_NO_ERROR) fprintf(stderr, "GL error detected: 0x%04X\n", error); } // End of main loop // Terminate AntTweakBar TwTerminate(); // Delete GL shaders and buffer UninitRender(); // Terminate SDL SDL_Quit(); return 0; }