diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..e4fbba0 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "linux-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "/nix/store/xcn9p4xxfbvlkpah7pwchpav4ab9d135-gcc-wrapper-14-20241116/bin/gcc", + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..08caf88 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,55 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "cppdbg", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/build/${input:executableName}", + "preLaunchTask": "build", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "miDebuggerPath": "/usr/bin/gdb", + "logging": { + "engineLogging": true + } + }, + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": false, + "cwd": "/home/micqdf/opengl/cpp/src", + "program": "/home/micqdf/opengl/cpp/src/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "/nix/store/xcn9p4xxfbvlkpah7pwchpav4ab9d135-gdb-wrapper-14-20241116/bin/gcc", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ], + "inputs": [ + { + "type": "promptString", + "id": "executableName", + "description": "Name of your executable" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..50ea268 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,61 @@ +{ + "C_Cpp_Runner.cCompilerPath": "/nix/store/xcn9p4xxfbvlkpah7pwchpav4ab9d135-gcc-wrapper-14-20241116/bin/gcc", + "C_Cpp_Runner.cppCompilerPath": "/nix/store/xcn9p4xxfbvlkpah7pwchpav4ab9d135-g++-wrapper-14-20241116/bin/gcc", + "C_Cpp_Runner.debuggerPath": "/nix/store/xcn9p4xxfbvlkpah7pwchpav4ab9d135-gdb-wrapper-14-20241116/bin/gcc", + "C_Cpp_Runner.cStandard": "c17", + "C_Cpp_Runner.cppStandard": "gnu++17", + "C_Cpp_Runner.msvcBatchPath": "", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [ + "${workspaceFolder}/**" + ], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false +} \ No newline at end of file diff --git a/MakeFile b/MakeFile deleted file mode 100644 index f2b7558..0000000 --- a/MakeFile +++ /dev/null @@ -1,41 +0,0 @@ -# A simple Makefile for compiling small SDL projects - -# set the compiler -CC := clang - -# set the compiler flags -CFLAGS := `sdl2-config --libs --cflags` -ggdb3 -O0 --std=c99 -Wall -lSDL2_image -lm -# add header files here -HDRS := - -# add source files here -SRCS := #file-name.c - -# generate names of object files -OBJS := $(SRCS:.c=.o) - -# name of executable -EXEC := #name your executable file - -# default recipe -all: $(EXEC) - -showfont: showfont.c Makefile - $(CC) -o $@ $@.c $(CFLAGS) $(LIBS) - -glfont: glfont.c Makefile - $(CC) -o $@ $@.c $(CFLAGS) $(LIBS) - -# recipe for building the final executable -$(EXEC): $(OBJS) $(HDRS) Makefile - $(CC) -o $@ $(OBJS) $(CFLAGS) - -# recipe for building object files -#$(OBJS): $(@:.o=.c) $(HDRS) Makefile -# $(CC) -o $@ $(@:.o=.c) -c $(CFLAGS) - -# recipe to clean the workspace -clean: - rm -f $(EXEC) $(OBJS) - -.PHONY: all clean diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..e3e9861 --- /dev/null +++ b/Makefile @@ -0,0 +1,38 @@ +# Compiler and flags +CXX := g++ +CXXFLAGS := -g #-O0 -Wall -Wextra + +# Libraries +LDFLAGS := -lSDL2 -lGLEW -lGL + +# Source and output directories +SRC_DIR := src +BUILD_DIR := build +TARGET := $(BUILD_DIR)/opengl + +# Source files and object files +SRC := $(wildcard $(SRC_DIR)/*.cpp) +OBJ := $(SRC:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o) + +# Default target +all: $(TARGET) + +# Build the target executable +$(TARGET): $(OBJ) + mkdir -p $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS) + +# Build object files +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp + mkdir -p $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Clean up build files +clean: + rm -rf $(BUILD_DIR) + +# Run the application +run: $(TARGET) + ./$(TARGET) + +.PHONY: all clean run diff --git a/src/IndexBuffer.cpp b/src/IndexBuffer.cpp new file mode 100644 index 0000000..0e2b9a7 --- /dev/null +++ b/src/IndexBuffer.cpp @@ -0,0 +1,60 @@ +#include "IndexBuffer.h" +#include "Renderer.h" + +IndexBuffer::IndexBuffer(const unsigned int* data, unsigned int count) + : m_Count(count) +{ + ASSERT(sizeof(unsigned int) == sizeof(GLuint)); + // + //std::cout << "m_RendererID: " << &m_RendererID << " " << m_RendererID << std::endl; + GLCall(glGenBuffers(1, &m_RendererID)); + GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer' + GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), data, GL_STATIC_DRAW)); // assigne buffer size, static as we use many times, but does not change +} + +// Destructor +IndexBuffer::~IndexBuffer() { + if (m_RendererID != 0) { // Only delete if valid + GLCall(glDeleteBuffers(1, &m_RendererID)); + std::cout << "IndexBuffer destroyed with RendererID: " << m_RendererID << std::endl; + } +} + +// Move Constructor +IndexBuffer::IndexBuffer(IndexBuffer&& other) noexcept + : m_RendererID(other.m_RendererID), m_Count(other.m_Count) { + other.m_RendererID = 0; // Invalidate the moved-from object + other.m_Count = 0; + std::cout << "IndexBuffer moved (constructor)" << std::endl; +} + +// Move Assignment Operator +IndexBuffer& IndexBuffer::operator=(IndexBuffer&& other) noexcept { + if (this != &other) { + // Free existing resources + if (m_RendererID != 0) { + GLCall(glDeleteBuffers(1, &m_RendererID)); + } + + // Transfer ownership + m_RendererID = other.m_RendererID; + m_Count = other.m_Count; + + // Invalidate the moved-from object + other.m_RendererID = 0; + other.m_Count = 0; + + std::cout << "IndexBuffer moved (assignment)" << std::endl; + } + return *this; +} + +void IndexBuffer::Bind() const +{ + GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer' +} + +void IndexBuffer::Unbind() const +{ + GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); //select buffer called 'buffer' +} diff --git a/src/IndexBuffer.h b/src/IndexBuffer.h new file mode 100644 index 0000000..ec77e6d --- /dev/null +++ b/src/IndexBuffer.h @@ -0,0 +1,24 @@ +#pragma once + +class IndexBuffer +{ +public: + IndexBuffer(const unsigned int* data, unsigned int count); + ~IndexBuffer(); + + // Disallow copy operations + IndexBuffer(const IndexBuffer&) = delete; + IndexBuffer& operator=(const IndexBuffer&) = delete; + + // Enable move operations + IndexBuffer(IndexBuffer&& other) noexcept; + IndexBuffer& operator=(IndexBuffer&& other) noexcept; + + void Bind() const; + void Unbind() const; + + inline unsigned int GetCount() const { return m_Count; } +private: + unsigned int m_RendererID = 0; + unsigned int m_Count = 0; +}; diff --git a/src/Renderer.cpp b/src/Renderer.cpp new file mode 100644 index 0000000..811b91b --- /dev/null +++ b/src/Renderer.cpp @@ -0,0 +1,20 @@ +#include "Renderer.h" +#include + + + +void GLClearError() { + while (glGetError() != GL_NO_ERROR); + +} + +bool GLLogCall() { + Color::Modifier red(Color::FG_RED); + Color::Modifier def(Color::FG_DEFAULT); + while (GLenum error = glGetError()) { + std::cout << red << "[OpenGL Error] (" << error << ")" << def << std::endl; //if error, it will return a number, this needs to be converted to hex to then look up that value inn GL docs + return false; + } + return true; +} + diff --git a/src/Renderer.h b/src/Renderer.h new file mode 100644 index 0000000..75a4451 --- /dev/null +++ b/src/Renderer.h @@ -0,0 +1,37 @@ +#pragma once +#include "colormod.h" +#include + +#include + + +#if defined(_MSC_VER) // Microsoft Visual C++ + #include + #define DEBUG_BREAK() __debugbreak() +#elif defined(__i386__) || defined(__x86_64__) + // Use inline assembly for x86/x86_64 + #define DEBUG_BREAK() __asm__ volatile("int3") +#else + // Fallback on non-x86 platforms + #include + #define DEBUG_BREAK() raise(SIGTRAP) +#endif + +// ASSERT macro that shows file, line, and the failed expression +#define ASSERT(x) \ + do { \ + if (!(x)) { \ + std::cerr << "Assertion Failed: " << #x << '\n' \ + << "File: " << __FILE__ << '\n' \ + << "Line: " << __LINE__ << std::endl; \ + DEBUG_BREAK(); \ + } \ + } while (false) + +#define GLCall(x) GLClearError();\ + x;\ + ASSERT(GLLogCall()) + +#define INT2VOIDP(i) (void*)(uintptr_t)(i) +void GLClearError(); +bool GLLogCall(); \ No newline at end of file diff --git a/src/VertexArray.cpp b/src/VertexArray.cpp new file mode 100644 index 0000000..5a66e37 --- /dev/null +++ b/src/VertexArray.cpp @@ -0,0 +1,41 @@ +#include "VertexArray.h" +#include "Renderer.h" + +VertexArray::VertexArray() +{ + std::cout << "VertexArray::VertexArray()" << std::endl; + std::cout << "m_RendererID: " << &m_RendererID << std::endl; + GLCall(glGenVertexArrays(1, &m_RendererID)); + //glGenVertexArrays(1, &m_RendererID); + std::cout << "m_RendererID: " << &m_RendererID << std::endl; + if (!m_RendererID) { + std::cerr << "Failed to generate VAO" << std::endl; + } + + +} +VertexArray::~VertexArray() +{ + GLCall(glDeleteVertexArrays(1, &m_RendererID)); +} + +void VertexArray::AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout) +{ + Bind(); + vb.Bind(); + const std::vector elements = layout.GetElements(); + unsigned int offset = 0; + for (unsigned int i = 0; i < elements.size(); i++) { + const auto& element = elements[i]; + GLCall(glEnableVertexAttribArray(i)); + GLCall( glVertexAttribPointer(i, element.count, element.type, element.normalized,layout.GetStride(), INT2VOIDP(offset)) ); + offset += element.count * VertexBufferElement::GetSizeOfType(element.type); + } +} + +void VertexArray::Bind() const { + GLCall(glBindVertexArray(m_RendererID)); +} +void VertexArray::Unbind() const { + GLCall(glBindVertexArray(0)); +} diff --git a/src/VertexArray.h b/src/VertexArray.h new file mode 100644 index 0000000..31a711e --- /dev/null +++ b/src/VertexArray.h @@ -0,0 +1,18 @@ +#pragma once +#include "VertexBuffer.h" +#include "VertexBufferLayout.h" + +class VertexArray +{ + private: + unsigned int m_RendererID; + + public: + VertexArray(); + ~VertexArray(); + void AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout); + + void Bind() const; + void Unbind() const; +}; + diff --git a/src/VertexBuffer.cpp b/src/VertexBuffer.cpp new file mode 100644 index 0000000..12fb9d9 --- /dev/null +++ b/src/VertexBuffer.cpp @@ -0,0 +1,24 @@ +#include "VertexBuffer.h" +#include "Renderer.h" + +VertexBuffer::VertexBuffer(const void* data, unsigned int size) +{ + GLCall(glGenBuffers(1, &m_RendererID)); + GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer' + GLCall(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)); // assigne buffer size, static as we use many times, but does not change +} + +VertexBuffer::~VertexBuffer() +{ + GLCall(glDeleteBuffers(1, &m_RendererID)); +} + +void VertexBuffer::Bind() const +{ + GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer' +} + +void VertexBuffer::Unbind() const +{ + GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0)); //select buffer called 'buffer' +} diff --git a/src/VertexBuffer.h b/src/VertexBuffer.h new file mode 100644 index 0000000..75d8907 --- /dev/null +++ b/src/VertexBuffer.h @@ -0,0 +1,13 @@ +#pragma once + +class VertexBuffer +{ +private: + unsigned int m_RendererID; +public: + VertexBuffer(const void* data, unsigned int size); + ~VertexBuffer(); + + void Bind() const; + void Unbind() const; +}; diff --git a/src/VertexBufferLayout.h b/src/VertexBufferLayout.h new file mode 100644 index 0000000..49ccc57 --- /dev/null +++ b/src/VertexBufferLayout.h @@ -0,0 +1,57 @@ +#ifndef VERTEXBUFFERLAYOUT_H +#define VERTEXBUFFERLAYOUT_H +#include +#include +#include "Renderer.h" +struct VertexBufferElement { + unsigned int type; + unsigned int count; + unsigned char normalized; + + VertexBufferElement(unsigned int type, unsigned int count, unsigned char normalized) + : type(type), count(count), normalized(normalized) {} + + static unsigned int GetSizeOfType(unsigned int type) { + switch (type) { + case GL_FLOAT: return sizeof(GLfloat); + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + } + return 0; + } +}; + +class VertexBufferLayout { +public: + VertexBufferLayout() : m_Stride(0) {} + + template + void Push(int count); + + inline const std::vector& GetElements() const { return m_Elements; } + inline unsigned int GetStride() const { return m_Stride; } + +private: + std::vector m_Elements; + unsigned int m_Stride; +}; + +// Explicit specializations +template<> +inline void VertexBufferLayout::Push(int count) { + m_Elements.push_back({ GL_FLOAT, static_cast(count), GL_FALSE }); + m_Stride += count * VertexBufferElement::GetSizeOfType(GL_FLOAT); +} + +template<> +inline void VertexBufferLayout::Push(int count) { + m_Elements.push_back({ GL_UNSIGNED_INT,static_cast(count), GL_FALSE }); + m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_INT); +} + +template<> +inline void VertexBufferLayout::Push(int count) { + m_Elements.push_back({ GL_UNSIGNED_BYTE, static_cast(count), GL_TRUE }); + m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_BYTE); +} +#endif // VERTEXBUFFERLAYOUT_H diff --git a/src/colormod.h b/src/colormod.h index 181d550..5ba4e10 100644 --- a/src/colormod.h +++ b/src/colormod.h @@ -1,3 +1,5 @@ +#ifndef COLORMOD_H +#define COLORMOD_H #include namespace Color { enum Code { @@ -20,3 +22,4 @@ namespace Color { } }; } +#endif // COLORMOD_H \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f958fe7..6390123 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,9 @@ int main(int argc, char* argv[]) { // Create an instance of our SdlWindow class + std::cout << "starting" << std::endl; SdlWindow window("My SDL2 Window", 800, 600); + std::cout << "About to run: " << std::endl; // Run the main loop window.run(); diff --git a/src/sdl.cpp b/src/sdl.cpp index bf8d963..4ebb06b 100644 --- a/src/sdl.cpp +++ b/src/sdl.cpp @@ -1,5 +1,6 @@ #include // Include GLEW before ? #include "sdl.hpp" +#include "VertexBufferLayout.h" #include "colormod.h" #include #include @@ -12,6 +13,11 @@ #include #include +#include "Renderer.h" +#include "VertexBuffer.h" +#include "VertexArray.h" +#include "IndexBuffer.h" + #if defined(_MSC_VER) // Microsoft Visual C++ #include #define DEBUG_BREAK() __debugbreak() @@ -45,24 +51,31 @@ struct ShaderProgramSource { }; SdlWindow::SdlWindow(const char* title, int width, int height) - : m_window(nullptr), - m_renderer(nullptr), - m_isRunning(false), - m_isFullscreen(false), - m_width(width), - m_height(height), - m_glContext(nullptr), - m_windowedWidth(width), - m_windowedHeight(height), - r(0.0f), - location(), - increment(0.05f) +: m_window(nullptr), + m_renderer(nullptr), + m_isRunning(false), + m_isFullscreen(false), + m_width(width), + m_height(height), + m_windowedWidth(width), + m_windowedHeight(height), + r(0.5f), + m_glContext(nullptr), + increment(0.05f), + m_shader(0), + m_Location(-1), + m_IB(nullptr), + m_VB(nullptr), + m_VA(nullptr) { + + std::cout << "Step 0: hellow world" << std::endl; + // 1. Set attributes SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - + std::cout << "Step 1: SDL_GL_SetAttribute completed" << std::endl; // 2. Create the window with OpenGL flag m_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, @@ -72,27 +85,40 @@ SdlWindow::SdlWindow(const char* title, int width, int height) SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN| SDL_WINDOW_RESIZABLE); if (!m_window) { - std::cerr << "Failed to create window: " << SDL_GetError() << std::endl; - return; + std::cerr << "Failed to create window: " << SDL_GetError() << std::endl; + return; } + std::cout << "Step 2: SDL_CreateWindow completed" << std::endl; - // 3. Create OpenGL context m_glContext = SDL_GL_CreateContext(m_window); if (!m_glContext) { std::cerr << "Failed to create GL context: " << SDL_GetError() << std::endl; return; } - // 4. Optionally init GLEW (if not on macOS core profile) + std::cout << "Step 3: SDL_GL_CreateContext completed" << std::endl; + + if (SDL_GL_MakeCurrent(m_window, m_glContext) != 0) { + std::cerr << "Failed to make GL context current: " << SDL_GetError() << std::endl; + return; + } + std::cout << "Step 4: SDL_GL_MakeCurrent completed" << std::endl; + #ifndef __APPLE__ glewExperimental = GL_TRUE; GLenum glewErr = glewInit(); - if (glewInit() != GLEW_OK) { - std::cerr << "Failed to init GLEW" << glewGetErrorString(glewErr) << std::endl; + if (glewErr != GLEW_OK) { + std::cerr << "Failed to init GLEW: " << glewGetErrorString(glewErr) << std::endl; return; } - glGetError(); + std::cout << "Step 5: GLEW initialized successfully" << std::endl; + glGetError(); // Clear GLEW's initial error #endif + std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl; + std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl; + + // 5. Set vsync (optional) SDL_GL_SetSwapInterval(1); //Vsync @@ -111,31 +137,38 @@ SdlWindow::SdlWindow(const char* title, int width, int height) 0, 1, 2, 2, 3, 0 }; - //vertex buffer - unsigned int buffer; - GLCall(glGenBuffers(1, &buffer)); - GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer)); //select buffer called 'buffer' - GLCall(glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), positions, GL_STATIC_DRAW)); // assigne buffer size, static as we use many times, but does not change - //vertext attributes / layout - GLCall(glEnableVertexAttribArray(0)); - GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0)); - //indext beffer - unsigned int ibo; //indext buffer object - GLCall(glGenBuffers(1, &ibo)); - GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)); //select buffer called 'buffer' - GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW)); // assigne buffer size, static as we use many times, but does not change + m_VA = new VertexArray(); + m_VB = new VertexBuffer(positions, 4 * 2 * sizeof(float)); + m_IB = new IndexBuffer(indices, 6); - ShaderProgramSource source = parseShader("res/shaders/Basic.shader"); - unsigned int shader = createShader(source.VertexSource, source.FragmentSource); - GLCall(glUseProgram(shader)); + VertexBufferLayout layout; + layout.Push(2); + + m_VA->AddBuffer(*m_VB, layout); - GLCall(int location = glGetUniformLocation(shader, "u_Color")); - ASSERT(location != -1); // -1 is an error - GLCall(glUniform4f(location, 0.8f, 0.3f, 0.8f, 1.0f)); + ShaderProgramSource source = parseShader("res/shaders/Basic.shader"); + + std::cout << "VERTEX" << std::endl << source.VertexSource << std::endl; + std::cout << "FRAGMENT" << std::endl << source.FragmentSource << std::endl; + + unsigned int shader = createShader(source.VertexSource, source.FragmentSource); + m_shader = shader; + std::cout << "shader: " << m_shader << std::endl; + std::cout << "shader: " << m_shader << std::endl; + GLCall(glUseProgram(m_shader)); + + GLCall(m_Location = glGetUniformLocation(m_shader, "u_Color")); + ASSERT(m_Location != -1); // -1 is an error + + GLCall(glUniform4f(m_Location, 0.8f, 0.3f, 0.8f, 1.0f)); + + GLCall(glBindVertexArray(0)); + GLCall(glUseProgram(0)); + GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0)); + GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } - SdlWindow::~SdlWindow() { // If using SDL Renderer, destroy it. But if you’re purely using OpenGL, you might remove it. if (m_renderer) { @@ -153,20 +186,24 @@ SdlWindow::~SdlWindow() { SDL_DestroyWindow(m_window); m_window = nullptr; } + if (m_shader) { + glDeleteProgram(m_shader); + m_shader = 0; + } SDL_Quit(); } - - +// +// void SdlWindow::run() { while (m_isRunning) { processEvents(); update(); render(); } - GLCall(glDeleteProgram(shader)); + GLCall(glDeleteProgram(m_shader)); } - +// void SdlWindow::processEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { @@ -212,7 +249,7 @@ SDL_Event event; } } } - +// void SdlWindow::update() { // Update game/application logic here if (r > 1.0f) { @@ -222,21 +259,29 @@ void SdlWindow::update() { } r += increment; } - +// void SdlWindow::render() { // Use GL calls instead of SDL’s renderer GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); //background + // GLCall(glClear(GL_COLOR_BUFFER_BIT)); + + GLCall(glUseProgram(m_shader)); + std::cout << "m_shader: " << m_shader << std::endl; + std::cout << "location: " << m_Location << std::endl; + std::cout << "R: " << r << std::endl; + GLCall(glUniform4f(m_Location, r, 0.3f, 0.8f, 1.0f)); + m_VA->Bind(); + m_IB->Bind(); // TODO: Draw with OpenGL here (shaders, triangles, etc.) - GLCall(glUniform4f( location, r, 0.3f, 0.8f, 1.0f)); //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)); //macro assert for debugging // Swap buffers SDL_GL_SwapWindow(m_window); } - +// void SdlWindow::setFullscreen(bool fullscreen) { if (m_window) { m_isFullscreen = fullscreen; @@ -259,7 +304,7 @@ void SdlWindow::setFullscreen(bool fullscreen) { } } } - +// unsigned int SdlWindow::compileShader(unsigned int type, const std::string& source) { GLCall(unsigned int id = glCreateShader(type)); const char* src = source.c_str(); // <--- this string needs to exist when compiling/running diff --git a/src/sdl.hpp b/src/sdl.hpp index fc049f2..dbe6066 100644 --- a/src/sdl.hpp +++ b/src/sdl.hpp @@ -9,10 +9,10 @@ #include // or if using GLAD #endif -//#include -#include #include -#include +#include "IndexBuffer.h" +#include "VertexBufferLayout.h" +#include "VertexArray.h" // Forward declaration of classes and structs if needed // class SomethingElse; @@ -54,14 +54,14 @@ private: int m_windowedWidth; // stored width before fullscreen int m_windowedHeight; // stored height before fullscreen float r; - int location; SDL_GLContext m_glContext; float increment; - // temp shader stuff - std::string vetexShader; - std::string fragmentShader; - unsigned int shader; - +// // temp shader stuff + unsigned int m_shader; + GLint m_Location; + VertexArray* m_VA; + IndexBuffer* m_IB; + VertexBuffer* m_VB; // Private methods void processEvents();