diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a3b204..8d39431 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,24 @@ -cmake_minimum_required(VERSION 4.2) +cmake_minimum_required(VERSION 3.20) project(Cinecraft) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$") - set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED on) find_package(SDL3 REQUIRED) +find_package(GLEW REQUIRED) -add_executable(app src/main.cpp) +add_executable(${PROJECT_NAME} src/main.cpp + include/VertexBuffer.hpp + include/defines.hpp + src/Shader.cpp + include/Shader.hpp) -target_link_libraries(app PRIVATE SDL3::SDL3 GL) \ No newline at end of file +target_include_directories(${PROJECT_NAME} PRIVATE include) +target_include_directories(${PROJECT_NAME} PRIVATE shaders) + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_SOURCE_DIR}/shaders + ${CMAKE_CURRENT_BINARY_DIR}/shaders) + +target_link_libraries(${PROJECT_NAME} PRIVATE SDL3::SDL3 GLEW::GLEW GL) \ No newline at end of file diff --git a/include/Shader.hpp b/include/Shader.hpp new file mode 100644 index 0000000..2eddf92 --- /dev/null +++ b/include/Shader.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include "defines.hpp" + +struct Shader { + Shader(const char* vertexShaderFileName, const char* fragmentShaderFileName); + virtual ~Shader(); + + void bind(); + void unbind(); + +private: + GLuint compile(std::string shaderSource, GLenum shaderType); + std::string parse(const char* filename); + GLuint createShader(const char* vertexShaderFileName, const char* fragmentShaderFileName); + + GLuint shaderId; +}; \ No newline at end of file diff --git a/include/VertexBuffer.hpp b/include/VertexBuffer.hpp new file mode 100644 index 0000000..bee5f98 --- /dev/null +++ b/include/VertexBuffer.hpp @@ -0,0 +1,34 @@ +#pragma once +#include + +#include "defines.hpp" + +struct VertexBuffer { + VertexBuffer(void* data, uint32 numVertices) { + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &bufferId); + glBindBuffer(GL_ARRAY_BUFFER, bufferId); + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Vertex), data, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(struct Vertex,x)); + + glBindVertexArray(0); + }; + virtual ~VertexBuffer() { + glDeleteBuffers(1, &bufferId); + } + + void bind() { + glBindVertexArray(vao); + } + void unbind() { + glBindVertexArray(0); + } + +private: + GLuint bufferId; + GLuint vao; +}; \ No newline at end of file diff --git a/include/defines.hpp b/include/defines.hpp new file mode 100644 index 0000000..4b364ba --- /dev/null +++ b/include/defines.hpp @@ -0,0 +1,19 @@ +#pragma once +#include + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; + +typedef float float32; +typedef double float64; + +struct Vertex { + float32 x, y, z; +}; \ No newline at end of file diff --git a/shaders/README.md b/shaders/README.md new file mode 100644 index 0000000..f6e2d6c --- /dev/null +++ b/shaders/README.md @@ -0,0 +1,4 @@ +# Attributes +|Index|Description| +|---|---| +|0|Position| \ No newline at end of file diff --git a/shaders/basic.frag b/shaders/basic.frag new file mode 100644 index 0000000..998d91e --- /dev/null +++ b/shaders/basic.frag @@ -0,0 +1,7 @@ +#version 330 core + +layout(location = 0) out vec4 color; + +void main() { + color = vec4(1.0f, 1.0f, 0.0f, 1.0f); +} \ No newline at end of file diff --git a/shaders/basic.vert b/shaders/basic.vert new file mode 100644 index 0000000..2649cde --- /dev/null +++ b/shaders/basic.vert @@ -0,0 +1,7 @@ +#version 330 core + +layout(location = 0) in vec3 position; + +void main() { + gl_Position = vec4(position, 1.0f); +} \ No newline at end of file diff --git a/src/Shader.cpp b/src/Shader.cpp new file mode 100644 index 0000000..96b7a1a --- /dev/null +++ b/src/Shader.cpp @@ -0,0 +1,78 @@ +#include +#include +#include "Shader.hpp" + +Shader::Shader(const char* vertexShaderFileName, const char* fragmentShaderFileName) { + shaderId = createShader(vertexShaderFileName, fragmentShaderFileName); +} + +Shader::~Shader() { + glDeleteProgram(shaderId); +} + +void Shader::bind() { + glUseProgram(shaderId); +} + +void Shader::unbind() { + glUseProgram(0); +} + +GLuint Shader::compile(std::string shaderSource, GLenum shaderType) { + GLuint id = glCreateShader(shaderType); + const char* src = shaderSource.c_str(); + glShaderSource(id, 1, &src, nullptr); + glCompileShader(id); + + int result; + glGetShaderiv(id, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) { + int length = 0; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); + char* message = new char[length]; + glGetShaderInfoLog(id, length, &length, message); + std::cout << "Shader Compilation Error" << message << std::endl; + delete[] message; + return 0; + } + return id; +} + +std::string Shader::parse(const char* filename) { + FILE* file; + file = fopen(filename, "rb"); + if (file == nullptr) { + std::cout << "File " << filename << " not found" << std::endl; + } + std::string contents; + fseek(file, 0, SEEK_END); + size_t filesize = ftell(file); + rewind(file); + contents.resize(filesize); + fread(&contents[0], 1, filesize, file); + fclose(file); + + return contents; +} + +GLuint Shader::createShader(const char* vertexShaderFileName, const char* fragmentShaderFileName) { + std::string vertexShaderSource = parse(vertexShaderFileName); + std::string fragmentShaderSource = parse(fragmentShaderFileName); + + GLuint program = glCreateProgram(); + GLuint vert = compile(vertexShaderSource, GL_VERTEX_SHADER); + GLuint frag = compile(fragmentShaderSource, GL_FRAGMENT_SHADER); + + glAttachShader(program, vert); + glAttachShader(program, frag); + glLinkProgram(program); + + // ATTENTION: use only for release + // NOTE: if you do not detach and delete the program from the gpu, it's easier to debug if errors happen with the shaders + // glDetachShader(program, vert); + // glDetachShader(program, frag); + // glDeleteShader(vert); + // glDeleteShader(frag); + + return program; +} diff --git a/src/main.cpp b/src/main.cpp index a6056af..38b2b4e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,12 @@ +#include +#define GLEW_STATIC +#include +#define SDL_MAIN_HANDLED #include -#include + +#include "defines.hpp" +#include "VertexBuffer.hpp" +#include "Shader.hpp" int main() { SDL_Init(SDL_INIT_VIDEO); @@ -20,9 +27,28 @@ int main() { SDL_GLContext context = SDL_GL_CreateContext(window); + GLenum err = glewInit(); + if (err != GLEW_OK) { + std::cout <<"Error: " << glewGetErrorString(err) << std::endl; + return -1; + } + std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl; + + Vertex vertices[] = { + Vertex{-0.5f, -0.5f, 0.0f}, + Vertex{0.0f, 0.5f, 0.0f}, + Vertex{0.5f, -0.5f, 0.0f}, + }; + uint32_t numVertices = 3; + + VertexBuffer vertexBuffer(vertices, numVertices); + vertexBuffer.unbind(); + + Shader shader("shaders/basic.vert", "shaders/basic.frag"); + shader.bind(); + bool running = true; SDL_Event e; - while (running) { while (SDL_PollEvent(&e)) { if (e.type == SDL_EVENT_QUIT) { @@ -30,9 +56,14 @@ int main() { } } - glClearColor(0.1f, 0.2f, 0.3f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + // FRAME GENERATION + vertexBuffer.bind(); + glDrawArrays(GL_TRIANGLES, 0, numVertices); + vertexBuffer.unbind(); + SDL_GL_SwapWindow(window); } @@ -41,4 +72,4 @@ int main() { SDL_Quit(); return 0; -} \ No newline at end of file +}