1//========================================================================
2// OpenGL triangle example
3// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
4//
5// This software is provided 'as-is', without any express or implied
6// warranty. In no event will the authors be held liable for any damages
7// arising from the use of this software.
8//
9// Permission is granted to anyone to use this software for any purpose,
10// including commercial applications, and to alter it and redistribute it
11// freely, subject to the following restrictions:
12//
13// 1. The origin of this software must not be misrepresented; you must not
14//    claim that you wrote the original software. If you use this software
15//    in a product, an acknowledgment in the product documentation would
16//    be appreciated but is not required.
17//
18// 2. Altered source versions must be plainly marked as such, and must not
19//    be misrepresented as being the original software.
20//
21// 3. This notice may not be removed or altered from any source
22//    distribution.
23//
24//========================================================================
25//! [code]
26
27#define GLAD_GL_IMPLEMENTATION
28#include <glad/gl.h>
29#define GLFW_INCLUDE_NONE
30#include <GLFW/glfw3.h>
31
32#include "linmath.h"
33
34#include <stdlib.h>
35#include <stddef.h>
36#include <stdio.h>
37
38typedef struct Vertex
39{
40    vec2 pos;
41    vec3 col;
42} Vertex;
43
44static const Vertex vertices[3] =
45{
46    { { -0.6f, -0.4f }, { 1.f, 0.f, 0.f } },
47    { {  0.6f, -0.4f }, { 0.f, 1.f, 0.f } },
48    { {   0.f,  0.6f }, { 0.f, 0.f, 1.f } }
49};
50
51static const char* vertex_shader_text =
52"#version 330\n"
53"uniform mat4 MVP;\n"
54"in vec3 vCol;\n"
55"in vec2 vPos;\n"
56"out vec3 color;\n"
57"void main()\n"
58"{\n"
59"    gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
60"    color = vCol;\n"
61"}\n";
62
63static const char* fragment_shader_text =
64"#version 330\n"
65"in vec3 color;\n"
66"out vec4 fragment;\n"
67"void main()\n"
68"{\n"
69"    fragment = vec4(color, 1.0);\n"
70"}\n";
71
72static void error_callback(int error, const char* description)
73{
74    fprintf(stderr, "Error: %s\n", description);
75}
76
77static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
78{
79    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
80        glfwSetWindowShouldClose(window, GLFW_TRUE);
81}
82
83int main(void)
84{
85    glfwSetErrorCallback(error_callback);
86
87    if (!glfwInit())
88        exit(EXIT_FAILURE);
89
90    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
91    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
92    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
93
94    GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Triangle", NULL, NULL);
95    if (!window)
96    {
97        glfwTerminate();
98        exit(EXIT_FAILURE);
99    }
100
101    glfwSetKeyCallback(window, key_callback);
102
103    glfwMakeContextCurrent(window);
104    gladLoadGL(glfwGetProcAddress);
105    glfwSwapInterval(1);
106
107    // NOTE: OpenGL error checks have been omitted for brevity
108
109    GLuint vertex_buffer;
110    glGenBuffers(1, &vertex_buffer);
111    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
112    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
113
114    const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
115    glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
116    glCompileShader(vertex_shader);
117
118    const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
119    glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
120    glCompileShader(fragment_shader);
121
122    const GLuint program = glCreateProgram();
123    glAttachShader(program, vertex_shader);
124    glAttachShader(program, fragment_shader);
125    glLinkProgram(program);
126
127    const GLint mvp_location = glGetUniformLocation(program, "MVP");
128    const GLint vpos_location = glGetAttribLocation(program, "vPos");
129    const GLint vcol_location = glGetAttribLocation(program, "vCol");
130
131    GLuint vertex_array;
132    glGenVertexArrays(1, &vertex_array);
133    glBindVertexArray(vertex_array);
134    glEnableVertexAttribArray(vpos_location);
135    glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
136                          sizeof(Vertex), (void*) offsetof(Vertex, pos));
137    glEnableVertexAttribArray(vcol_location);
138    glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
139                          sizeof(Vertex), (void*) offsetof(Vertex, col));
140
141    while (!glfwWindowShouldClose(window))
142    {
143        int width, height;
144        glfwGetFramebufferSize(window, &width, &height);
145        const float ratio = width / (float) height;
146
147        glViewport(0, 0, width, height);
148        glClear(GL_COLOR_BUFFER_BIT);
149
150        mat4x4 m, p, mvp;
151        mat4x4_identity(m);
152        mat4x4_rotate_Z(m, m, (float) glfwGetTime());
153        mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
154        mat4x4_mul(mvp, p, m);
155
156        glUseProgram(program);
157        glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp);
158        glBindVertexArray(vertex_array);
159        glDrawArrays(GL_TRIANGLES, 0, 3);
160
161        glfwSwapBuffers(window);
162        glfwPollEvents();
163    }
164
165    glfwDestroyWindow(window);
166
167    glfwTerminate();
168    exit(EXIT_SUCCESS);
169}
170
171//! [code]
172