Draw first triangle
This commit is contained in:
		
							
								
								
									
										134
									
								
								src/main.cc
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								src/main.cc
									
									
									
									
									
								
							| @@ -6,6 +6,8 @@ | |||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  | #include <string> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
| #define WINDOW_WIDTH 1280 | #define WINDOW_WIDTH 1280 | ||||||
| #define WINDOW_HEIGHT 720 | #define WINDOW_HEIGHT 720 | ||||||
| @@ -22,11 +24,29 @@ struct App { | |||||||
|   SDL_Window    *window; |   SDL_Window    *window; | ||||||
|   SDL_GLContext context; |   SDL_GLContext context; | ||||||
|   SDL_Event     event; |   SDL_Event     event; | ||||||
|  |  | ||||||
|  |   // Defines the different attributes in the vertex data and how to access them. | ||||||
|  |   // Think of it as a specification or a C struct that defines the types of data stored for each | ||||||
|  |   // vertex. | ||||||
|  |   GLuint        vao; | ||||||
|  |  | ||||||
|  |   // The buffer that contains all the vertex data | ||||||
|  |   // e.g. assume 3 vertices with position, colour and uv | ||||||
|  |   //  ----------------------------------------------------------------------------------- | ||||||
|  |   // | position1 | colour1 | uv1 | position2 | colour2 | uv2 | position3 | colour3 | uv3 | | ||||||
|  |   //  ----------------------------------------------------------------------------------- | ||||||
|  |   GLuint        vbo; | ||||||
|  |  | ||||||
|  |   GLuint        shader_program; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| int  init         (App &app); | int    init                    (App &app); | ||||||
| void run_main_loop(App &app); | void   create_vertex_spec      (App &app); | ||||||
| void cleanup      (App &app); | void   create_graphics_pipeline(App &app); | ||||||
|  | void   run_main_loop           (App &app); | ||||||
|  | void   cleanup                 (App &app); | ||||||
|  | GLuint create_shader_program   (const std::string &vertex_shader_source, const std::string &fragment_shader_source); | ||||||
|  | GLuint compile_shader          (GLuint type, const std::string &source); | ||||||
|  |  | ||||||
| int main() { | int main() { | ||||||
|   App app    = {}; |   App app    = {}; | ||||||
| @@ -35,6 +55,10 @@ int main() { | |||||||
|     return result; |     return result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   create_vertex_spec(app); | ||||||
|  |  | ||||||
|  |   create_graphics_pipeline(app); | ||||||
|  |  | ||||||
|   run_main_loop(app); |   run_main_loop(app); | ||||||
|  |  | ||||||
|   cleanup(app); |   cleanup(app); | ||||||
| @@ -49,7 +73,7 @@ int init(App &app) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   uint32_t flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; |   uint32_t flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; | ||||||
|   app.window        = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, |   app.window     = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, | ||||||
|                                     WINDOW_WIDTH, WINDOW_HEIGHT, flags); |                                     WINDOW_WIDTH, WINDOW_HEIGHT, flags); | ||||||
|   if (!app.window) { |   if (!app.window) { | ||||||
|     fprintf(stderr, "Failed to create window: %s", SDL_GetError()); |     fprintf(stderr, "Failed to create window: %s", SDL_GetError()); | ||||||
| @@ -84,6 +108,57 @@ int init(App &app) { | |||||||
|   return EXIT_CODE_SUCCESS; |   return EXIT_CODE_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void create_vertex_spec(App &app) { | ||||||
|  |   const std::vector<GLfloat> vertices = { | ||||||
|  |     -0.8f, -0.8f, 0.0f, | ||||||
|  |      0.8f, -0.8f, 0.0f, | ||||||
|  |      0.0f,  0.8f, 0.0f, | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   glGenVertexArrays(1, &app.vao); | ||||||
|  |   glBindVertexArray(app.vao); | ||||||
|  |  | ||||||
|  |   glGenBuffers(1, &app.vbo); | ||||||
|  |   glBindBuffer(GL_ARRAY_BUFFER, app.vbo); | ||||||
|  |   glBufferData(GL_ARRAY_BUFFER, | ||||||
|  |                vertices.size() * sizeof(GLfloat), | ||||||
|  |                (void *)vertices.data(), | ||||||
|  |                GL_STATIC_DRAW | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   // Defines the vertex attributes and their indices. This defines the attribute for the currently | ||||||
|  |   // bound VAO | ||||||
|  |   glEnableVertexAttribArray(0); | ||||||
|  |  | ||||||
|  |   // Defines the number of components for the attribute, its type, the stride between the component | ||||||
|  |   // for each vertex and the offset of the first instance of the component in the buffer | ||||||
|  |   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); | ||||||
|  |  | ||||||
|  |   // Cleanup. The order matters. Unbind VAO first then disable the attributes. If you do it the | ||||||
|  |   // other way around, the VAO will store that the attributes are disabled and nothing will be | ||||||
|  |   // drawn during the rendering stage | ||||||
|  |   glBindVertexArray(0); | ||||||
|  |   glBindBuffer(GL_ARRAY_BUFFER, 0); | ||||||
|  |   glDisableVertexAttribArray(0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void create_graphics_pipeline(App &app) { | ||||||
|  |   const std::string vs_source = | ||||||
|  |     "#version 460 core\n" | ||||||
|  |     "in vec4 position;\n" | ||||||
|  |     "void main() {\n" | ||||||
|  |     "  gl_Position = vec4(position.x, position.y, position.z, position.w);\n" | ||||||
|  |     "}"; | ||||||
|  |   const std::string fs_source = | ||||||
|  |     "#version 460 core\n" | ||||||
|  |     "out vec4 color;\n" | ||||||
|  |     "void main() {\n" | ||||||
|  |     "  color = vec4(0.93f, 0.42f, 0.35f, 1.0f);\n" | ||||||
|  |     "}"; | ||||||
|  |  | ||||||
|  |   app.shader_program = create_shader_program(vs_source, fs_source); | ||||||
|  | } | ||||||
|  |  | ||||||
| void run_main_loop(App &app) { | void run_main_loop(App &app) { | ||||||
|   bool running = true; |   bool running = true; | ||||||
|  |  | ||||||
| @@ -96,6 +171,23 @@ void run_main_loop(App &app) { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Pre draw setup | ||||||
|  |     glDisable(GL_DEPTH_TEST); | ||||||
|  |     glDisable(GL_CULL_FACE); | ||||||
|  |  | ||||||
|  |     glViewport  (0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); | ||||||
|  |     glClearColor(0.36f, 0.34f, 0.42f, 1.0f); | ||||||
|  |     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); | ||||||
|  |  | ||||||
|  |     glUseProgram(app.shader_program); | ||||||
|  |     // End pre draw setup | ||||||
|  |  | ||||||
|  |     // Draw call | ||||||
|  |     glBindVertexArray(app.vao); | ||||||
|  |     glBindBuffer(GL_ARRAY_BUFFER, app.vbo); // Is this actually needed? | ||||||
|  |     glDrawArrays(GL_TRIANGLES, 0, 3); | ||||||
|  |     // End draw call | ||||||
|  |  | ||||||
|     SDL_GL_SwapWindow(app.window); |     SDL_GL_SwapWindow(app.window); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -105,3 +197,37 @@ void cleanup(App &app) { | |||||||
|   SDL_DestroyWindow(app.window); |   SDL_DestroyWindow(app.window); | ||||||
|   SDL_Quit(); |   SDL_Quit(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GLuint create_shader_program(const std::string &vertex_shader_source, const std::string &fragment_shader_source) { | ||||||
|  |   GLuint shader_program  = glCreateProgram(); | ||||||
|  |   GLuint vertex_shader   = compile_shader(GL_VERTEX_SHADER, vertex_shader_source); | ||||||
|  |   GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_source); | ||||||
|  |  | ||||||
|  |   glAttachShader(shader_program, vertex_shader); | ||||||
|  |   glAttachShader(shader_program, fragment_shader); | ||||||
|  |   glLinkProgram (shader_program); | ||||||
|  |  | ||||||
|  |   // Validate the shader_program | ||||||
|  |   glValidateProgram(shader_program); | ||||||
|  |  | ||||||
|  |   return shader_program; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GLuint compile_shader(GLuint type, const std::string &source) { | ||||||
|  |   GLuint shader             = glCreateShader(type); | ||||||
|  |   const char *shader_source = source.c_str(); | ||||||
|  |  | ||||||
|  |   glShaderSource (shader, 1, &shader_source, NULL); | ||||||
|  |   glCompileShader(shader); | ||||||
|  |  | ||||||
|  |   GLint compile_status; | ||||||
|  |   glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | ||||||
|  |   if (compile_status != GL_TRUE) { | ||||||
|  |     GLsizei log_length = 0; | ||||||
|  |     GLchar message[1024]; | ||||||
|  |     glGetShaderInfoLog(shader, 1024, &log_length, message); | ||||||
|  |     fprintf(stderr, "%s\n", message); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return shader; | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user