mirror of
https://github.com/MichaelFisher1997/opengl-cpp.git
synced 2025-04-27 22:23:10 +00:00
Merge pull request #1 from MichaelFisher1997/openGL-abstraction
Open gl abstraction
This commit is contained in:
commit
d25b046691
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
@ -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
|
||||||
|
}
|
55
.vscode/launch.json
vendored
Normal file
55
.vscode/launch.json
vendored
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
61
.vscode/settings.json
vendored
Normal file
61
.vscode/settings.json
vendored
Normal file
@ -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
|
||||||
|
}
|
41
MakeFile
41
MakeFile
@ -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
|
|
38
Makefile
Executable file
38
Makefile
Executable file
@ -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
|
60
src/IndexBuffer.cpp
Normal file
60
src/IndexBuffer.cpp
Normal file
@ -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'
|
||||||
|
}
|
24
src/IndexBuffer.h
Normal file
24
src/IndexBuffer.h
Normal file
@ -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;
|
||||||
|
};
|
20
src/Renderer.cpp
Normal file
20
src/Renderer.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "Renderer.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
37
src/Renderer.h
Normal file
37
src/Renderer.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "colormod.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) // Microsoft Visual C++
|
||||||
|
#include <intrin.h>
|
||||||
|
#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 <signal.h>
|
||||||
|
#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();
|
41
src/VertexArray.cpp
Normal file
41
src/VertexArray.cpp
Normal file
@ -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<VertexBufferElement> 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));
|
||||||
|
}
|
18
src/VertexArray.h
Normal file
18
src/VertexArray.h
Normal file
@ -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;
|
||||||
|
};
|
||||||
|
|
24
src/VertexBuffer.cpp
Normal file
24
src/VertexBuffer.cpp
Normal file
@ -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'
|
||||||
|
}
|
13
src/VertexBuffer.h
Normal file
13
src/VertexBuffer.h
Normal file
@ -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;
|
||||||
|
};
|
57
src/VertexBufferLayout.h
Normal file
57
src/VertexBufferLayout.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef VERTEXBUFFERLAYOUT_H
|
||||||
|
#define VERTEXBUFFERLAYOUT_H
|
||||||
|
#include <vector>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#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<typename T>
|
||||||
|
void Push(int count);
|
||||||
|
|
||||||
|
inline const std::vector<VertexBufferElement>& GetElements() const { return m_Elements; }
|
||||||
|
inline unsigned int GetStride() const { return m_Stride; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<VertexBufferElement> m_Elements;
|
||||||
|
unsigned int m_Stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Explicit specializations
|
||||||
|
template<>
|
||||||
|
inline void VertexBufferLayout::Push<float>(int count) {
|
||||||
|
m_Elements.push_back({ GL_FLOAT, static_cast<unsigned int>(count), GL_FALSE });
|
||||||
|
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void VertexBufferLayout::Push<unsigned int>(int count) {
|
||||||
|
m_Elements.push_back({ GL_UNSIGNED_INT,static_cast<unsigned int>(count), GL_FALSE });
|
||||||
|
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void VertexBufferLayout::Push<unsigned char>(int count) {
|
||||||
|
m_Elements.push_back({ GL_UNSIGNED_BYTE, static_cast<unsigned int>(count), GL_TRUE });
|
||||||
|
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_BYTE);
|
||||||
|
}
|
||||||
|
#endif // VERTEXBUFFERLAYOUT_H
|
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef COLORMOD_H
|
||||||
|
#define COLORMOD_H
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
namespace Color {
|
namespace Color {
|
||||||
enum Code {
|
enum Code {
|
||||||
@ -20,3 +22,4 @@ namespace Color {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
#endif // COLORMOD_H
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
// Create an instance of our SdlWindow class
|
// Create an instance of our SdlWindow class
|
||||||
|
std::cout << "starting" << std::endl;
|
||||||
SdlWindow window("My SDL2 Window", 800, 600);
|
SdlWindow window("My SDL2 Window", 800, 600);
|
||||||
|
std::cout << "About to run: " << std::endl;
|
||||||
|
|
||||||
// Run the main loop
|
// Run the main loop
|
||||||
window.run();
|
window.run();
|
||||||
|
141
src/sdl.cpp
141
src/sdl.cpp
@ -1,5 +1,6 @@
|
|||||||
#include <GL/glew.h> // Include GLEW before <SDL2/SDL.h>?
|
#include <GL/glew.h> // Include GLEW before <SDL2/SDL.h>?
|
||||||
#include "sdl.hpp"
|
#include "sdl.hpp"
|
||||||
|
#include "VertexBufferLayout.h"
|
||||||
#include "colormod.h"
|
#include "colormod.h"
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
@ -12,6 +13,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "VertexBuffer.h"
|
||||||
|
#include "VertexArray.h"
|
||||||
|
#include "IndexBuffer.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) // Microsoft Visual C++
|
#if defined(_MSC_VER) // Microsoft Visual C++
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#define DEBUG_BREAK() __debugbreak()
|
#define DEBUG_BREAK() __debugbreak()
|
||||||
@ -45,24 +51,31 @@ struct ShaderProgramSource {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SdlWindow::SdlWindow(const char* title, int width, int height)
|
SdlWindow::SdlWindow(const char* title, int width, int height)
|
||||||
: m_window(nullptr),
|
: m_window(nullptr),
|
||||||
m_renderer(nullptr),
|
m_renderer(nullptr),
|
||||||
m_isRunning(false),
|
m_isRunning(false),
|
||||||
m_isFullscreen(false),
|
m_isFullscreen(false),
|
||||||
m_width(width),
|
m_width(width),
|
||||||
m_height(height),
|
m_height(height),
|
||||||
m_glContext(nullptr),
|
m_windowedWidth(width),
|
||||||
m_windowedWidth(width),
|
m_windowedHeight(height),
|
||||||
m_windowedHeight(height),
|
r(0.5f),
|
||||||
r(0.0f),
|
m_glContext(nullptr),
|
||||||
location(),
|
increment(0.05f),
|
||||||
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
|
// 1. Set attributes
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
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
|
// 2. Create the window with OpenGL flag
|
||||||
m_window = SDL_CreateWindow(title,
|
m_window = SDL_CreateWindow(title,
|
||||||
SDL_WINDOWPOS_CENTERED,
|
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);
|
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN| SDL_WINDOW_RESIZABLE);
|
||||||
|
|
||||||
if (!m_window) {
|
if (!m_window) {
|
||||||
std::cerr << "Failed to create window: " << SDL_GetError() << std::endl;
|
std::cerr << "Failed to create window: " << SDL_GetError() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::cout << "Step 2: SDL_CreateWindow completed" << std::endl;
|
||||||
|
|
||||||
// 3. Create OpenGL context
|
|
||||||
m_glContext = SDL_GL_CreateContext(m_window);
|
m_glContext = SDL_GL_CreateContext(m_window);
|
||||||
if (!m_glContext) {
|
if (!m_glContext) {
|
||||||
std::cerr << "Failed to create GL context: " << SDL_GetError() << std::endl;
|
std::cerr << "Failed to create GL context: " << SDL_GetError() << std::endl;
|
||||||
return;
|
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__
|
#ifndef __APPLE__
|
||||||
glewExperimental = GL_TRUE;
|
glewExperimental = GL_TRUE;
|
||||||
GLenum glewErr = glewInit();
|
GLenum glewErr = glewInit();
|
||||||
if (glewInit() != GLEW_OK) {
|
if (glewErr != GLEW_OK) {
|
||||||
std::cerr << "Failed to init GLEW" << glewGetErrorString(glewErr) << std::endl;
|
std::cerr << "Failed to init GLEW: " << glewGetErrorString(glewErr) << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glGetError();
|
std::cout << "Step 5: GLEW initialized successfully" << std::endl;
|
||||||
|
glGetError(); // Clear GLEW's initial error
|
||||||
#endif
|
#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)
|
// 5. Set vsync (optional)
|
||||||
SDL_GL_SetSwapInterval(1); //Vsync
|
SDL_GL_SetSwapInterval(1); //Vsync
|
||||||
|
|
||||||
@ -111,31 +137,38 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
0, 1, 2,
|
0, 1, 2,
|
||||||
2, 3, 0
|
2, 3, 0
|
||||||
};
|
};
|
||||||
//vertex buffer
|
m_VA = new VertexArray();
|
||||||
unsigned int buffer;
|
m_VB = new VertexBuffer(positions, 4 * 2 * sizeof(float));
|
||||||
GLCall(glGenBuffers(1, &buffer));
|
m_IB = new IndexBuffer(indices, 6);
|
||||||
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
|
VertexBufferLayout layout;
|
||||||
//vertext attributes / layout
|
layout.Push<float>(2);
|
||||||
GLCall(glEnableVertexAttribArray(0));
|
|
||||||
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));
|
m_VA->AddBuffer(*m_VB, layout);
|
||||||
//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
|
|
||||||
|
|
||||||
ShaderProgramSource source = parseShader("res/shaders/Basic.shader");
|
ShaderProgramSource source = parseShader("res/shaders/Basic.shader");
|
||||||
unsigned int shader = createShader(source.VertexSource, source.FragmentSource);
|
|
||||||
GLCall(glUseProgram(shader));
|
|
||||||
|
|
||||||
GLCall(int location = glGetUniformLocation(shader, "u_Color"));
|
std::cout << "VERTEX" << std::endl << source.VertexSource << std::endl;
|
||||||
ASSERT(location != -1); // -1 is an error
|
std::cout << "FRAGMENT" << std::endl << source.FragmentSource << std::endl;
|
||||||
GLCall(glUniform4f(location, 0.8f, 0.3f, 0.8f, 1.0f));
|
|
||||||
|
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() {
|
SdlWindow::~SdlWindow() {
|
||||||
// If using SDL Renderer, destroy it. But if you’re purely using OpenGL, you might remove it.
|
// If using SDL Renderer, destroy it. But if you’re purely using OpenGL, you might remove it.
|
||||||
if (m_renderer) {
|
if (m_renderer) {
|
||||||
@ -153,20 +186,24 @@ SdlWindow::~SdlWindow() {
|
|||||||
SDL_DestroyWindow(m_window);
|
SDL_DestroyWindow(m_window);
|
||||||
m_window = nullptr;
|
m_window = nullptr;
|
||||||
}
|
}
|
||||||
|
if (m_shader) {
|
||||||
|
glDeleteProgram(m_shader);
|
||||||
|
m_shader = 0;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
//
|
||||||
void SdlWindow::run() {
|
void SdlWindow::run() {
|
||||||
while (m_isRunning) {
|
while (m_isRunning) {
|
||||||
processEvents();
|
processEvents();
|
||||||
update();
|
update();
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
GLCall(glDeleteProgram(shader));
|
GLCall(glDeleteProgram(m_shader));
|
||||||
}
|
}
|
||||||
|
//
|
||||||
void SdlWindow::processEvents() {
|
void SdlWindow::processEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
@ -212,7 +249,7 @@ SDL_Event event;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
void SdlWindow::update() {
|
void SdlWindow::update() {
|
||||||
// Update game/application logic here
|
// Update game/application logic here
|
||||||
if (r > 1.0f) {
|
if (r > 1.0f) {
|
||||||
@ -222,21 +259,29 @@ void SdlWindow::update() {
|
|||||||
}
|
}
|
||||||
r += increment;
|
r += increment;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
void SdlWindow::render() {
|
void SdlWindow::render() {
|
||||||
// Use GL calls instead of SDL’s renderer
|
// Use GL calls instead of SDL’s renderer
|
||||||
GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); //background
|
GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); //background
|
||||||
|
//
|
||||||
GLCall(glClear(GL_COLOR_BUFFER_BIT));
|
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.)
|
// 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);
|
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
|
||||||
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)); //macro assert for debugging
|
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)); //macro assert for debugging
|
||||||
|
|
||||||
// Swap buffers
|
// Swap buffers
|
||||||
SDL_GL_SwapWindow(m_window);
|
SDL_GL_SwapWindow(m_window);
|
||||||
}
|
}
|
||||||
|
//
|
||||||
void SdlWindow::setFullscreen(bool fullscreen) {
|
void SdlWindow::setFullscreen(bool fullscreen) {
|
||||||
if (m_window) {
|
if (m_window) {
|
||||||
m_isFullscreen = fullscreen;
|
m_isFullscreen = fullscreen;
|
||||||
@ -259,7 +304,7 @@ void SdlWindow::setFullscreen(bool fullscreen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
unsigned int SdlWindow::compileShader(unsigned int type, const std::string& source) {
|
unsigned int SdlWindow::compileShader(unsigned int type, const std::string& source) {
|
||||||
GLCall(unsigned int id = glCreateShader(type));
|
GLCall(unsigned int id = glCreateShader(type));
|
||||||
const char* src = source.c_str(); // <--- this string needs to exist when compiling/running
|
const char* src = source.c_str(); // <--- this string needs to exist when compiling/running
|
||||||
|
18
src/sdl.hpp
18
src/sdl.hpp
@ -9,10 +9,10 @@
|
|||||||
#include <GL/glew.h> // or <glad/glad.h> if using GLAD
|
#include <GL/glew.h> // or <glad/glad.h> if using GLAD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include "IndexBuffer.h"
|
||||||
|
#include "VertexBufferLayout.h"
|
||||||
|
#include "VertexArray.h"
|
||||||
|
|
||||||
// Forward declaration of classes and structs if needed
|
// Forward declaration of classes and structs if needed
|
||||||
// class SomethingElse;
|
// class SomethingElse;
|
||||||
@ -54,14 +54,14 @@ private:
|
|||||||
int m_windowedWidth; // stored width before fullscreen
|
int m_windowedWidth; // stored width before fullscreen
|
||||||
int m_windowedHeight; // stored height before fullscreen
|
int m_windowedHeight; // stored height before fullscreen
|
||||||
float r;
|
float r;
|
||||||
int location;
|
|
||||||
SDL_GLContext m_glContext;
|
SDL_GLContext m_glContext;
|
||||||
float increment;
|
float increment;
|
||||||
// temp shader stuff
|
// // temp shader stuff
|
||||||
std::string vetexShader;
|
unsigned int m_shader;
|
||||||
std::string fragmentShader;
|
GLint m_Location;
|
||||||
unsigned int shader;
|
VertexArray* m_VA;
|
||||||
|
IndexBuffer* m_IB;
|
||||||
|
VertexBuffer* m_VB;
|
||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
void processEvents();
|
void processEvents();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user