feat(render) Render shaders!
Implements the rendering pipeline to dispaly a 2D triangle using shaders!
This commit is contained in:
parent
7eb86f9389
commit
6b7684ba92
7
assets/shaders/simple.frag
Normal file
7
assets/shaders/simple.frag
Normal file
@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); /* Orange??!? */
|
||||
}
|
||||
7
assets/shaders/simple.vert
Normal file
7
assets/shaders/simple.vert
Normal file
@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 aPos;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
#include <GL/glew.h>
|
||||
#include <SDL3/SDL_error.h>
|
||||
/* FINE LSP!! I'll play your games!!!! */
|
||||
#include <SDL3/SDL_events.h> /* ~HJAPPY?!?!?! */
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
|
||||
#include "bettola.h"
|
||||
@ -16,7 +16,9 @@ const int SCREEN_HEIGHT = 600;
|
||||
Bettola::Bettola(void) :
|
||||
_is_running(false),
|
||||
_window(nullptr),
|
||||
_gl_context(nullptr) {}
|
||||
_gl_context(nullptr),
|
||||
_vao(0),
|
||||
_vbo(0) {}
|
||||
|
||||
Bettola::~Bettola(void) {
|
||||
if(_gl_context) {
|
||||
@ -28,6 +30,9 @@ Bettola::~Bettola(void) {
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
glDeleteVertexArrays(1, &_vao);
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
int Bettola::run(void) {
|
||||
@ -36,6 +41,13 @@ int Bettola::run(void) {
|
||||
if(!create_gl_context()) return -1;
|
||||
if(!init_glew()) return -1;
|
||||
|
||||
if(!_shader.load_from_files("assets/shaders/simple.vert",
|
||||
"assets/shaders/simple.frag")) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
setup_triangle();
|
||||
|
||||
glViewport(0,0,SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
_is_running = true;
|
||||
@ -81,6 +93,12 @@ void Bettola::update(double dt) {
|
||||
void Bettola::render(void) {
|
||||
glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
_shader.use();
|
||||
glBindVertexArray(_vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glBindVertexArray(0);
|
||||
|
||||
SDL_GL_SwapWindow(_window);
|
||||
}
|
||||
|
||||
@ -107,11 +125,13 @@ bool Bettola::create_window(void) {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
|
||||
/* Don't you dare f.ckin fail to open!!!!! */
|
||||
_window = SDL_CreateWindow("Bettola Makes No Sense!", SCREEN_WIDTH, SCREEN_HEIGHT,
|
||||
SDL_WINDOW_OPENGL);
|
||||
|
||||
if(!_window) {
|
||||
/* Don't you dare f.ckin fail to open!!!!! */
|
||||
_window = SDL_CreateWindow("Bettola Makes No Sense!", SCREEN_WIDTH, SCREEN_HEIGHT,
|
||||
SDL_WINDOW_OPENGL);
|
||||
fprintf(stderr, "Failed to create window! SDL_ERROR: %s\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -126,3 +146,26 @@ bool Bettola::create_gl_context(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bettola::setup_triangle(void) {
|
||||
float vertices[] = {
|
||||
/* Should be a triangle??!?? */
|
||||
-0.5f, -0.5f, 0.0f,
|
||||
0.5f, -0.5f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f,
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &_vao);
|
||||
glGenBuffers(1, &_vbo);
|
||||
|
||||
glBindVertexArray(_vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "graphics/shader.h"
|
||||
|
||||
class Bettola {
|
||||
public:
|
||||
Bettola(void);
|
||||
@ -18,9 +20,14 @@ private:
|
||||
bool init_glew(void);
|
||||
bool create_window(void);
|
||||
bool create_gl_context(void);
|
||||
void setup_triangle(void);
|
||||
|
||||
bool _is_running;
|
||||
|
||||
SDL_Window* _window;
|
||||
SDL_GLContext _gl_context;
|
||||
|
||||
Shader _shader;
|
||||
unsigned int _vao;
|
||||
unsigned int _vbo;
|
||||
};
|
||||
|
||||
96
src/graphics/shader.cpp
Normal file
96
src/graphics/shader.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include <GL/glew.h>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "shader.h"
|
||||
|
||||
Shader::Shader(void) : _program_id(0) {}
|
||||
|
||||
Shader::~Shader(void) {
|
||||
if(_program_id != 0) {
|
||||
glDeleteProgram(_program_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::load_from_files(const std::string& vert_path, const std::string& frag_path) {
|
||||
std::string vert_source = read_file(vert_path);
|
||||
if(vert_source.empty()) {
|
||||
fprintf(stderr, "Failed to read vertex shader file: %s\n", vert_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string frag_source = read_file(frag_path);
|
||||
if(frag_source.empty()) {
|
||||
fprintf(stderr, "Failed to read fragment shader file: %s\n", frag_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int vert_shader_id;
|
||||
if(!compile_shader(vert_shader_id, vert_source.c_str(), GL_VERTEX_SHADER)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int frag_shader_id;
|
||||
if(!compile_shader(frag_shader_id, frag_source.c_str(), GL_FRAGMENT_SHADER)) {
|
||||
glDeleteShader(vert_shader_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
_program_id = glCreateProgram();
|
||||
glAttachShader(_program_id, vert_shader_id);
|
||||
glAttachShader(_program_id, frag_shader_id);
|
||||
glLinkProgram(_program_id);
|
||||
|
||||
int success;
|
||||
char info_log[512];
|
||||
glGetProgramiv(_program_id, GL_LINK_STATUS, &success);
|
||||
if(!success) {
|
||||
glGetProgramInfoLog(_program_id, 512, NULL, info_log);
|
||||
fprintf(stderr, "ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", info_log);
|
||||
glDeleteShader(vert_shader_id);
|
||||
glDeleteShader(frag_shader_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
glDetachShader(_program_id, vert_shader_id);
|
||||
glDetachShader(_program_id, frag_shader_id);
|
||||
glDeleteShader(vert_shader_id);
|
||||
glDeleteShader(frag_shader_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shader::use(void) {
|
||||
if(_program_id != 0) {
|
||||
glUseProgram(_program_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::compile_shader(unsigned int& shader_id, const char* shader_source, int shader_type) {
|
||||
shader_id = glCreateShader(shader_type);
|
||||
glShaderSource(shader_id, 1, &shader_source, NULL);
|
||||
glCompileShader(shader_id);
|
||||
|
||||
int success;
|
||||
char info_log[512];
|
||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if(!success) {
|
||||
glGetShaderInfoLog(shader_id, 512, NULL, info_log);
|
||||
fprintf(stderr, "ERROR::SHADER::COMPILATION\n%s\n", info_log);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Shader::read_file(const std::string& path) {
|
||||
std::ifstream file(path);
|
||||
if(!file.is_open()) {
|
||||
return "";
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
return buffer.str();
|
||||
}
|
||||
18
src/graphics/shader.h
Normal file
18
src/graphics/shader.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
Shader(void);
|
||||
~Shader(void);
|
||||
|
||||
bool load_from_files(const std::string& vert_path, const std::string& frag_path);
|
||||
void use(void);
|
||||
unsigned int get_id(void) const { return _program_id; }
|
||||
private:
|
||||
bool compile_shader(unsigned int& shader_id, const char* shader_source, int shader_type);
|
||||
|
||||
std::string read_file(const std::string& path);
|
||||
unsigned int _program_id;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user