Draw first triangle
This commit is contained in:
		
							
								
								
									
										126
									
								
								src/main.cc
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								src/main.cc
									
									
									
									
									
								
							| @@ -6,6 +6,8 @@ | ||||
| #include <cstdint> | ||||
| #include <cstdio> | ||||
| #include <stdbool.h> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| #define WINDOW_WIDTH 1280 | ||||
| #define WINDOW_HEIGHT 720 | ||||
| @@ -22,11 +24,29 @@ struct App { | ||||
|   SDL_Window    *window; | ||||
|   SDL_GLContext context; | ||||
|   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); | ||||
| void   create_vertex_spec      (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() { | ||||
|   App app    = {}; | ||||
| @@ -35,6 +55,10 @@ int main() { | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   create_vertex_spec(app); | ||||
|  | ||||
|   create_graphics_pipeline(app); | ||||
|  | ||||
|   run_main_loop(app); | ||||
|  | ||||
|   cleanup(app); | ||||
| @@ -84,6 +108,57 @@ int init(App &app) { | ||||
|   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) { | ||||
|   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); | ||||
|   } | ||||
| } | ||||
| @@ -105,3 +197,37 @@ void cleanup(App &app) { | ||||
|   SDL_DestroyWindow(app.window); | ||||
|   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