Implemented ShaderProgramBuilder

This commit is contained in:
2025-07-27 16:13:48 -04:00
parent 94c9216225
commit 370196ef7a
6 changed files with 135 additions and 35 deletions

View File

@@ -7,3 +7,4 @@ find_package(glfw3 CONFIG REQUIRED)
find_package(glm CONFIG REQUIRED)
add_subdirectory(./source/app)
add_subdirectory(./source/shader)

View File

@@ -13,4 +13,5 @@ target_link_libraries(${PROJECT_NAME}
GLEW::GLEW
glfw
glm::glm
UglyShaderLib
)

View File

@@ -6,6 +6,7 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "ShaderProgramBuilder.hpp"
int App::main(std::vector<std::string> &args) {
auto app = App{};
@@ -57,9 +58,9 @@ App::~App() {
void App::game_loop() {
float vertices[] = {
.0f, .5f,
.5f, -.5f,
-.5f, -.5f
.0f, .5f, 1.f, 0.f, 0.f,
.5f, -.5f, 0.f, 1.f, 0.f,
-.5f, -.5f, 0.f, 0.f, 1.f
};
GLuint vbo;
@@ -70,56 +71,38 @@ void App::game_loop() {
auto vertexSource = R"glsl(
#version 150 core
in vec2 position;
void main() { gl_Position = vec4(position, 0.0, 1.0); }
in vec3 color;
out vec3 _color;
void main() { _color = color; gl_Position = vec4(position, 0.0, 1.0); }
)glsl";
GLint status;
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if(!status) {
error_callback_s(GLFW_NO_ERROR, "glShaderSource() failed");
}
auto fragmentSource = R"glsl(
#version 150 core
uniform vec3 triangleColor;
in vec3 _color;
out vec4 color;
void main() { color = vec4(triangleColor, 1.0); }
void main() { color = vec4(_color, 1.0); }
)glsl";
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if(!status) {
error_callback_s(GLFW_NO_ERROR, "glShaderSource() failed");
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
GLuint shaderProgram = ugly::ShaderProgramBuilder{}
.attachFromMemory(GL_VERTEX_SHADER, vertexSource)
.attachFromMemory(GL_FRAGMENT_SHADER, fragmentSource)
.link();
glUseProgram(shaderProgram);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);
glEnableVertexAttribArray(0);
auto start = glfwGetTime();
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));
glEnableVertexAttribArray(1);
while(!glfwWindowShouldClose(mpWindow)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
auto now = glfwGetTime();
glUniform3f(glGetUniformLocation(shaderProgram, "triangleColor"), (sin(now-start) + 1.0f) / 2.0f, 0.0f, 0.0f);
glfwSwapBuffers(mpWindow);
}
}

View File

@@ -0,0 +1,14 @@
project(UglyShaderLib)
add_library(${PROJECT_NAME}
./src/ShaderProgramBuilder.cpp
)
target_include_directories(${PROJECT_NAME}
PUBLIC ./include
PRIVATE ./src
)
target_link_libraries(${PROJECT_NAME}
GLEW::GLEW
)

View File

@@ -0,0 +1,28 @@
#pragma once
#include <stdexcept>
#include <GL/glew.h>
namespace ugly{
class ShaderProgramBuilder {
public:
class Error: public std::runtime_error{
public:
using std::runtime_error::runtime_error;
};
public:
ShaderProgramBuilder();
~ShaderProgramBuilder();
void reset();
ShaderProgramBuilder &attachFromMemory(GLenum type, const GLchar *string, GLint length = 0);
ShaderProgramBuilder &attachFromFile(GLenum type, const char *filename);
GLuint link();
private:
GLuint mProgram;
};
}

View File

@@ -0,0 +1,73 @@
#include "ShaderProgramBuilder.hpp"
#include <fstream>
#include <iostream>
#include <sstream>
#include <utility>
ugly::ShaderProgramBuilder::ShaderProgramBuilder():
mProgram{glCreateProgram()} {
}
ugly::ShaderProgramBuilder::~ShaderProgramBuilder() {
if(mProgram != 0) {
glDeleteProgram(mProgram);
}
}
void ugly::ShaderProgramBuilder::reset() {
using namespace std;
swap(*this, ShaderProgramBuilder{});
}
ugly::ShaderProgramBuilder &ugly::ShaderProgramBuilder::attachFromMemory(GLenum type, const GLchar *string, GLint length) {
auto shader = glCreateShader(type);
glShaderSource(shader, 1, &string, length != 0 ? &length : NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status != GL_TRUE) {
char buf[512];
glGetShaderInfoLog(shader, 512, NULL, buf);
glDeleteShader(shader);
std::cerr << "Failed to compile shader:\n\t" << buf << '\n';
throw Error{"shader failed to compile"};
}
glAttachShader(mProgram, shader);
glDeleteShader(shader);
return *this;
}
ugly::ShaderProgramBuilder &ugly::ShaderProgramBuilder::attachFromFile(GLenum type, const char *filename) {
auto file = std::ifstream{filename};
file.exceptions(std::ios_base::badbit);
std::ostringstream ss;
ss << file.rdbuf();
return attachFromMemory(type, ss.str().c_str());
}
GLuint ugly::ShaderProgramBuilder::link() {
glLinkProgram(mProgram);
GLint status;
glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
if(status != GL_TRUE) {
char buf[512];
glGetProgramInfoLog(mProgram, 512, NULL, buf);
std::cerr << "Failed to link program:\n\t" << buf << '\n';
throw Error{"program failed to link"};
}
auto result = mProgram;
mProgram = 0;
reset();
return result;
}