├── LICENSE ├── Makefile ├── README.md ├── gl_utils.cpp ├── glad.c ├── hello_colorful_triangle.cpp ├── include ├── KHR │ └── khrplatform.h ├── gl_utils.h └── glad │ └── glad.h ├── shader_triangle.frag └── shader_triangle.vert /LICENSE: -------------------------------------------------------------------------------- 1 | PLEASE NOTE 2 | 3 | Code from Anton Gerdelan (gl_utils) is under specific licence : 4 | https://github.com/capnramses/antons_opengl_tutorials_book/blob/master/LICENCE.md 5 | 6 | Code from learnOpenGL.com is under Creative Commons: 7 | https://github.com/JoeyDeVries/LearnOpenGL/blob/master/LICENSE.md 8 | 9 | Glad lib is free to use for any purpose. 10 | 11 | My code is public domain. 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Hellor Colorful Triangle Makefile 2 | # ludo456 @github 3 | # 4 | # -g adds debugging information to the executable file 5 | # -Wall turns on most, but not all, compiler warnings 6 | # 7 | 8 | CC = g++ 9 | CFLAGS = -g -Wall 10 | LIBS = -lGL -lglfw -ldl 11 | INCL = ./include 12 | DEPS = gl_utils.cpp glad.c 13 | EXE = hello_colorful_triangle 14 | 15 | .PHONY: run 16 | 17 | # typing 'make' will invoke the first target entry in the file 18 | # (in this case the default target entry) 19 | # you can name this target entry anything, but "default" or "all" 20 | # are the most commonly used names by convention 21 | # 22 | all: $(EXE) run 23 | 24 | # To create the executable file count we need the object files 25 | # countwords.o, counter.o, and scanner.o: 26 | # 27 | $(EXE): $(EXE).cpp $(DEPS) 28 | $(CC) $(CFLAGS) $^ $(LIBS) -I$(INCL) -o bin/$(EXE) 29 | 30 | run: 31 | ./bin/$(EXE) 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenGL-4.6-Hello-Triangle 2 | 3 | The famous OpenGL "Hello triangle" using shaders. It uses the OpenGL 4.5 functionality called [Direct State Access](https://www.khronos.org/opengl/wiki/Direct_State_Access). Be aware, not-that-old hardware may not be compatible with this functionality. 4 | 5 | As of November 2020, it is the most up-to-date "hello triangle" example I could piece together. 6 | 7 | ## Build and run 8 | 9 | I work on GNU/Linux Ubuntu 20. Obviously you need to install a compiler (g++), make, opengl and glfw3. 10 | 11 | `sudo apt install g++ build-essential libopengl0 libopengl-dev libglfw3 libglfw3-dev` 12 | 13 | Run `make` in the directory of the project. 14 | 15 | ## Glad 16 | 17 | This code uses Glad as its openGL extensions loader. Glew would work fine too. 18 | The directories include/glad, include/KHR, and the files glad.h, glad.c and khrplatform.h were generated from [Glad website](https://glad.dav1d.de/) 19 | 20 | ## Greetings 21 | 22 | I copied/modified code from [Anton Gerdelan](https://antongerdelan.net/opengl/index.html) and [Joey De Vries / Learnopengl](https://learnopengl.com/Getting-started/Shaders). See Licence file for more info. Also check [Fendevel repos about modern OpenGL](https://github.com/fendevel). 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /gl_utils.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | | OpenGL 4 Example Code. | 3 | | Accompanies written series "Anton's OpenGL 4 Tutorials" | 4 | | Email: anton at antongerdelan dot net | 5 | | First version 27 Jan 2014 | 6 | | Dr Anton Gerdelan, Trinity College Dublin, Ireland. | 7 | | See individual libraries separate legal notices | 8 | |******************************************************************************| 9 | | This is just a file holding some commonly-used "utility" functions to keep | 10 | | the main file a bit easier to read. You can might build up something like | 11 | | this as learn more GL. Note that you don't need much code here to do good GL.| 12 | | If you have a big object-oriented engine then maybe you can ask yourself if | 13 | | it is really making life easier. | 14 | \******************************************************************************/ 15 | #include "include/gl_utils.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define GL_LOG_FILE "gl.log" 21 | #define MAX_SHADER_LENGTH 262144 22 | 23 | /*--------------------------------LOG FUNCTIONS-------------------------------*/ 24 | bool restart_gl_log() { 25 | FILE* file = fopen( GL_LOG_FILE, "w" ); 26 | if ( !file ) { 27 | fprintf( stderr, "ERROR: could not open GL_LOG_FILE log file %s for writing\n", GL_LOG_FILE ); 28 | return false; 29 | } 30 | time_t now = time( NULL ); 31 | char* date = ctime( &now ); 32 | fprintf( file, "GL_LOG_FILE log. local time %s\n", date ); 33 | fclose( file ); 34 | return true; 35 | } 36 | 37 | bool gl_log( const char* message, ... ) { 38 | va_list argptr; 39 | FILE* file = fopen( GL_LOG_FILE, "a" ); 40 | if ( !file ) { 41 | fprintf( stderr, "ERROR: could not open GL_LOG_FILE %s file for appending\n", GL_LOG_FILE ); 42 | return false; 43 | } 44 | va_start( argptr, message ); 45 | vfprintf( file, message, argptr ); 46 | va_end( argptr ); 47 | fclose( file ); 48 | return true; 49 | } 50 | 51 | /* same as gl_log except also prints to stderr */ 52 | bool gl_log_err( const char* message, ... ) { 53 | va_list argptr; 54 | FILE* file = fopen( GL_LOG_FILE, "a" ); 55 | if ( !file ) { 56 | fprintf( stderr, "ERROR: could not open GL_LOG_FILE %s file for appending\n", GL_LOG_FILE ); 57 | return false; 58 | } 59 | va_start( argptr, message ); 60 | vfprintf( file, message, argptr ); 61 | va_end( argptr ); 62 | va_start( argptr, message ); 63 | vfprintf( stderr, message, argptr ); 64 | va_end( argptr ); 65 | fclose( file ); 66 | return true; 67 | } 68 | 69 | 70 | void glfw_error_callback( int error, const char* description ) { 71 | fputs( description, stderr ); 72 | gl_log_err( "%s\n", description ); 73 | } 74 | 75 | 76 | void _update_fps_counter( GLFWwindow* window ) { 77 | static double previous_seconds = glfwGetTime(); 78 | static int frame_count; 79 | double current_seconds = glfwGetTime(); 80 | double elapsed_seconds = current_seconds - previous_seconds; 81 | if ( elapsed_seconds > 0.25 ) { 82 | previous_seconds = current_seconds; 83 | double fps = (double)frame_count / elapsed_seconds; 84 | char tmp[128]; 85 | sprintf( tmp, "opengl @ fps: %.2f", fps ); 86 | glfwSetWindowTitle( window, tmp ); 87 | frame_count = 0; 88 | } 89 | frame_count++; 90 | } 91 | 92 | /*-----------------------------------SHADERS----------------------------------*/ 93 | /* copy a shader from a plain text file into a character array */ 94 | bool parse_file_into_str( const char* file_name, char* shader_str, int max_len ) { 95 | FILE* file = fopen( file_name, "r" ); 96 | if ( !file ) { 97 | gl_log_err( "ERROR: opening file for reading: %s\n", file_name ); 98 | return false; 99 | } 100 | size_t cnt = fread( shader_str, 1, max_len - 1, file ); 101 | if ( (int)cnt >= max_len - 1 ) { gl_log_err( "WARNING: file %s too big - truncated.\n", file_name ); } 102 | if ( ferror( file ) ) { 103 | gl_log_err( "ERROR: reading shader file %s\n", file_name ); 104 | fclose( file ); 105 | return false; 106 | } 107 | // append \0 to end of file string 108 | shader_str[cnt] = 0; 109 | fclose( file ); 110 | return true; 111 | } 112 | 113 | void print_shader_info_log( GLuint shader_index ) { 114 | int max_length = 2048; 115 | int actual_length = 0; 116 | char log[2048]; 117 | glGetShaderInfoLog( shader_index, max_length, &actual_length, log ); 118 | printf( "shader info log for GL index %i:\n%s\n", shader_index, log ); 119 | gl_log( "shader info log for GL index %i:\n%s\n", shader_index, log ); 120 | } 121 | 122 | bool create_shader( const char* file_name, GLuint* shader, GLenum type ) { 123 | gl_log( "creating shader from %s...\n", file_name ); 124 | char shader_string[MAX_SHADER_LENGTH]; 125 | parse_file_into_str( file_name, shader_string, MAX_SHADER_LENGTH ); 126 | *shader = glCreateShader( type ); 127 | const GLchar* p = (const GLchar*)shader_string; 128 | glShaderSource( *shader, 1, &p, NULL ); 129 | glCompileShader( *shader ); 130 | // check for compile errors 131 | int params = -1; 132 | glGetShaderiv( *shader, GL_COMPILE_STATUS, ¶ms ); 133 | if ( GL_TRUE != params ) { 134 | gl_log_err( "ERROR: GL shader index %i did not compile\n", *shader ); 135 | print_shader_info_log( *shader ); 136 | return false; // or exit or something 137 | } 138 | gl_log( "shader compiled. index %i\n", *shader ); 139 | return true; 140 | } 141 | 142 | void print_programme_info_log( GLuint sp ) { 143 | int max_length = 2048; 144 | int actual_length = 0; 145 | char log[2048]; 146 | glGetProgramInfoLog( sp, max_length, &actual_length, log ); 147 | printf( "program info log for GL index %u:\n%s", sp, log ); 148 | gl_log( "program info log for GL index %u:\n%s", sp, log ); 149 | } 150 | 151 | bool is_programme_valid( GLuint sp ) { 152 | glValidateProgram( sp ); 153 | GLint params = -1; 154 | glGetProgramiv( sp, GL_VALIDATE_STATUS, ¶ms ); 155 | if ( GL_TRUE != params ) { 156 | gl_log_err( "program %i GL_VALIDATE_STATUS = GL_FALSE\n", sp ); 157 | print_programme_info_log( sp ); 158 | return false; 159 | } 160 | gl_log( "program %i GL_VALIDATE_STATUS = GL_TRUE\n", sp ); 161 | return true; 162 | } 163 | 164 | bool create_programme( GLuint vert, GLuint frag, GLuint* programme ) { 165 | *programme = glCreateProgram(); 166 | gl_log( "created programme %u. attaching shaders %u and %u...\n", *programme, vert, frag ); 167 | glAttachShader( *programme, vert ); 168 | glAttachShader( *programme, frag ); 169 | // link the shader programme. if binding input attributes do that before link 170 | glLinkProgram( *programme ); 171 | GLint params = -1; 172 | glGetProgramiv( *programme, GL_LINK_STATUS, ¶ms ); 173 | if ( GL_TRUE != params ) { 174 | gl_log_err( "ERROR: could not link shader programme GL index %u\n", *programme ); 175 | print_programme_info_log( *programme ); 176 | return false; 177 | } 178 | ( is_programme_valid( *programme ) ); 179 | // delete shaders here to free memory 180 | glDeleteShader( vert ); 181 | glDeleteShader( frag ); 182 | return true; 183 | } 184 | 185 | GLuint create_programme_from_files( const char* vert_file_name, const char* frag_file_name ) { 186 | GLuint vert, frag, programme; 187 | ( create_shader( vert_file_name, &vert, GL_VERTEX_SHADER ) ); 188 | ( create_shader( frag_file_name, &frag, GL_FRAGMENT_SHADER ) ); 189 | ( create_programme( vert, frag, &programme ) ); 190 | return programme; 191 | } 192 | -------------------------------------------------------------------------------- /hello_colorful_triangle.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Hello colorful triangle 3 | * 4 | * An OpenGL "Hello Triangle" using 5 | * - glad instead of glew (because reason), and glfw3, 6 | - pieces from learnopengl.com 7 | * - the gl_utils lib of Anton Gerdelan tutos 8 | * - DSA, looking at fendevel/Guide-to-Modern-OpenGL-Functions @github 9 | * - heavy comments! This is the way. 10 | * 11 | * @author ludo456 / the opensourcedev @github 12 | */ 13 | 14 | #include "include/gl_utils.h" //includes glad.h & glfw3.h 15 | #include 16 | 17 | // Forward declarations 18 | void framebuffer_size_callback(GLFWwindow* window, int width, int height); 19 | void processInput(GLFWwindow *window); 20 | 21 | 22 | int main() 23 | { 24 | // glfw: initialize and configure 25 | // ------------------------------ 26 | glfwInit(); 27 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 28 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); 29 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 30 | 31 | // glfw window creation 32 | // -------------------- 33 | GLFWwindow* window = glfwCreateWindow(800, 600, "Hello Colorful Triangle", NULL, NULL); 34 | if (window == NULL) 35 | { 36 | std::cout << "Failed to create GLFW window" << std::endl; 37 | glfwTerminate(); 38 | return -1; 39 | } 40 | glfwMakeContextCurrent(window); 41 | glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 42 | 43 | // glad: load all OpenGL function pointers 44 | // --------------------------------------- 45 | if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) 46 | { 47 | std::cout << "Failed to initialize GLAD" << std::endl; 48 | return -1; 49 | } 50 | if ( !GLAD_GL_ARB_direct_state_access ) 51 | { 52 | /* see 53 | * https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_direct_state_access.txt 54 | * https://www.khronos.org/opengl/wiki/Direct_State_Access. This is the way. 55 | */ 56 | std::cout << "DSA not supported!" << std::endl; 57 | return -1; 58 | } 59 | 60 | // Setting up the triangle data 61 | // ---------------------------- 62 | 63 | float vertices[] = { 64 | -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 65 | 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 66 | 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f 67 | }; 68 | GLuint attribPos = 0; 69 | GLuint attribCol = 1; 70 | 71 | /**************** VBO ***************/ 72 | unsigned int hctVBO; // hello colorful triangle vbo 73 | //glGenBuffers(1, &VBO); // Way to go before openGl 4.5 74 | //glBindBuffer(GL_ARRAY_BUFFER, VBO); // Binding to openGl context was necessary 75 | // replaced with: 76 | glCreateBuffers(1, &hctVBO);//uses DSA. This is the way. 77 | 78 | //glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 79 | // replaced with: 80 | glNamedBufferStorage(hctVBO, sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT); 81 | // ^^^ needed, since there is no context binding. 82 | 83 | /**************** VAO ***************/ 84 | unsigned int hctVAO; 85 | //glGenVertexArrays(1, &VAO); 86 | //glBindVertexArray(VAO); 87 | // replaced with: 88 | glCreateVertexArrays(1, &hctVAO);// This is the way. 89 | 90 | // As there is, by definition, no context binding in DSA, then we need to 91 | //"bind" vao with vbo explicitely, like linking 2 indexes in a database. 92 | 93 | GLuint vaoBindingPoint = 0;//A binding point in VAO. See GL_MAX_VERTEX_ATTRIB_BINDINGS 94 | glVertexArrayVertexBuffer( 95 | hctVAO, // vao to bind 96 | vaoBindingPoint, // Could be 1, 2... if there were several vbo to source. 97 | hctVBO, // VBO to bound at "vaoBindingPoint". 98 | 0, // offset of the first element in the buffer hctVBO. 99 | 6*sizeof(float)); // stride == 3 position floats + 3 color floats. 100 | 101 | //glEnableVertexAttribArray(attribPos); 102 | //glEnableVertexAttribArray(attribCol); 103 | // replaced with: 104 | glEnableVertexArrayAttrib(hctVAO, attribPos);// Need to precise vao, as there is no context binding in DSA style 105 | glEnableVertexArrayAttrib(hctVAO, attribCol);// Meaning no current vao is bound to the opengl context. 106 | 107 | //glVertexAttribPointer(attribPos, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); 108 | //glVertexAttribPointer(attribCol, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)( 3*sizeof(float) )); 109 | // replaced with: 110 | glVertexArrayAttribFormat(hctVAO, attribPos, 3, GL_FLOAT, false, 0);// Need to precise vao, as there is no context binding in DSA 111 | glVertexArrayAttribFormat(hctVAO, attribCol, 3, GL_FLOAT, false, 3*sizeof(float));//https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribFormat.xhtml 112 | 113 | //Explicit binding of an attribute to a vao binding point 114 | glVertexArrayAttribBinding(hctVAO, attribPos, vaoBindingPoint); 115 | glVertexArrayAttribBinding(hctVAO, attribCol, vaoBindingPoint); 116 | 117 | 118 | //Create shader using gl_utils 119 | // --------------------------- 120 | GLuint shader_prog = 121 | create_programme_from_files( "shader_triangle.vert", "shader_triangle.frag" ); 122 | glUseProgram(shader_prog); // Could be copy-pasted in render loop too... 123 | 124 | 125 | //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//Wireframe rendering 126 | // render loop 127 | // ----------- 128 | while (!glfwWindowShouldClose(window)) 129 | { 130 | // input 131 | // ----- 132 | processInput(window); 133 | 134 | // render 135 | // ------ 136 | glClearColor(1.0f, 0.3f, 0.3f, 1.0f); 137 | glClear(GL_COLOR_BUFFER_BIT); 138 | 139 | glBindVertexArray(hctVAO); 140 | glDrawArrays(GL_TRIANGLES, 0, 3); 141 | 142 | // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) 143 | // ------------------------------------------------------------------------------- 144 | glfwSwapBuffers(window); 145 | glfwPollEvents(); 146 | } 147 | 148 | // glfw: terminate, clearing all previously allocated GLFW resources. 149 | // ------------------------------------------------------------------ 150 | glfwTerminate(); 151 | return 0; 152 | } 153 | 154 | // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly 155 | // --------------------------------------------------------------------------------------------------------- 156 | void processInput(GLFWwindow *window) 157 | { 158 | if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 159 | glfwSetWindowShouldClose(window, true); 160 | } 161 | 162 | // glfw: whenever the window size changed (by OS or user resize) this callback function executes 163 | // --------------------------------------------------------------------------------------------- 164 | void framebuffer_size_callback(GLFWwindow* window, int width, int height) 165 | { 166 | // make sure the viewport matches the new window dimensions; note that width and 167 | // height will be significantly larger than specified on retina displays. 168 | glViewport(0, 0, width, height); 169 | } 170 | -------------------------------------------------------------------------------- /include/KHR/khrplatform.h: -------------------------------------------------------------------------------- 1 | #ifndef __khrplatform_h_ 2 | #define __khrplatform_h_ 3 | 4 | /* 5 | ** Copyright (c) 2008-2018 The Khronos Group Inc. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining a 8 | ** copy of this software and/or associated documentation files (the 9 | ** "Materials"), to deal in the Materials without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Materials, and to 12 | ** permit persons to whom the Materials are furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included 16 | ** in all copies or substantial portions of the Materials. 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 | */ 26 | 27 | /* Khronos platform-specific types and definitions. 28 | * 29 | * The master copy of khrplatform.h is maintained in the Khronos EGL 30 | * Registry repository at https://github.com/KhronosGroup/EGL-Registry 31 | * The last semantic modification to khrplatform.h was at commit ID: 32 | * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 33 | * 34 | * Adopters may modify this file to suit their platform. Adopters are 35 | * encouraged to submit platform specific modifications to the Khronos 36 | * group so that they can be included in future versions of this file. 37 | * Please submit changes by filing pull requests or issues on 38 | * the EGL Registry repository linked above. 39 | * 40 | * 41 | * See the Implementer's Guidelines for information about where this file 42 | * should be located on your system and for more details of its use: 43 | * http://www.khronos.org/registry/implementers_guide.pdf 44 | * 45 | * This file should be included as 46 | * #include 47 | * by Khronos client API header files that use its types and defines. 48 | * 49 | * The types in khrplatform.h should only be used to define API-specific types. 50 | * 51 | * Types defined in khrplatform.h: 52 | * khronos_int8_t signed 8 bit 53 | * khronos_uint8_t unsigned 8 bit 54 | * khronos_int16_t signed 16 bit 55 | * khronos_uint16_t unsigned 16 bit 56 | * khronos_int32_t signed 32 bit 57 | * khronos_uint32_t unsigned 32 bit 58 | * khronos_int64_t signed 64 bit 59 | * khronos_uint64_t unsigned 64 bit 60 | * khronos_intptr_t signed same number of bits as a pointer 61 | * khronos_uintptr_t unsigned same number of bits as a pointer 62 | * khronos_ssize_t signed size 63 | * khronos_usize_t unsigned size 64 | * khronos_float_t signed 32 bit floating point 65 | * khronos_time_ns_t unsigned 64 bit time in nanoseconds 66 | * khronos_utime_nanoseconds_t unsigned time interval or absolute time in 67 | * nanoseconds 68 | * khronos_stime_nanoseconds_t signed time interval in nanoseconds 69 | * khronos_boolean_enum_t enumerated boolean type. This should 70 | * only be used as a base type when a client API's boolean type is 71 | * an enum. Client APIs which use an integer or other type for 72 | * booleans cannot use this as the base type for their boolean. 73 | * 74 | * Tokens defined in khrplatform.h: 75 | * 76 | * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. 77 | * 78 | * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. 79 | * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. 80 | * 81 | * Calling convention macros defined in this file: 82 | * KHRONOS_APICALL 83 | * KHRONOS_APIENTRY 84 | * KHRONOS_APIATTRIBUTES 85 | * 86 | * These may be used in function prototypes as: 87 | * 88 | * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( 89 | * int arg1, 90 | * int arg2) KHRONOS_APIATTRIBUTES; 91 | */ 92 | 93 | #if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) 94 | # define KHRONOS_STATIC 1 95 | #endif 96 | 97 | /*------------------------------------------------------------------------- 98 | * Definition of KHRONOS_APICALL 99 | *------------------------------------------------------------------------- 100 | * This precedes the return type of the function in the function prototype. 101 | */ 102 | #if defined(KHRONOS_STATIC) 103 | /* If the preprocessor constant KHRONOS_STATIC is defined, make the 104 | * header compatible with static linking. */ 105 | # define KHRONOS_APICALL 106 | #elif defined(_WIN32) 107 | # define KHRONOS_APICALL __declspec(dllimport) 108 | #elif defined (__SYMBIAN32__) 109 | # define KHRONOS_APICALL IMPORT_C 110 | #elif defined(__ANDROID__) 111 | # define KHRONOS_APICALL __attribute__((visibility("default"))) 112 | #else 113 | # define KHRONOS_APICALL 114 | #endif 115 | 116 | /*------------------------------------------------------------------------- 117 | * Definition of KHRONOS_APIENTRY 118 | *------------------------------------------------------------------------- 119 | * This follows the return type of the function and precedes the function 120 | * name in the function prototype. 121 | */ 122 | #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) 123 | /* Win32 but not WinCE */ 124 | # define KHRONOS_APIENTRY __stdcall 125 | #else 126 | # define KHRONOS_APIENTRY 127 | #endif 128 | 129 | /*------------------------------------------------------------------------- 130 | * Definition of KHRONOS_APIATTRIBUTES 131 | *------------------------------------------------------------------------- 132 | * This follows the closing parenthesis of the function prototype arguments. 133 | */ 134 | #if defined (__ARMCC_2__) 135 | #define KHRONOS_APIATTRIBUTES __softfp 136 | #else 137 | #define KHRONOS_APIATTRIBUTES 138 | #endif 139 | 140 | /*------------------------------------------------------------------------- 141 | * basic type definitions 142 | *-----------------------------------------------------------------------*/ 143 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) 144 | 145 | 146 | /* 147 | * Using 148 | */ 149 | #include 150 | typedef int32_t khronos_int32_t; 151 | typedef uint32_t khronos_uint32_t; 152 | typedef int64_t khronos_int64_t; 153 | typedef uint64_t khronos_uint64_t; 154 | #define KHRONOS_SUPPORT_INT64 1 155 | #define KHRONOS_SUPPORT_FLOAT 1 156 | 157 | #elif defined(__VMS ) || defined(__sgi) 158 | 159 | /* 160 | * Using 161 | */ 162 | #include 163 | typedef int32_t khronos_int32_t; 164 | typedef uint32_t khronos_uint32_t; 165 | typedef int64_t khronos_int64_t; 166 | typedef uint64_t khronos_uint64_t; 167 | #define KHRONOS_SUPPORT_INT64 1 168 | #define KHRONOS_SUPPORT_FLOAT 1 169 | 170 | #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) 171 | 172 | /* 173 | * Win32 174 | */ 175 | typedef __int32 khronos_int32_t; 176 | typedef unsigned __int32 khronos_uint32_t; 177 | typedef __int64 khronos_int64_t; 178 | typedef unsigned __int64 khronos_uint64_t; 179 | #define KHRONOS_SUPPORT_INT64 1 180 | #define KHRONOS_SUPPORT_FLOAT 1 181 | 182 | #elif defined(__sun__) || defined(__digital__) 183 | 184 | /* 185 | * Sun or Digital 186 | */ 187 | typedef int khronos_int32_t; 188 | typedef unsigned int khronos_uint32_t; 189 | #if defined(__arch64__) || defined(_LP64) 190 | typedef long int khronos_int64_t; 191 | typedef unsigned long int khronos_uint64_t; 192 | #else 193 | typedef long long int khronos_int64_t; 194 | typedef unsigned long long int khronos_uint64_t; 195 | #endif /* __arch64__ */ 196 | #define KHRONOS_SUPPORT_INT64 1 197 | #define KHRONOS_SUPPORT_FLOAT 1 198 | 199 | #elif 0 200 | 201 | /* 202 | * Hypothetical platform with no float or int64 support 203 | */ 204 | typedef int khronos_int32_t; 205 | typedef unsigned int khronos_uint32_t; 206 | #define KHRONOS_SUPPORT_INT64 0 207 | #define KHRONOS_SUPPORT_FLOAT 0 208 | 209 | #else 210 | 211 | /* 212 | * Generic fallback 213 | */ 214 | #include 215 | typedef int32_t khronos_int32_t; 216 | typedef uint32_t khronos_uint32_t; 217 | typedef int64_t khronos_int64_t; 218 | typedef uint64_t khronos_uint64_t; 219 | #define KHRONOS_SUPPORT_INT64 1 220 | #define KHRONOS_SUPPORT_FLOAT 1 221 | 222 | #endif 223 | 224 | 225 | /* 226 | * Types that are (so far) the same on all platforms 227 | */ 228 | typedef signed char khronos_int8_t; 229 | typedef unsigned char khronos_uint8_t; 230 | typedef signed short int khronos_int16_t; 231 | typedef unsigned short int khronos_uint16_t; 232 | 233 | /* 234 | * Types that differ between LLP64 and LP64 architectures - in LLP64, 235 | * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears 236 | * to be the only LLP64 architecture in current use. 237 | */ 238 | #ifdef _WIN64 239 | typedef signed long long int khronos_intptr_t; 240 | typedef unsigned long long int khronos_uintptr_t; 241 | typedef signed long long int khronos_ssize_t; 242 | typedef unsigned long long int khronos_usize_t; 243 | #else 244 | typedef signed long int khronos_intptr_t; 245 | typedef unsigned long int khronos_uintptr_t; 246 | typedef signed long int khronos_ssize_t; 247 | typedef unsigned long int khronos_usize_t; 248 | #endif 249 | 250 | #if KHRONOS_SUPPORT_FLOAT 251 | /* 252 | * Float type 253 | */ 254 | typedef float khronos_float_t; 255 | #endif 256 | 257 | #if KHRONOS_SUPPORT_INT64 258 | /* Time types 259 | * 260 | * These types can be used to represent a time interval in nanoseconds or 261 | * an absolute Unadjusted System Time. Unadjusted System Time is the number 262 | * of nanoseconds since some arbitrary system event (e.g. since the last 263 | * time the system booted). The Unadjusted System Time is an unsigned 264 | * 64 bit value that wraps back to 0 every 584 years. Time intervals 265 | * may be either signed or unsigned. 266 | */ 267 | typedef khronos_uint64_t khronos_utime_nanoseconds_t; 268 | typedef khronos_int64_t khronos_stime_nanoseconds_t; 269 | #endif 270 | 271 | /* 272 | * Dummy value used to pad enum types to 32 bits. 273 | */ 274 | #ifndef KHRONOS_MAX_ENUM 275 | #define KHRONOS_MAX_ENUM 0x7FFFFFFF 276 | #endif 277 | 278 | /* 279 | * Enumerated boolean type 280 | * 281 | * Values other than zero should be considered to be true. Therefore 282 | * comparisons should not be made against KHRONOS_TRUE. 283 | */ 284 | typedef enum { 285 | KHRONOS_FALSE = 0, 286 | KHRONOS_TRUE = 1, 287 | KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM 288 | } khronos_boolean_enum_t; 289 | 290 | #endif /* __khrplatform_h_ */ 291 | -------------------------------------------------------------------------------- /include/gl_utils.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | | OpenGL 4 Example Code. | 3 | | Accompanies written series "Anton's OpenGL 4 Tutorials" | 4 | | Email: anton at antongerdelan dot net | 5 | | First version 27 Jan 2014 | 6 | | Dr Anton Gerdelan, Trinity College Dublin, Ireland. | 7 | | See individual libraries for separate legal notices | 8 | \******************************************************************************/ 9 | #ifndef _GL_UTILS_H_ 10 | #define _GL_UTILS_H_ 11 | 12 | #include // include GLEW and new version of GL on Windows 13 | #include // GLFW helper library 14 | #include 15 | 16 | #define GL_LOG_FILE "gl.log" 17 | 18 | extern GLFWwindow* g_window; 19 | 20 | bool restart_gl_log(); 21 | 22 | bool gl_log( const char* message, ... ); 23 | 24 | /* same as gl_log except also prints to stderr */ 25 | bool gl_log_err( const char* message, ... ); 26 | 27 | void glfw_error_callback( int error, const char* description ); 28 | 29 | void log_gl_params(); 30 | 31 | void _update_fps_counter( GLFWwindow* window ); 32 | 33 | const char* GL_type_to_string( unsigned int type ); 34 | 35 | void print_shader_info_log( GLuint shader_index ); 36 | 37 | void print_programme_info_log( GLuint sp ); 38 | 39 | void print_all( GLuint sp ); 40 | 41 | bool is_valid( GLuint sp ); 42 | 43 | bool parse_file_into_str( const char* file_name, char* shader_str, int max_len ); 44 | 45 | GLuint create_programme_from_files( const char* vert_file_name, const char* frag_file_name ); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /shader_triangle.frag: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | in vec4 vertexColor; 4 | out vec4 FragColor; 5 | 6 | void main() 7 | { 8 | FragColor = vertexColor; 9 | } 10 | -------------------------------------------------------------------------------- /shader_triangle.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location = 0) in vec3 aPos; 4 | layout(location = 1) in vec3 aColor; 5 | 6 | out vec4 vertexColor; 7 | 8 | void main () 9 | { 10 | gl_Position = vec4(aPos, 1.0); 11 | vertexColor = vec4(aColor, 1.0); 12 | } 13 | --------------------------------------------------------------------------------