Add a togglable rectangle and toggable wireframe.

This commit is contained in:
Fries 2024-03-10 18:13:28 -07:00
parent 86b72db39e
commit 6d4b70aa1c
2 changed files with 138 additions and 33 deletions

View file

@ -0,0 +1,5 @@
{
"clangd.arguments": [
"-header-insertion=never"
]
}

View file

@ -4,6 +4,7 @@
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void process_input(GLFWwindow* window);
void key_pressed(GLFWwindow *window, int key, int scancode, int action, int mods);
int check_shader_compilation_status(unsigned int shaderId);
const char* vertexShaderCode = R"(
@ -26,6 +27,98 @@ void main() {
}
)";
bool wireframe;
bool rectangleToggled;
struct GlRenderObjects {
unsigned int vertexBufferObject;
unsigned int vertexArrayObject;
unsigned int elementBufferObject;
void Destroy() {
glDeleteBuffers(1, &vertexBufferObject);
glDeleteVertexArrays(1, &vertexArrayObject);
glDeleteBuffers(1, &elementBufferObject);
}
};
GlRenderObjects triangle() {
// An array of verticies containing data for a triangle.
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
unsigned int vertexBufferObject, vertexArrayObject;
// Create a Vertex Array Object.
glGenVertexArrays(1, &vertexArrayObject);
// Create a Vertex Buffer Object and write the id to the vertexBufferObject variable.
glGenBuffers(1, &vertexBufferObject);
// Bind the vertex array object so the attributes are stored in that object.
glBindVertexArray(vertexArrayObject);
// Bind the GL_ARRAY_BUFFER target to the verterBufferObject object id.
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
// Copy the verticies data into the vertexBufferObject object and tell the GPU it will only be written once but read many times.
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Tell OpenGL how to process the Vertex attributes so it can pass it to the Vertex shader.
// This will pass the vertex to the location "0". We tell OpenGL the size of the array is 3 elements.
// We tell OpenGL that we're using floating point types.
// We tell OpenGL we don't want our data to be normalized as its already normalized.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return {vertexBufferObject, vertexArrayObject, 0};
}
GlRenderObjects rectangle() {
float vertices[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
unsigned int vertexBufferObject, vertexArrayObject, elementBufferObject;
// Create a Vertex Array Object.
glGenVertexArrays(1, &vertexArrayObject);
// Create a Vertex Buffer Object.
glGenBuffers(1, &vertexBufferObject);
// Create a Element Buffer Object;
glGenBuffers(1, &elementBufferObject);
// Bind the Vertex Array Object to the state.
glBindVertexArray(vertexArrayObject);
// Bind the Vertex Buffer Object to the GL_ARRAY_BUFFER target on the state.
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
// Copy verticies into the GPU's memory.
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Bind the Element Buffer Object to the GL_ELEMENT_ARRAY_BUFFER target on the state.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
// Copy indicies into the GPU's memory.
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Tell OpenGL on how to process the verticies.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// Unbind the current buffers and arrays from the state.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return {vertexBufferObject, vertexArrayObject, elementBufferObject};
}
int main() {
glfwInit();
@ -103,40 +196,15 @@ int main() {
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// An array of verticies containing data for a triangle.
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
unsigned int vertexBufferObject, vertexArrayObject;
// Create a Vertex Array Object.
glGenVertexArrays(1, &vertexArrayObject);
// Create a Vertex Buffer Object and write the id to the vertexBufferObject variable.
glGenBuffers(1, &vertexBufferObject);
// Bind the vertex array object so the attributes are stored in that object.
glBindVertexArray(vertexArrayObject);
// Bind the GL_ARRAY_BUFFER target to the verterBufferObject object id.
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
// Copy the verticies data into the vertexBufferObject object and tell the GPU it will only be written once but read many times.
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Tell OpenGL how to process the Vertex attributes so it can pass it to the Vertex shader.
// This will pass the vertex to the location "0". We tell OpenGL the size of the array is 3 elements.
// We tell OpenGL that we're using floating point types.
// We tell OpenGL we don't want our data to be normalized as its already normalized.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
GlRenderObjects triangleRenderObjs = triangle();
GlRenderObjects rectangleRenderObjs = rectangle();
// Create a render loop, which keeps the program open until glfw tells the loop that the window should close.
while (!glfwWindowShouldClose(window)) {
// Process input.
process_input(window);
// Set a callback to trigger whenever a key is pressed.
glfwSetKeyCallback(window, key_pressed);
// Set the GL state to use this color when clearing the screen.
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
@ -145,10 +213,17 @@ int main() {
// Use the shaderProgram shader program for drawing verticies.
glUseProgram(shaderProgram);
if (!rectangleToggled) {
// Bind the state to use the vertexArrayObject object so OpenGL knows what to do with the verticies.
glBindVertexArray(vertexArrayObject);
glBindVertexArray(triangleRenderObjs.vertexArrayObject);
// Draw the verticies.
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
} else {
glBindVertexArray(rectangleRenderObjs.vertexArrayObject);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
// This swaps completely drawn frames from the "second buffer" to the front one which is displayed on the screen.
glfwSwapBuffers(window);
@ -156,6 +231,11 @@ int main() {
glfwPollEvents();
}
// Clean up objects from memory.
triangleRenderObjs.Destroy();
rectangleRenderObjs.Destroy();
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
@ -176,3 +256,23 @@ int check_shader_compilation_status(unsigned int shaderId) {
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
return success;
}
void key_pressed(GLFWwindow *window, int key, int scancode, int action, int mods) {
// If the W key is pressed, toggle wireframe mode.
if (key == GLFW_KEY_W && action == GLFW_PRESS) {
if (!wireframe) {
// Render polygons in wireframe mode.
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
wireframe = true;
} else {
// Render polygons in fill mode.
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
wireframe = false;
}
}
// Flip a boolean indicating the rectangle should be rendered.
if (key == GLFW_KEY_R && action == GLFW_PRESS) {
rectangleToggled = !rectangleToggled;
}
}