-
-
Save koute/7391344 to your computer and use it in GitHub Desktop.
/* | |
Minimal SDL2 + OpenGL3 example. | |
Author: https://github.com/koute | |
This file is in the public domain; you can do whatever you want with it. | |
In case the concept of public domain doesn't exist in your jurisdiction | |
you can also use this code under the terms of Creative Commons CC0 license, | |
either version 1.0 or (at your option) any later version; for details see: | |
http://creativecommons.org/publicdomain/zero/1.0/ | |
This software is distributed without any warranty whatsoever. | |
Compile and run with: gcc opengl3_hello.c `sdl2-config --libs --cflags` -lGL -Wall && ./a.out | |
*/ | |
#define GL_GLEXT_PROTOTYPES | |
#include <SDL.h> | |
#include <SDL_opengl.h> | |
#include <stdio.h> | |
typedef float t_mat4x4[16]; | |
static inline void mat4x4_ortho( t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar ) | |
{ | |
#define T(a, b) (a * 4 + b) | |
out[T(0,0)] = 2.0f / (right - left); | |
out[T(0,1)] = 0.0f; | |
out[T(0,2)] = 0.0f; | |
out[T(0,3)] = 0.0f; | |
out[T(1,1)] = 2.0f / (top - bottom); | |
out[T(1,0)] = 0.0f; | |
out[T(1,2)] = 0.0f; | |
out[T(1,3)] = 0.0f; | |
out[T(2,2)] = -2.0f / (zfar - znear); | |
out[T(2,0)] = 0.0f; | |
out[T(2,1)] = 0.0f; | |
out[T(2,3)] = 0.0f; | |
out[T(3,0)] = -(right + left) / (right - left); | |
out[T(3,1)] = -(top + bottom) / (top - bottom); | |
out[T(3,2)] = -(zfar + znear) / (zfar - znear); | |
out[T(3,3)] = 1.0f; | |
#undef T | |
} | |
static const char * vertex_shader = | |
"#version 130\n" | |
"in vec2 i_position;\n" | |
"in vec4 i_color;\n" | |
"out vec4 v_color;\n" | |
"uniform mat4 u_projection_matrix;\n" | |
"void main() {\n" | |
" v_color = i_color;\n" | |
" gl_Position = u_projection_matrix * vec4( i_position, 0.0, 1.0 );\n" | |
"}\n"; | |
static const char * fragment_shader = | |
"#version 130\n" | |
"in vec4 v_color;\n" | |
"out vec4 o_color;\n" | |
"void main() {\n" | |
" o_color = v_color;\n" | |
"}\n"; | |
typedef enum t_attrib_id | |
{ | |
attrib_position, | |
attrib_color | |
} t_attrib_id; | |
int main( int argc, char * argv[] ) | |
{ | |
SDL_Init( SDL_INIT_VIDEO ); | |
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); | |
SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); | |
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); | |
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); | |
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 ); | |
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 ); | |
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 ); | |
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 ); | |
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); | |
static const int width = 800; | |
static const int height = 600; | |
SDL_Window * window = SDL_CreateWindow( "", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN ); | |
SDL_GLContext context = SDL_GL_CreateContext( window ); | |
GLuint vs, fs, program; | |
vs = glCreateShader( GL_VERTEX_SHADER ); | |
fs = glCreateShader( GL_FRAGMENT_SHADER ); | |
int length = strlen( vertex_shader ); | |
glShaderSource( vs, 1, ( const GLchar ** )&vertex_shader, &length ); | |
glCompileShader( vs ); | |
GLint status; | |
glGetShaderiv( vs, GL_COMPILE_STATUS, &status ); | |
if( status == GL_FALSE ) | |
{ | |
fprintf( stderr, "vertex shader compilation failed\n" ); | |
return 1; | |
} | |
length = strlen( fragment_shader ); | |
glShaderSource( fs, 1, ( const GLchar ** )&fragment_shader, &length ); | |
glCompileShader( fs ); | |
glGetShaderiv( fs, GL_COMPILE_STATUS, &status ); | |
if( status == GL_FALSE ) | |
{ | |
fprintf( stderr, "fragment shader compilation failed\n" ); | |
return 1; | |
} | |
program = glCreateProgram(); | |
glAttachShader( program, vs ); | |
glAttachShader( program, fs ); | |
glBindAttribLocation( program, attrib_position, "i_position" ); | |
glBindAttribLocation( program, attrib_color, "i_color" ); | |
glLinkProgram( program ); | |
glUseProgram( program ); | |
glDisable( GL_DEPTH_TEST ); | |
glClearColor( 0.5, 0.0, 0.0, 0.0 ); | |
glViewport( 0, 0, width, height ); | |
GLuint vao, vbo; | |
glGenVertexArrays( 1, &vao ); | |
glGenBuffers( 1, &vbo ); | |
glBindVertexArray( vao ); | |
glBindBuffer( GL_ARRAY_BUFFER, vbo ); | |
glEnableVertexAttribArray( attrib_position ); | |
glEnableVertexAttribArray( attrib_color ); | |
glVertexAttribPointer( attrib_color, 4, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, 0 ); | |
glVertexAttribPointer( attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, ( void * )(4 * sizeof(float)) ); | |
const GLfloat g_vertex_buffer_data[] = { | |
/* R, G, B, A, X, Y */ | |
1, 0, 0, 1, 0, 0, | |
0, 1, 0, 1, width, 0, | |
0, 0, 1, 1, width, height, | |
1, 0, 0, 1, 0, 0, | |
0, 0, 1, 1, width, height, | |
1, 1, 1, 1, 0, height | |
}; | |
glBufferData( GL_ARRAY_BUFFER, sizeof( g_vertex_buffer_data ), g_vertex_buffer_data, GL_STATIC_DRAW ); | |
t_mat4x4 projection_matrix; | |
mat4x4_ortho( projection_matrix, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 100.0f ); | |
glUniformMatrix4fv( glGetUniformLocation( program, "u_projection_matrix" ), 1, GL_FALSE, projection_matrix ); | |
for( ;; ) | |
{ | |
glClear( GL_COLOR_BUFFER_BIT ); | |
SDL_Event event; | |
while( SDL_PollEvent( &event ) ) | |
{ | |
switch( event.type ) | |
{ | |
case SDL_KEYUP: | |
if( event.key.keysym.sym == SDLK_ESCAPE ) | |
return 0; | |
break; | |
} | |
} | |
glBindVertexArray( vao ); | |
glDrawArrays( GL_TRIANGLES, 0, 6 ); | |
SDL_GL_SwapWindow( window ); | |
SDL_Delay( 1 ); | |
} | |
SDL_GL_DeleteContext( context ); | |
SDL_DestroyWindow( window ); | |
SDL_Quit(); | |
return 0; | |
} | |
Hahahaha, random dude throw some code on GitHub, then it DOES EXACTLY WHAT I WANT!!!!!!
CMake complie:
cmake_minimum_required(VERSION 3.19)
project(openGL)
set(CMAKE_CXX_STANDARD 20)
find_package(SDL2 REQUIRED)
find_package(OpenGL REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
include_directories(${OPENGL_INCLUDE_DIR})
add_executable(prog main.cpp)
target_link_libraries(prog ${SDL2_LIBRARIES})
target_link_libraries(prog ${OPENGL_LIBRARIES})
Hi. I do not use cmake. I'm buiilding with visual studio and vcpkg library management, and Im getting unresolved externals. I've made sure that opengl32.lib, sdl2.lib are available. What lib do I need to make available? Thank you.
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glBindAttribLocation
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glShaderSource
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glBindBuffer
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glBindVertexArray
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glVertexAttribPointer
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glUniformMatrix4fv
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glCreateProgram
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glEnableVertexAttribArray
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glBufferData
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glGenBuffers
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glGenVertexArrays
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glCompileShader
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glLinkProgram
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glGetUniformLocation
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glCreateShader
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glAttachShader
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glUseProgram
1>testOpenGL.obj : error LNK2001: unresolved external symbol __imp_glGetShaderiv
And for others trying to run it in MacOS: change both ""#version 130\n" into "#version 330\n" or something similar and it will work (at least for me). Some sources suggest "#version 330 core\n"...
This code is beautiful and compiles for me fine. I have no idea how it works yet but you are a genius for making this and sharing it with us all! Thanks a billion!
Work with
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
-lSDL2 and -lGL in linker settings
Tested on Codeblocks under Debian (Linux)
Thanks for the only non-unhinged code example for this on the internet
For me to compile I need these headers:
#include <SDL.h>
#include <glew.h>
#include <SDL_opengl.h>
#include <string.h>
#include <stdio.h>
I don´t know what I am missing. But after adding these and compile the example only shows a red screen and no triangles are draw.
This was really helpful - I was following the LazyFoo tutorials and was having issues getting their OpenGL3 stuff to compile - this is much simpler and more to-the-point. Thanks very much - jb