mirror of
https://github.com/MichaelFisher1997/opengl-cpp.git
synced 2025-04-27 14:13:10 +00:00
Merge pull request #2 from MichaelFisher1997/shader-abstraction
Shader abstraction
This commit is contained in:
commit
e5a9f37c88
@ -2,21 +2,26 @@
|
|||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
|
|
||||||
IndexBuffer::IndexBuffer(const unsigned int *data, unsigned int count)
|
IndexBuffer::IndexBuffer(const unsigned int *data, unsigned int count)
|
||||||
: m_Count(count)
|
: m_Count(count) {
|
||||||
{
|
|
||||||
ASSERT(sizeof(unsigned int) == sizeof(GLuint));
|
ASSERT(sizeof(unsigned int) == sizeof(GLuint));
|
||||||
//
|
//
|
||||||
//std::cout << "m_RendererID: " << &m_RendererID << " " << m_RendererID << std::endl;
|
// std::cout << "m_RendererID: " << &m_RendererID << " " << m_RendererID <<
|
||||||
|
// std::endl;
|
||||||
GLCall(glGenBuffers(1, &m_RendererID));
|
GLCall(glGenBuffers(1, &m_RendererID));
|
||||||
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer'
|
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_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
|
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
|
// Destructor
|
||||||
IndexBuffer::~IndexBuffer() {
|
IndexBuffer::~IndexBuffer() {
|
||||||
if (m_RendererID != 0) { // Only delete if valid
|
if (m_RendererID != 0) { // Only delete if valid
|
||||||
GLCall(glDeleteBuffers(1, &m_RendererID));
|
GLCall(glDeleteBuffers(1, &m_RendererID));
|
||||||
std::cout << "IndexBuffer destroyed with RendererID: " << m_RendererID << std::endl;
|
std::cout << "IndexBuffer destroyed with RendererID: " << m_RendererID
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,12 +54,12 @@ IndexBuffer& IndexBuffer::operator=(IndexBuffer&& other) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexBuffer::Bind() const
|
void IndexBuffer::Bind() const {
|
||||||
{
|
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
|
||||||
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer'
|
m_RendererID)); // select buffer called 'buffer'
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexBuffer::Unbind() const
|
void IndexBuffer::Unbind() const {
|
||||||
{
|
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
|
||||||
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); //select buffer called 'buffer'
|
0)); // select buffer called 'buffer'
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
#include "Renderer.h"
|
#include <GL/glew.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Renderer.h"
|
||||||
|
|
||||||
void GLClearError() {
|
void GLClearError() {
|
||||||
while (glGetError() != GL_NO_ERROR);
|
while (glGetError() != GL_NO_ERROR)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLLogCall() {
|
bool GLLogCall() {
|
||||||
Color::Modifier red(Color::FG_RED);
|
Color::Modifier red(Color::FG_RED);
|
||||||
Color::Modifier def(Color::FG_DEFAULT);
|
Color::Modifier def(Color::FG_DEFAULT);
|
||||||
while (GLenum error = glGetError()) {
|
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
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "colormod.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <assert.h>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include "colormod.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) // Microsoft Visual C++
|
#if defined(_MSC_VER) // Microsoft Visual C++
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
@ -33,5 +33,8 @@
|
|||||||
ASSERT(GLLogCall())
|
ASSERT(GLLogCall())
|
||||||
|
|
||||||
#define INT2VOIDP(i) (void*)(uintptr_t)(i)
|
#define INT2VOIDP(i) (void*)(uintptr_t)(i)
|
||||||
|
|
||||||
|
// Declare global functions
|
||||||
void GLClearError();
|
void GLClearError();
|
||||||
bool GLLogCall();
|
bool GLLogCall();
|
||||||
|
|
||||||
|
135
src/Shader.cpp
Normal file
135
src/Shader.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "Shader.h"
|
||||||
|
#include "IndexBuffer.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "VertexArray.h"
|
||||||
|
#include "VertexBuffer.h"
|
||||||
|
#include "fstream"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
Shader::Shader(const std::string &filepath)
|
||||||
|
: m_FilePath(filepath), m_RendererID(0) {
|
||||||
|
ShaderProgramSource source = ParseShader(filepath);
|
||||||
|
|
||||||
|
std::cout << "VERTEX" << std::endl << source.VertexSource << std::endl;
|
||||||
|
std::cout << "FRAGMENT" << std::endl << source.FragmentSource << std::endl;
|
||||||
|
|
||||||
|
m_RendererID = CreateShader(source.VertexSource, source.FragmentSource);
|
||||||
|
|
||||||
|
GLCall(glUseProgram(m_RendererID));
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::~Shader() { GLCall(glDeleteProgram(m_RendererID)); }
|
||||||
|
|
||||||
|
void Shader::Bind() const { GLCall(glUseProgram(m_RendererID)); }
|
||||||
|
|
||||||
|
void Shader::Unbind() const { GLCall(glUseProgram(0)); }
|
||||||
|
|
||||||
|
int Shader::GetUniformLocation(const std::string &name) {
|
||||||
|
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
|
||||||
|
return m_UniformLocationCache[name];
|
||||||
|
|
||||||
|
GLCall(int location = glGetUniformLocation(m_RendererID, name.c_str()));
|
||||||
|
if (location == -1)
|
||||||
|
std::cout << "No active uniform variable with name " << name << " found"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
m_UniformLocationCache[name] = location;
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetUniform1f(const std::string &name, float value) {
|
||||||
|
GLCall(glUniform1f(GetUniformLocation(name), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetUniform4f(const std::string &name, float f0, float f1, float f2,
|
||||||
|
float f3) {
|
||||||
|
GLCall(glUniform4f(GetUniformLocation(name), f0, f1, f2, f3));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShaderType { NONE = -1, VERTEX = 0, FRAGMENT = 1 };
|
||||||
|
|
||||||
|
struct ShaderProgramSource Shader::ParseShader(const std::string &filepath) {
|
||||||
|
|
||||||
|
std::ifstream stream(filepath);
|
||||||
|
std::string line;
|
||||||
|
std::stringstream ss[2];
|
||||||
|
ShaderType type = NONE;
|
||||||
|
|
||||||
|
while (getline(stream, line)) {
|
||||||
|
if (line.find("#shader") != std::string::npos) {
|
||||||
|
if (line.find("vertex") != std::string::npos)
|
||||||
|
type = VERTEX;
|
||||||
|
else if (line.find("fragment") != std::string::npos)
|
||||||
|
type = FRAGMENT;
|
||||||
|
} else {
|
||||||
|
ss[(int)type] << line << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ShaderProgramSource sps = {ss[0].str(), ss[1].str()};
|
||||||
|
return sps;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Shader::CompileShader(unsigned int type,
|
||||||
|
const std::string &source) {
|
||||||
|
GLCall(unsigned int id = glCreateShader(type));
|
||||||
|
const char *src = source.c_str();
|
||||||
|
GLCall(glShaderSource(id, 1, &src, nullptr));
|
||||||
|
GLCall(glCompileShader(id));
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
int result;
|
||||||
|
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
|
||||||
|
std::cout << (type == GL_VERTEX_SHADER ? "vertex" : "fragment")
|
||||||
|
<< " shader compile status: " << result << std::endl;
|
||||||
|
if (result == GL_FALSE) {
|
||||||
|
int length;
|
||||||
|
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
|
||||||
|
char *message = (char *)alloca(length * sizeof(char));
|
||||||
|
GLCall(glGetShaderInfoLog(id, length, &length, message));
|
||||||
|
std::cout << "Failed to compile "
|
||||||
|
<< (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader"
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << message << std::endl;
|
||||||
|
GLCall(glDeleteShader(id));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Shader::CreateShader(const std::string &vertexShader,
|
||||||
|
const std::string &fragmentShader) {
|
||||||
|
// create a shader program
|
||||||
|
unsigned int program = glCreateProgram();
|
||||||
|
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
|
||||||
|
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
|
||||||
|
|
||||||
|
GLCall(glAttachShader(program, vs));
|
||||||
|
GLCall(glAttachShader(program, fs));
|
||||||
|
|
||||||
|
GLCall(glLinkProgram(program));
|
||||||
|
|
||||||
|
GLint program_linked;
|
||||||
|
|
||||||
|
GLCall(glGetProgramiv(program, GL_LINK_STATUS, &program_linked));
|
||||||
|
std::cout << "Program link status: " << program_linked << std::endl;
|
||||||
|
if (program_linked != GL_TRUE) {
|
||||||
|
GLsizei log_length = 0;
|
||||||
|
GLchar message[1024];
|
||||||
|
GLCall(glGetProgramInfoLog(program, 1024, &log_length, message));
|
||||||
|
std::cout << "Failed to link program" << std::endl;
|
||||||
|
std::cout << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCall(glValidateProgram(program));
|
||||||
|
|
||||||
|
GLCall(glDeleteShader(vs));
|
||||||
|
GLCall(glDeleteShader(fs));
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
36
src/Shader.h
Normal file
36
src/Shader.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct ShaderProgramSource
|
||||||
|
{
|
||||||
|
std::string VertexSource;
|
||||||
|
std::string FragmentSource;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned int m_RendererID;
|
||||||
|
std::string m_FilePath;
|
||||||
|
std::unordered_map<std::string, int> m_UniformLocationCache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Shader(const std::string& filepath);
|
||||||
|
~Shader();
|
||||||
|
|
||||||
|
void Bind() const;
|
||||||
|
void Unbind() const;
|
||||||
|
|
||||||
|
// Set uniforms
|
||||||
|
void SetUniform4f(const std::string& name, float f0, float f1, float f2, float f3);
|
||||||
|
void SetUniform1f(const std::string& name, float value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int GetUniformLocation(const std::string& name);
|
||||||
|
struct ShaderProgramSource ParseShader(const std::string& filepath);
|
||||||
|
unsigned int CompileShader(unsigned int type, const std::string& source);
|
||||||
|
unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader);
|
||||||
|
|
||||||
|
};
|
@ -1,8 +1,7 @@
|
|||||||
#include "VertexArray.h"
|
#include "VertexArray.h"
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
|
|
||||||
VertexArray::VertexArray()
|
VertexArray::VertexArray() {
|
||||||
{
|
|
||||||
std::cout << "VertexArray::VertexArray()" << std::endl;
|
std::cout << "VertexArray::VertexArray()" << std::endl;
|
||||||
std::cout << "m_RendererID: " << &m_RendererID << std::endl;
|
std::cout << "m_RendererID: " << &m_RendererID << std::endl;
|
||||||
GLCall(glGenVertexArrays(1, &m_RendererID));
|
GLCall(glGenVertexArrays(1, &m_RendererID));
|
||||||
@ -11,16 +10,11 @@ VertexArray::VertexArray()
|
|||||||
if (!m_RendererID) {
|
if (!m_RendererID) {
|
||||||
std::cerr << "Failed to generate VAO" << std::endl;
|
std::cerr << "Failed to generate VAO" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
VertexArray::~VertexArray()
|
|
||||||
{
|
|
||||||
GLCall(glDeleteVertexArrays(1, &m_RendererID));
|
|
||||||
}
|
}
|
||||||
|
VertexArray::~VertexArray() { GLCall(glDeleteVertexArrays(1, &m_RendererID)); }
|
||||||
|
|
||||||
void VertexArray::AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout)
|
void VertexArray::AddBuffer(const VertexBuffer &vb,
|
||||||
{
|
const VertexBufferLayout &layout) {
|
||||||
Bind();
|
Bind();
|
||||||
vb.Bind();
|
vb.Bind();
|
||||||
const std::vector<VertexBufferElement> elements = layout.GetElements();
|
const std::vector<VertexBufferElement> elements = layout.GetElements();
|
||||||
@ -28,14 +22,12 @@ void VertexArray::AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& la
|
|||||||
for (unsigned int i = 0; i < elements.size(); i++) {
|
for (unsigned int i = 0; i < elements.size(); i++) {
|
||||||
const auto &element = elements[i];
|
const auto &element = elements[i];
|
||||||
GLCall(glEnableVertexAttribArray(i));
|
GLCall(glEnableVertexAttribArray(i));
|
||||||
GLCall( glVertexAttribPointer(i, element.count, element.type, element.normalized,layout.GetStride(), INT2VOIDP(offset)) );
|
GLCall(glVertexAttribPointer(i, element.count, element.type,
|
||||||
|
element.normalized, layout.GetStride(),
|
||||||
|
INT2VOIDP(offset)));
|
||||||
offset += element.count * VertexBufferElement::GetSizeOfType(element.type);
|
offset += element.count * VertexBufferElement::GetSizeOfType(element.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexArray::Bind() const {
|
void VertexArray::Bind() const { GLCall(glBindVertexArray(m_RendererID)); }
|
||||||
GLCall(glBindVertexArray(m_RendererID));
|
void VertexArray::Unbind() const { GLCall(glBindVertexArray(0)); }
|
||||||
}
|
|
||||||
void VertexArray::Unbind() const {
|
|
||||||
GLCall(glBindVertexArray(0));
|
|
||||||
}
|
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
#include "VertexBuffer.h"
|
#include "VertexBuffer.h"
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
|
|
||||||
VertexBuffer::VertexBuffer(const void* data, unsigned int size)
|
VertexBuffer::VertexBuffer(const void *data, unsigned int size) {
|
||||||
{
|
|
||||||
GLCall(glGenBuffers(1, &m_RendererID));
|
GLCall(glGenBuffers(1, &m_RendererID));
|
||||||
GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID)); //select buffer called 'buffer'
|
GLCall(glBindBuffer(GL_ARRAY_BUFFER,
|
||||||
GLCall(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)); // assigne buffer size, static as we use many times, but does not change
|
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()
|
VertexBuffer::~VertexBuffer() { GLCall(glDeleteBuffers(1, &m_RendererID)); }
|
||||||
{
|
|
||||||
GLCall(glDeleteBuffers(1, &m_RendererID));
|
void VertexBuffer::Bind() const {
|
||||||
|
GLCall(glBindBuffer(GL_ARRAY_BUFFER,
|
||||||
|
m_RendererID)); // select buffer called 'buffer'
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexBuffer::Bind() const
|
void VertexBuffer::Unbind() 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'
|
GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0)); // select buffer called 'buffer'
|
||||||
}
|
}
|
||||||
|
@ -11,4 +11,3 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
232
src/sdl.cpp
232
src/sdl.cpp
@ -1,73 +1,25 @@
|
|||||||
#include <GL/glew.h> // Include GLEW before <SDL2/SDL.h>?
|
|
||||||
#include "sdl.hpp"
|
#include "sdl.hpp"
|
||||||
#include "VertexBufferLayout.h"
|
#include "VertexBufferLayout.h"
|
||||||
#include "colormod.h"
|
#include <GL/glew.h> // Include GLEW before <SDL2/SDL.h>?
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
//#include <iterator>
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "VertexBuffer.h"
|
|
||||||
#include "VertexArray.h"
|
|
||||||
#include "IndexBuffer.h"
|
#include "IndexBuffer.h"
|
||||||
|
#include "Renderer.h"
|
||||||
#if defined(_MSC_VER) // Microsoft Visual C++
|
#include "Shader.h"
|
||||||
#include <intrin.h>
|
#include "VertexArray.h"
|
||||||
#define DEBUG_BREAK() __debugbreak()
|
#include "VertexBuffer.h"
|
||||||
#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())
|
|
||||||
|
|
||||||
|
|
||||||
struct ShaderProgramSource {
|
|
||||||
std::string VertexSource, FragmentSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
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_isRunning(false),
|
||||||
m_renderer(nullptr),
|
m_isFullscreen(false), m_width(width), m_height(height),
|
||||||
m_isRunning(false),
|
m_windowedWidth(width), m_windowedHeight(height), r(0.5f),
|
||||||
m_isFullscreen(false),
|
m_glContext(nullptr), increment(0.05f), m_Shader(nullptr), m_Location(-1),
|
||||||
m_width(width),
|
m_IB(nullptr), m_VB(nullptr), m_VA(nullptr) {
|
||||||
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;
|
std::cout << "Step 0: hellow world" << std::endl;
|
||||||
|
|
||||||
@ -77,11 +29,8 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
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;
|
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(
|
||||||
SDL_WINDOWPOS_CENTERED,
|
title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height,
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
width,
|
|
||||||
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) {
|
||||||
@ -98,7 +47,8 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
std::cout << "Step 3: SDL_GL_CreateContext completed" << std::endl;
|
std::cout << "Step 3: SDL_GL_CreateContext completed" << std::endl;
|
||||||
|
|
||||||
if (SDL_GL_MakeCurrent(m_window, m_glContext) != 0) {
|
if (SDL_GL_MakeCurrent(m_window, m_glContext) != 0) {
|
||||||
std::cerr << "Failed to make GL context current: " << SDL_GetError() << std::endl;
|
std::cerr << "Failed to make GL context current: " << SDL_GetError()
|
||||||
|
<< std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cout << "Step 4: SDL_GL_MakeCurrent completed" << std::endl;
|
std::cout << "Step 4: SDL_GL_MakeCurrent completed" << std::endl;
|
||||||
@ -107,7 +57,8 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
glewExperimental = GL_TRUE;
|
glewExperimental = GL_TRUE;
|
||||||
GLenum glewErr = glewInit();
|
GLenum glewErr = glewInit();
|
||||||
if (glewErr != 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;
|
||||||
}
|
}
|
||||||
std::cout << "Step 5: GLEW initialized successfully" << std::endl;
|
std::cout << "Step 5: GLEW initialized successfully" << std::endl;
|
||||||
@ -115,17 +66,18 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
|
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
|
||||||
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
|
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
||||||
|
<< std::endl;
|
||||||
std::cout << "Vendor: " << glGetString(GL_VENDOR) << 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
|
||||||
|
|
||||||
// 6. Mark as running
|
// 6. Mark as running
|
||||||
m_isRunning = true;
|
m_isRunning = true;
|
||||||
|
|
||||||
float positions[] = { // vertex for a triangle
|
float positions[] = {
|
||||||
|
// vertex for a triangle
|
||||||
// x,y
|
// x,y
|
||||||
-0.5f, -0.5f, // 0
|
-0.5f, -0.5f, // 0
|
||||||
0.5f, -0.5f, // 1
|
0.5f, -0.5f, // 1
|
||||||
@ -133,10 +85,7 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
-0.5f, 0.5f // 3
|
-0.5f, 0.5f // 3
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int indices[] = {
|
unsigned int indices[] = {0, 1, 2, 2, 3, 0};
|
||||||
0, 1, 2,
|
|
||||||
2, 3, 0
|
|
||||||
};
|
|
||||||
m_VA = new VertexArray();
|
m_VA = new VertexArray();
|
||||||
m_VB = new VertexBuffer(positions, 4 * 2 * sizeof(float));
|
m_VB = new VertexBuffer(positions, 4 * 2 * sizeof(float));
|
||||||
m_IB = new IndexBuffer(indices, 6);
|
m_IB = new IndexBuffer(indices, 6);
|
||||||
@ -146,31 +95,12 @@ SdlWindow::SdlWindow(const char* title, int width, int height)
|
|||||||
|
|
||||||
m_VA->AddBuffer(*m_VB, layout);
|
m_VA->AddBuffer(*m_VB, layout);
|
||||||
|
|
||||||
ShaderProgramSource source = parseShader("res/shaders/Basic.shader");
|
m_Shader = new Shader("res/shaders/Basic.shader");
|
||||||
|
m_Shader->Bind();
|
||||||
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() {
|
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) {
|
||||||
SDL_DestroyRenderer(m_renderer);
|
SDL_DestroyRenderer(m_renderer);
|
||||||
m_renderer = nullptr;
|
m_renderer = nullptr;
|
||||||
@ -186,11 +116,8 @@ SdlWindow::~SdlWindow() {
|
|||||||
SDL_DestroyWindow(m_window);
|
SDL_DestroyWindow(m_window);
|
||||||
m_window = nullptr;
|
m_window = nullptr;
|
||||||
}
|
}
|
||||||
if (m_shader) {
|
////TODO
|
||||||
glDeleteProgram(m_shader);
|
// some point check everything is being deleted
|
||||||
m_shader = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -201,7 +128,6 @@ void SdlWindow::run() {
|
|||||||
update();
|
update();
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
GLCall(glDeleteProgram(m_shader));
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
void SdlWindow::processEvents() {
|
void SdlWindow::processEvents() {
|
||||||
@ -224,8 +150,7 @@ SDL_Event event;
|
|||||||
std::cout << "Bye!" << std::endl;
|
std::cout << "Bye!" << std::endl;
|
||||||
m_isRunning = false; // exit application
|
m_isRunning = false; // exit application
|
||||||
}
|
}
|
||||||
}
|
} else if (event.type == SDL_WINDOWEVENT) {
|
||||||
else if (event.type == SDL_WINDOWEVENT) {
|
|
||||||
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||||
// SDL gives the new width/height in event.window.data1/data2
|
// SDL gives the new width/height in event.window.data1/data2
|
||||||
int newWidth = event.window.data1;
|
int newWidth = event.window.data1;
|
||||||
@ -266,17 +191,15 @@ void SdlWindow::render() {
|
|||||||
//
|
//
|
||||||
GLCall(glClear(GL_COLOR_BUFFER_BIT));
|
GLCall(glClear(GL_COLOR_BUFFER_BIT));
|
||||||
|
|
||||||
GLCall(glUseProgram(m_shader));
|
m_Shader->Bind();
|
||||||
std::cout << "m_shader: " << m_shader << std::endl;
|
m_Shader->SetUniform4f("u_Color", r, 0.3, 0.8, 1.0);
|
||||||
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_VA->Bind();
|
||||||
m_IB->Bind();
|
m_IB->Bind();
|
||||||
// TODO: Draw with OpenGL here (shaders, triangles, etc.)
|
// TODO: Draw with OpenGL here (shaders, triangles, etc.)
|
||||||
// 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);
|
||||||
@ -304,94 +227,3 @@ 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
|
|
||||||
GLCall(glShaderSource(id, 1, &src, nullptr));
|
|
||||||
GLCall(glCompileShader(id));
|
|
||||||
//TODO: error handling
|
|
||||||
int result;
|
|
||||||
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
|
|
||||||
if (result == GL_FALSE) {
|
|
||||||
int length;
|
|
||||||
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
|
|
||||||
char* message = (char*)alloca(length * sizeof(char)); //do i need to deallocate this??
|
|
||||||
GLCall(glGetShaderInfoLog(id, length, &length, message));
|
|
||||||
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex":"fragment") << " shader" << std::endl; // print out what type of shader it is
|
|
||||||
std::cout << message << std::endl;
|
|
||||||
GLCall(glDeleteShader(id));
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return id;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int SdlWindow::createShader(const std::string& vertexShader, const std::string& fragmentShader) {
|
|
||||||
GLCall(unsigned int program = glCreateProgram());
|
|
||||||
unsigned int vs = compileShader(GL_VERTEX_SHADER, vertexShader);
|
|
||||||
unsigned int fs = compileShader(GL_FRAGMENT_SHADER, fragmentShader);
|
|
||||||
GLCall(glAttachShader(program, vs));
|
|
||||||
GLCall(glAttachShader(program, fs));
|
|
||||||
|
|
||||||
GLCall(glLinkProgram(program));
|
|
||||||
GLCall(glValidateProgram(program));
|
|
||||||
|
|
||||||
GLCall(glDeleteShader(vs));
|
|
||||||
GLCall(glDeleteShader(fs));
|
|
||||||
return program;
|
|
||||||
|
|
||||||
}
|
|
||||||
SdlWindow::ShaderProgramSource SdlWindow::parseShader(const std::string& filepath) {
|
|
||||||
//can be changed to c standard which is a bit faster
|
|
||||||
std::ifstream stream(filepath);
|
|
||||||
if (!stream.is_open()) {
|
|
||||||
std::cerr << "parseShader ERROR: Could not open file " << filepath << std::endl;
|
|
||||||
// Return empty (or handle however you prefer)
|
|
||||||
return {"", ""};
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ShaderType {
|
|
||||||
NONE = -1, VERTEX = 0, FRAGMENT = 1
|
|
||||||
};
|
|
||||||
std::string line;
|
|
||||||
std::stringstream ss[2]; //vertex - fragment
|
|
||||||
ShaderType type = ShaderType::NONE;
|
|
||||||
|
|
||||||
while (getline(stream, line)) {
|
|
||||||
if (line.find("#shader") != std::string::npos) {
|
|
||||||
if (line.find("vertex") != std::string::npos) {
|
|
||||||
type = ShaderType::VERTEX;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (line.find("fragment") != std::string::npos) {
|
|
||||||
type = ShaderType::FRAGMENT;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ss[(int)type] << line << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {ss[0].str(), ss[1].str() };
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SdlWindow::GLClearError() {
|
|
||||||
while (glGetError() != GL_NO_ERROR);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SdlWindow::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
30
src/sdl.hpp
30
src/sdl.hpp
@ -9,10 +9,11 @@
|
|||||||
#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 <string>
|
|
||||||
#include "IndexBuffer.h"
|
#include "IndexBuffer.h"
|
||||||
#include "VertexBufferLayout.h"
|
#include "Shader.h"
|
||||||
#include "VertexArray.h"
|
#include "VertexArray.h"
|
||||||
|
#include "VertexBufferLayout.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// Forward declaration of classes and structs if needed
|
// Forward declaration of classes and structs if needed
|
||||||
// class SomethingElse;
|
// class SomethingElse;
|
||||||
@ -27,21 +28,19 @@ public:
|
|||||||
|
|
||||||
// Run the main loop
|
// Run the main loop
|
||||||
void run();
|
void run();
|
||||||
unsigned int compileShader(unsigned int type, const std::string& source);
|
// unsigned int compileShader(unsigned int type, const std::string& source);
|
||||||
unsigned int createShader(const std::string& vetexShader, const std::string& fragmentShader);
|
// unsigned int createShader(const std::string& vetexShader, const
|
||||||
// for spliting our shaders
|
// std::string& fragmentShader);
|
||||||
|
// // for spliting our shaders
|
||||||
|
// //struct ShaderProgramSource {
|
||||||
|
// // std::string VetexSource, FragmentSource;
|
||||||
// struct ShaderProgramSource {
|
// struct ShaderProgramSource {
|
||||||
// std::string VetexSource, FragmentSource;
|
// std::string VertexSource;
|
||||||
struct ShaderProgramSource {
|
// std::string FragmentSource;
|
||||||
std::string VertexSource;
|
// };
|
||||||
std::string FragmentSource;
|
// ShaderProgramSource parseShader(const std::string& filepath);
|
||||||
};
|
|
||||||
ShaderProgramSource parseShader(const std::string& filepath);
|
|
||||||
|
|
||||||
void setFullscreen(bool fullscreen);
|
void setFullscreen(bool fullscreen);
|
||||||
void GLClearError();
|
|
||||||
bool GLLogCall();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Private data members
|
// Private data members
|
||||||
@ -57,15 +56,14 @@ private:
|
|||||||
SDL_GLContext m_glContext;
|
SDL_GLContext m_glContext;
|
||||||
float increment;
|
float increment;
|
||||||
// // temp shader stuff
|
// // temp shader stuff
|
||||||
unsigned int m_shader;
|
|
||||||
GLint m_Location;
|
GLint m_Location;
|
||||||
VertexArray *m_VA;
|
VertexArray *m_VA;
|
||||||
IndexBuffer *m_IB;
|
IndexBuffer *m_IB;
|
||||||
VertexBuffer *m_VB;
|
VertexBuffer *m_VB;
|
||||||
|
Shader *m_Shader;
|
||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
void processEvents();
|
void processEvents();
|
||||||
void update();
|
void update();
|
||||||
void render();
|
void render();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user