Skip to content

Commit

Permalink
Add OpenGL abstractions
Browse files Browse the repository at this point in the history
  • Loading branch information
Notiooo committed Oct 29, 2023
1 parent b0aa280 commit 4caeaa8
Show file tree
Hide file tree
Showing 14 changed files with 532 additions and 0 deletions.
15 changes: 15 additions & 0 deletions AimGL/src/Renderer3D/Buffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "Buffer.h"
#include "pch.h"

Buffer::Buffer(Buffer&& rhs) noexcept
{
mBufferId = rhs.mBufferId;
rhs.mBufferId = 0;
}

Buffer& Buffer::operator=(Buffer&& rhs) noexcept
{
mBufferId = rhs.mBufferId;
rhs.mBufferId = 0;
return *this;
}
31 changes: 31 additions & 0 deletions AimGL/src/Renderer3D/Buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

/*
* The base class for all kinds of buffers found in OpenGL.
*/
class Buffer
{
public:
Buffer() = default;

Buffer(const Buffer&) = delete;
Buffer(Buffer&&) noexcept;

Buffer& operator=(const Buffer&) = delete;
Buffer& operator=(Buffer&&) noexcept;

virtual ~Buffer() = default;

/**
* Binds a buffer object to the specific (depends on derived class) buffer binding point
*/
virtual void bind() const = 0;

/**
* Unbinds a buffer object
*/
virtual void unbind() const = 0;

protected:
unsigned int mBufferId;
};
2 changes: 2 additions & 0 deletions AimGL/src/Renderer3D/BufferElement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "BufferElement.h"
#include "pch.h"
18 changes: 18 additions & 0 deletions AimGL/src/Renderer3D/BufferElement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

/**
* Represents the memory layout for the buffer layout part of a given type and number of elements.
*/
struct BufferElement
{
unsigned int type; //!< OpenGL type of given data
unsigned int count; //!< Number of elements of given type
unsigned char normalized;//!< Is the data normalized

/**
* Returns the data size of a given OpenGL type.
* @param type OpenGL Type.
* @return Size of given OpenGL type.
*/
static unsigned int sizeOfGLType(unsigned int type);
};
30 changes: 30 additions & 0 deletions AimGL/src/Renderer3D/BufferLayout.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "BufferLayout.h"
#include "Renderer3D/Renderer3D.h"
#include "pch.h"

unsigned BufferElement::sizeOfGLType(unsigned type)
{
switch (type)
{
case GL_FLOAT: return 4;
case GL_UNSIGNED_INT: return 4;
case GL_UNSIGNED_BYTE: return 1;
}
ASSERT(false);
return 0;
}

BufferLayout::BufferLayout()
: mStride(0)
{
}

const std::vector<BufferElement> BufferLayout::bufferElements() const
{
return mBufferElements;
}

unsigned BufferLayout::stride() const
{
return mStride;
}
75 changes: 75 additions & 0 deletions AimGL/src/Renderer3D/BufferLayout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once
#include "Renderer3D/BufferElement.h"
#include <vector>

/**
* Represents the data layout for a given buffer.
*/
class BufferLayout
{
public:
BufferLayout();

/**
* Adds information that the layout consists of the given number of elements of type T.
* @tparam T Parameters other than float, unsigned int and unsigned char are not supported.
* @param count Number of elements of a given type per row.
*/
template<typename T>
void push(unsigned int count)
{
// static_assert(false);
}

/**
* Adds information that the layout consists of the given number of elements of type float.
* @param count Number of elements of a float type per row.
*/
template<>
void push<float>(unsigned int count)
{
mBufferElements.push_back({GL_FLOAT, count, GL_FALSE});
mStride += BufferElement::sizeOfGLType(GL_FLOAT) * count;
}

/**
* Adds information that the layout consists of the given number of elements of type unsigned
* int.
* @param count Number of elements of a unsigned int type per row.
*/
template<>
void push<unsigned int>(unsigned int count)
{
mBufferElements.push_back({GL_UNSIGNED_INT, count, GL_FALSE});
mStride += BufferElement::sizeOfGLType(GL_UNSIGNED_INT) * count;
}

/**
* Adds information that the layout consists of the given number of elements of type unsigned
* char.
* @param count Number of elements of a unsigned char type per row.
*/
template<>
void push<unsigned char>(unsigned int count)
{
mBufferElements.push_back({GL_UNSIGNED_BYTE, count, GL_TRUE});
mStride += BufferElement::sizeOfGLType(GL_UNSIGNED_BYTE) * count;
}

/**
* Contains all buffer elements
* @return A vector of many single buffer elements
*/
[[nodiscard]] const std::vector<BufferElement> bufferElements() const;

/**
* Determines the size that one 'entry', or otherwise 'row' of data contains before the next set
* of data begins.
* @return Size of the stride
*/
[[nodiscard]] unsigned int stride() const;

private:
std::vector<BufferElement> mBufferElements;
unsigned int mStride;
};
47 changes: 47 additions & 0 deletions AimGL/src/Renderer3D/IndexBuffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "IndexBuffer.h"
#include "pch.h"

#include "Renderer3D.h"

IndexBuffer::IndexBuffer()
: mCount(0)
{
GLCall(glGenBuffers(1, &mBufferId));
}

