wip: Basic spinning triangle demonstration
This commit is contained in:
parent
487dae631f
commit
d7996a991e
|
@ -1,6 +1,12 @@
|
|||
add_executable(Exponent
|
||||
main.cc
|
||||
GLProgramLoader.cc
|
||||
)
|
||||
|
||||
target_link_libraries(Exponent PUBLIC glfw glm::glm)
|
||||
target_include_directories(Exponent PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||
target_include_directories(Exponent PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
target_compile_definitions(Exponent PRIVATE GLFW_INCLUDE_NONE)
|
||||
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.frag" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.vert" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
|
|
@ -0,0 +1,81 @@
|
|||
#include "GLProgramLoader.hh"
|
||||
|
||||
#include <exception>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
static GLuint compile_shader(GLenum shader_type, const std::string &path) {
|
||||
if (shader_type != GL_VERTEX_SHADER && shader_type != GL_FRAGMENT_SHADER) {
|
||||
throw GLProgramException(std::format("Unsupported shader type {} provided.", shader_type));
|
||||
}
|
||||
|
||||
// Check that the path actually exists
|
||||
std::ifstream shader_file_handle;
|
||||
shader_file_handle.open(path);
|
||||
|
||||
if (!shader_file_handle.is_open()) {
|
||||
throw GLProgramException(std::format("Failed to open path {}.", path));
|
||||
}
|
||||
|
||||
// Read the data in.
|
||||
std::stringstream shader_source_stream;
|
||||
shader_source_stream << shader_file_handle.rdbuf();
|
||||
std::string shader_source_str = shader_source_stream.str();
|
||||
const GLchar *shader_source = shader_source_str.c_str();
|
||||
|
||||
GLuint shader_id = glCreateShader(shader_type);
|
||||
|
||||
if (shader_id == 0) {
|
||||
throw GLProgramException(std::format("Error when creating shader type {}.", shader_type));
|
||||
}
|
||||
|
||||
glShaderSource(shader_id, 1, &shader_source, NULL);
|
||||
glCompileShader(shader_id);
|
||||
GLint did_compile;
|
||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &did_compile);
|
||||
if(!did_compile) {
|
||||
GLint len = 0;
|
||||
|
||||
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &len);
|
||||
std::string error_log(len, ' ');
|
||||
|
||||
glGetShaderInfoLog(shader_id, len, &len, error_log.data());
|
||||
|
||||
glDeleteShader(shader_id);
|
||||
throw GLProgramException(std::format("Shader {} compilation failed:\n{}", path, error_log));
|
||||
}
|
||||
|
||||
return shader_id;
|
||||
}
|
||||
|
||||
GLuint compile_and_link_program(const std::vector<std::pair<GLuint, std::string>> &shaders) {
|
||||
// Firstly, compile all the shaders and get all of their ids.
|
||||
// I would love to use a functional map here, but C++ doesn't really do that.
|
||||
std::vector<GLuint> shader_ids = {};
|
||||
for(auto &s:shaders) {
|
||||
shader_ids.push_back(compile_shader(s.first, s.second));
|
||||
}
|
||||
|
||||
GLuint program_id = glCreateProgram();
|
||||
for (auto &s:shader_ids) {
|
||||
glAttachShader(program_id, s);
|
||||
}
|
||||
glLinkProgram(program_id);
|
||||
|
||||
GLint link_worked;
|
||||
glGetProgramiv(program_id, GL_LINK_STATUS, &link_worked);
|
||||
if (!link_worked) {
|
||||
GLint len = 0;
|
||||
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &len);
|
||||
|
||||
std::string error_log(len, ' ');
|
||||
|
||||
glGetProgramInfoLog(program_id, len, &len, error_log.data());
|
||||
|
||||
glDeleteProgram(program_id);
|
||||
throw GLProgramException(std::format("Program {} link failed:\n{}", program_id, error_log));
|
||||
}
|
||||
|
||||
return program_id;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "glad/gl.h"
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
class GLProgramException : public std::exception {
|
||||
std::string m_what;
|
||||
public:
|
||||
GLProgramException(const char *str):m_what(str) {
|
||||
}
|
||||
|
||||
GLProgramException(const std::string &str):m_what(str) {
|
||||
}
|
||||
|
||||
virtual const char* what() const throw() {
|
||||
return m_what.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GLuint compile_and_link_program(const std::vector<std::pair<GLuint, std::string>> &shaders);
|
97
src/main.cc
97
src/main.cc
|
@ -1,9 +1,20 @@
|
|||
#define GLAD_GL_IMPLEMENTATION
|
||||
#include "glad/gl.h"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
//http://seshbot.com/blog/2015/05/05/an-introduction-to-opengl-getting-started/
|
||||
#include "GLProgramLoader.hh"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// This has to come last.
|
||||
#define GLAD_GL_IMPLEMENTATION
|
||||
#include <glad/gl.h>
|
||||
|
||||
static void dbg_log(const char* str) {
|
||||
std::cout << str << std::endl;
|
||||
}
|
||||
|
||||
static void key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) {
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
||||
|
@ -11,14 +22,74 @@ static void key_callback(GLFWwindow *w, int key, int scancode, int action, int m
|
|||
}
|
||||
}
|
||||
|
||||
#define VERTEX_SHADER_LOCATION "shaders/shader.vert"
|
||||
#define FRAGMENT_SHADER_LOCATION "shaders/shader.frag"
|
||||
|
||||
GLuint g_program_id = 0;
|
||||
|
||||
static GLuint time_unif;
|
||||
|
||||
static void init_shaders() {
|
||||
dbg_log("Initialising shaders");
|
||||
|
||||
const std::vector<std::pair<GLuint, std::string>> shaders = {
|
||||
{GL_VERTEX_SHADER, VERTEX_SHADER_LOCATION},
|
||||
{GL_FRAGMENT_SHADER, FRAGMENT_SHADER_LOCATION},
|
||||
};
|
||||
|
||||
try {
|
||||
g_program_id = compile_and_link_program(shaders);
|
||||
} catch (GLProgramException e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
} catch (...) {
|
||||
std::cerr << "Unexpected exception while compiling shaders." << std::endl;
|
||||
}
|
||||
|
||||
glUseProgram(g_program_id);
|
||||
|
||||
glGetUniformLocation(g_program_id, "time");
|
||||
}
|
||||
|
||||
static const GLfloat verts[6] = {
|
||||
0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f
|
||||
};
|
||||
|
||||
static GLuint vertex_buf;
|
||||
static GLuint array_buf;
|
||||
static const GLuint vertex_data_position = 0;
|
||||
|
||||
// Do the work of initialising opengl so we can draw stuff
|
||||
static void init_opengl() {
|
||||
dbg_log("Initialising opengl");
|
||||
// Configure the context's capabilities
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
glGenVertexArrays(1, &array_buf);
|
||||
glBindVertexArray(array_buf);
|
||||
|
||||
glGenBuffers(1, &vertex_buf);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
|
||||
|
||||
|
||||
init_shaders();
|
||||
|
||||
glVertexAttribPointer(vertex_data_position, 2, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||
glEnableVertexAttribArray(vertex_data_position);
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
dbg_log("Initialising glfw");
|
||||
// Initialise GLFW
|
||||
if (!glfwInit()) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// Create our context
|
||||
GLFWwindow *w = glfwCreateWindow(640, 480, "Test", NULL, NULL);
|
||||
if (!w) {
|
||||
|
@ -32,13 +103,7 @@ int main() {
|
|||
// Set up the key handler
|
||||
glfwSetKeyCallback(w, key_callback);
|
||||
|
||||
// Configure the context's capabilities
|
||||
glClearColor(1.0, 0.0, 0.0, 1.0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND); // Maybe this allows transparency?
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// TODO: Actually make some opengl shit happen
|
||||
init_opengl();
|
||||
|
||||
// Main Loop
|
||||
while(!glfwWindowShouldClose(w)) {
|
||||
|
@ -50,6 +115,14 @@ int main() {
|
|||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
*/
|
||||
|
||||
float time = glfwGetTime();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glUniform1f(time_unif, time);
|
||||
glBindVertexArray(array_buf);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
// TODO Draw primitives
|
||||
|
||||
glfwSwapBuffers(w);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#version 430 core
|
||||
|
||||
out vec4 f_color;
|
||||
|
||||
// All fragments are the same colour for now.
|
||||
void main() {
|
||||
f_color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec4 v_position;
|
||||
|
||||
uniform float time;
|
||||
|
||||
// Simple passthrough shader for now.
|
||||
void main() {
|
||||
vec2 new_xy = v_position.xy * mat2x2(
|
||||
cos(time), -sin(time),
|
||||
sin(time), cos(time)
|
||||
);
|
||||
|
||||
vec4 new_position = vec4(new_xy.x, new_xy.y, 0.0, 1.0);
|
||||
|
||||
gl_Position = new_position;
|
||||
}
|
Loading…
Reference in New Issue