-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.cpp
162 lines (139 loc) · 5.73 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "../common/util.h"
#include "../common/shader.h"
const char* VERTEX_SRC = "#version 330 core\n"
"layout(location=0) in vec2 position;" // Vertex position (x, y)
"layout(location=1) in vec3 color;" // Vertex color (r, g, b)
"layout(location=2) in vec2 texcoord;" // Texture coordinate (u, v)
"out vec3 fColor;" // Vertex shader has to pass color to fragment shader
"out vec2 fTexcoord;" // Pass to fragment shader
"void main()"
"{"
" fColor = color;" // Pass color to fragment shader
" fTexcoord = texcoord;" // Pass texcoord to fragment shader
" gl_Position=vec4(position, 0.0, 1.0);" // Place vertex at (x, y, 0, 1)
"}";
const char* FRAGMENT_SRC = "#version 330 core\n"
"in vec3 fColor;" // From the vertex shader
"in vec2 fTexcoord;" // From the vertex shader
"uniform sampler2D tex;" // The texture
"out vec4 outputColor;" // The color of the resulting fragment
"void main()"
"{"
" outputColor = texture(tex, fTexcoord)" // Color using the color and texutre
" * vec4(fColor, 1.0);"
"}";
int main(void)
{
GLFWwindow* window;
// The OpenGL context creation code is in
// ../common/util.cpp
window = init("Hello Sprite", 640, 480);
if(!window)
{
return -1;
}
// We start by creating a vertex and fragment shader
// from the above strings
GLuint vertex = createShader(VERTEX_SRC, GL_VERTEX_SHADER);
if(!vertex)
{
return -1;
}
GLuint fragment = createShader(FRAGMENT_SRC, GL_FRAGMENT_SHADER);
if(!fragment)
{
return -1;
}
// Now we must make a shader program: this program
// contains both the vertex and the fragment shader
GLuint program = createShaderProgram(vertex, fragment);
if(!program)
{
return -1;
}
// We link the program, just like your C compiler links
// .o files
bool result = linkShader(program);
if(!result)
{
return -1;
}
// We make sure the shader is validated
result = validateShader(program);
if(!result)
{
return -1;
}
// Detach and delete the shaders, because we no longer need them
glDetachShader(program, vertex);
glDeleteShader(vertex);
glDetachShader(program, fragment);
glDeleteShader(fragment);
glUseProgram(program); // Set this as the current shader program
// We now create the data to send to the GPU
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
float vertices[] =
{
// x y r g b u v
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
// Upload the vertices to the buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint indices[] =
{
0, 1, 2,
2, 3, 0
};
// Upload the indices (elements) to the buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Enable the vertex attributes and upload their data (see: layout(location=x))
glEnableVertexAttribArray(0); // position
// 2 floats: x and y, but 7 floats in total per row
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(1); // color
// 3 floats: r, g and b, but 7 floats in total per row and start at the third one
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); // texture coordinates
// 2 floats: u and v, but 7 floats in total per row and start at the sixth one
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(5 * sizeof(GLfloat)));
// We have now successfully created a drawable Vertex Array Object
// Load the texture and bind it to the uniform
int w, h;
GLuint texture = loadImage("image.png", &w, &h, 0, false); // GL_TEXTURE0
if(!texture)
{
return -1;
}
glUniform1i(glGetUniformLocation(program, "tex"), 0); // GL_TEXTURE0
// Set the clear color to a light grey
glClearColor(0.75f, 0.75f, 0.75f, 1.0f);
while(!glfwWindowShouldClose(window))
{
// Clear
glClear(GL_COLOR_BUFFER_BIT);
// The VAO is still bound so just draw the 6 vertices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Tip: if nothing is drawn, check the return value of glGetError and google it
// Swap buffers to show current image on screen (for more information google 'backbuffer')
glfwSwapBuffers(window);
glfwPollEvents();
}
// Clean up
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteVertexArrays(1, &vao);
glDeleteTextures(1, &texture);
glfwTerminate();
return 0;
}