IndexBuffer::IndexBuffer(const unsigned int* data, unsigned count)
: mCount(count)
{
ASSERT(sizeof(unsigned int) == sizeof(GLuint));

GLCall(glGenBuffers(1, &mBufferId));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLuint), data, GL_STATIC_DRAW));
}

IndexBuffer::~IndexBuffer()
{
GLCall(glDeleteBuffers(1, &mBufferId));
}

void IndexBuffer::bind() const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId));
}

void IndexBuffer::unbind() const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}

void IndexBuffer::setData(const unsigned int* data, unsigned count)
{
this->mCount = count;
bind();
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLuint), data, GL_STATIC_DRAW));
}

unsigned IndexBuffer::size() const
{
return mCount;
}
47 changes: 47 additions & 0 deletions AimGL/src/Renderer3D/IndexBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once
#include "Buffer.h"

/**
* A higher level representation of OpenGL IndexBuffer which is an array of pointers into the vertex
* buffer.
*/
class IndexBuffer : public Buffer
{
public:
IndexBuffer();
IndexBuffer(const unsigned int* data, unsigned int count);

IndexBuffer(const IndexBuffer&) = delete;
IndexBuffer(IndexBuffer&&) noexcept = default;

IndexBuffer& operator=(const IndexBuffer&) = delete;
IndexBuffer& operator=(IndexBuffer&&) noexcept = default;

~IndexBuffer() override;

/**
* Binds a buffer object to the specific (GL_ELEMENT_ARRAY_BUFFER) buffer binding point
*/
void bind() const override;

/**
* Unbinds a buffer object (GL_ELEMENT_ARRAY_BUFFER)
*/
void unbind() const override;

/**
* Sets the data with the specified number of ints and binds the buffer
* @param data Array of unsigned ints containing buffer indexes
* @param count Size of the Array
*/
void setData(const unsigned int* data, unsigned count);

/**
* Returns the number of elements in the index buffer
* @return Size of the index buffer
*/
unsigned int size() const;

private:
unsigned int mCount;
};
52 changes: 52 additions & 0 deletions AimGL/src/Renderer3D/Renderer3D.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "Renderer3D.h"
#include "pch.h"

#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Shader.hpp>

void GLClearError()
{
while (glGetError() /* != GL_NO_ERROR*/)
{
;
}
}

bool GLLogCall(const char* function, const char* file, int line)
{
if (GLenum error = glGetError())
{
std::cout << "[OpenGL Error] (0x" << std::hex << error << std::dec << "): " << function
<< " " << file << " at line: " << line << std::endl;
return false;
}
return true;
}

void Renderer3D::draw(const VertexArray& va, const IndexBuffer& ib, const sf::Shader& shader,
const DrawMode& drawMode) const
{
sf::Shader::bind(&shader);
va.bind();
ib.bind();
GLCall(glDrawElements(toOpenGL(drawMode), ib.size(), GL_UNSIGNED_INT, nullptr));

#ifdef _DEBUG
sf::Shader::bind(nullptr);
va.unbind();
ib.unbind();
#endif
}

unsigned Renderer3D::toOpenGL(const Renderer3D::DrawMode& drawMode) const
{
switch (drawMode)
{
case DrawMode::Lines: return GL_LINES;
case DrawMode::Triangles: return GL_TRIANGLES;
case DrawMode::Quads: return GL_QUADS;
default: throw std::runtime_error("This DrawMode is not supported!");
}
}
66 changes: 66 additions & 0 deletions AimGL/src/Renderer3D/Renderer3D.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once

#include "Renderer3D/IndexBuffer.h"
#include "Renderer3D/VertexArray.h"

/**
* Activates breakpoint
*/
#ifdef _MSC_VER
#define ASSERT(x) \
if (!x) \
__debugbreak();
#else
#define ASSERT(x) \
if (!x) \
raise(SIGTRAP);
#endif

/**
* Macro to use on OpenGL functions to correctly catch errors and write them out
*/
#define GLCall(x) \
GLClearError(); \
x; \
ASSERT(GLLogCall(#x, __FILE__, __LINE__));

/**
* Cleans up OpenGL errors
*/
void GLClearError();

/**
* Prints an error if an OpenGL error occurred
* @param function The function in which the error occurred
* @param file The name of the file in which the error occurred
* @param line The line where the error occurred
* @return False if the error occurred, true otherwise
*/
bool GLLogCall(const char* function, const char* file, int line);

/**
* 3D Renderer allows to draw 3D objects to the screen using appropriate buffers and shaders
*/
class Renderer3D
{
public:
enum class DrawMode
{
Lines,
Triangles,
Quads
};

/**
* Draws the data given in VertexArray, IndexBuffer to the screen using the interpretation given
* in Shader.
* @param va Stores all Vertex Data.
* @param ib Specifies the drawing order of the VertexArray.
* @param shader Shader telling how to draw data.
*/
void draw(const VertexArray& va, const IndexBuffer& ib, const sf::Shader& shader,
const DrawMode& drawMode = DrawMode::Triangles) const;

private:
unsigned toOpenGL(const DrawMode& drawMode) const;
};
Loading

0 comments on commit 4caeaa8

Please sign in to comment.