Add Attributes to Shader.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m40s

This commit is contained in:
2024-08-24 23:27:10 -04:00
parent f96a3851a1
commit 04a4cbd54d
6 changed files with 280 additions and 32 deletions

View File

@@ -0,0 +1,5 @@
#version 120
void main() {
gl_FragColor = vec4(1, 1, 1, 1);
}

View File

@@ -0,0 +1,7 @@
#version 120
attribute vec2 position;
void main() {
gl_Position = vec4(position.x, position.y, 1.0, 1.0);
}

View File

@@ -15,9 +15,9 @@ namespace JGL {
COMBINED = 2,
};
//You could definitely do this with Typename T.
//Idk it increases the likelihood for mistakes.
class Uniform;
// You could definitely do this with Typename T.
// Idk it increases the likelihood for mistakes.
class ShaderValue;
class Uniform_Float;
class Uniform_Int;
@@ -30,61 +30,81 @@ namespace JGL {
class Uniform_Matrix2x2;
class Uniform_Matrix3x3;
class Uniform_Matrix4x4;
class Attribute_Vector2;
class Attribute_Vector3;
class Attribute_Vector4;
}
class JGL::Uniform {
class JGL::ShaderValue {
public:
std::string name;
GLint location = 0;
GLint location = -1;
};
class JGL::Uniform_Float : public Uniform {
class JGL::Uniform_Float : public ShaderValue {
public:
float value = 0;
};
class JGL::Uniform_Int : public Uniform {
class JGL::Uniform_Int : public ShaderValue {
public:
int value = 0;
};
class JGL::Uniform_Bool : public Uniform {
class JGL::Uniform_Bool : public ShaderValue {
public:
bool value = false;
};
class JGL::Uniform_Vector2 : public Uniform {
class JGL::Uniform_Vector2 : public ShaderValue {
public:
Vector2 value;
};
class JGL::Uniform_Vector3 : public Uniform {
class JGL::Uniform_Vector3 : public ShaderValue {
public:
Vector3 value;
};
class JGL::Uniform_Vector4 : public Uniform {
class JGL::Uniform_Vector4 : public ShaderValue {
public:
Vector4 value;
};
class JGL::Uniform_Matrix2x2 : public Uniform {
class JGL::Uniform_Matrix2x2 : public ShaderValue {
public:
Matrix2x2 value;
};
class JGL::Uniform_Matrix3x3 : public Uniform {
class JGL::Uniform_Matrix3x3 : public ShaderValue {
public:
Matrix3x3 value;
};
class JGL::Uniform_Matrix4x4 : public Uniform {
class JGL::Uniform_Matrix4x4 : public ShaderValue {
public:
Matrix4x4 value;
};
//TODO attributes.
class JGL::Attribute_Vector2 : public ShaderValue {
public:
std::vector<Vector2> value;
};
class JGL::Attribute_Vector3 : public ShaderValue {
public:
std::vector<Vector3> value;
};
class JGL::Attribute_Vector4 : public ShaderValue {
public:
std::vector<Vector4> value;
};
class JGL::Shader {
private:
///Shader program.
@@ -111,6 +131,12 @@ private:
std::vector<Uniform_Matrix3x3> matrix3x3_uniforms;
std::vector<Uniform_Matrix4x4> matrix4x4_uniforms;
/// Vertex Attributes are similar to Uniforms, but are per Vertex instead of per draw call.
/// Effectively an array list of elements such as position, normal, color, bone weights etc etc.
std::vector<Attribute_Vector2> vector2_attributes;
std::vector<Attribute_Vector3> vector3_attributes;
std::vector<Attribute_Vector4> vector4_attributes;
/// Varyings allow you to pass values from the Vertex pass to the Fragment pass.
/// They are defined in the shader source only.
private:
@@ -120,6 +146,7 @@ private:
public:
[[nodiscard]] GLuint GetGLShaderProgramHandle() const;
[[nodiscard]] ShaderType GetShaderType() const;
void ListUniforms();
public:
void SetUF(const std::string& uniform_name, float value);
void SetUI(const std::string& uniform_name, int value);
@@ -135,6 +162,13 @@ public:
void SetUMat3(const std::string& uniform_name, const Matrix3x3& value);
void SetUMat4(const std::string& uniform_name, const Matrix4x4& value);
void SetAV2(const std::string& attribute_name, const std::vector<Vector2>& value);
void SetAV2(const std::string& attribute_name, const Vector2* value, size_t size);
void SetAV3(const std::string& attribute_name, const std::vector<Vector3>& value);
void SetAV3(const std::string& attribute_name, const Vector3* value, size_t size);
void SetAV4(const std::string& attribute_name, const std::vector<Vector4>& value);
void SetAV4(const std::string& attribute_name, const Vector4* value, size_t size);
/// Zeroes out all uniforms locally.
void ResetLocalUniforms();
/// Zeroes out all uniforms locally and on the GPU.
@@ -142,9 +176,16 @@ public:
/// DMA the uniforms into the Shader Program.
void SubmitUniforms(bool reset_uniforms_in_local_store = true);
/// Sets the memory location at which the Shader Program will look for the Attribute list.
void SubmitAttributes();
/// Un-sets the memory location in the Shader Program and clears locally.
void ResetAttributes();
public:
Shader(const char* vertex_shader_file, const char* fragment_shader_file);
Shader(const std::string& vertex_shader_text, const std::string& fragment_shader_text);
void Erase() const;
void Erase();
Shader() = default;
~Shader();
};

View File

@@ -5,6 +5,7 @@
#include <chrono>
#include <J3ML/LinearAlgebra/Vector2.hpp>
#include <JGL/types/Font.h>
#include <JGL/types/Shader.h>
#include <JGL/Logger.h>
#include <ReTexture/Texture.h>
@@ -13,6 +14,7 @@ using namespace JGL;
JGL::Font FreeSans;
JGL::Font Jupiteroid;
JGL::Shader test_shader;
class Gizmo
{
@@ -135,7 +137,9 @@ public:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
test_shader = Shader("assets/shader_programs/test_vertex.glsl", "assets/shader_programs/test_fragment.glsl");
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::BILINEAR);
test_shader.SetAV2("position", {{2,2}});
}
Vector3 textAngle = {0,0,0};

View File

@@ -37,8 +37,7 @@ namespace JGL {
}
void J2D::UseShaderProgram(Shader* shader) {
j2d_shader_program = shader;
glUseProgram(shader->GetGLShaderProgramHandle());
J2D::UseShaderProgram(*shader);
}
void J2D::UseFixedFunction() {
@@ -390,9 +389,12 @@ namespace JGL {
void J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) {
if (!inJ2D)
jlog::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {A, B};
if (J2D::IsUsingShaderProgram()) {
return;
}
glLineWidth(thickness);
glColor4f(color.RedChannelNormalized(),
color.GreenChannelNormalized(),

View File

@@ -4,7 +4,8 @@
#include <fstream>
#include <sstream>
#include <Color3.hpp>
#include "Color4.hpp"
#include <Color4.hpp>
#include <jlog/Logger.hpp>
void checkCompilationError(GLuint shader) {
GLint success;
@@ -41,10 +42,12 @@ JGL::ShaderType JGL::Shader::GetShaderType() const {
return shader_type;
}
void JGL::Shader::Erase() const {
void JGL::Shader::Erase() {
if (shader_program_handle == 0)
throw std::runtime_error("JGL::Shader::Erase: Deleted the default shader?");
ResetUniforms();
ResetAttributes();
glDeleteProgram(shader_program_handle);
}
@@ -141,20 +144,47 @@ void JGL::Shader::link() {
else if (type == GL_FLOAT_MAT4)
matrix4x4_uniforms.push_back(Uniform_Matrix4x4({uniform_name, location}, {}));
}
GLint num_attributes;
glGetProgramiv(shader_program_handle, GL_ACTIVE_ATTRIBUTES, &num_attributes);
for (GLint i = 0; i < num_attributes; ++i) {
char attribute_name[256];
GLsizei length;
GLint size;
GLenum type;
glGetActiveAttrib(shader_program_handle, i, sizeof(attribute_name), &length, &size, &type, attribute_name);
GLint location = glGetAttribLocation(shader_program_handle, attribute_name);
if (type == GL_FLOAT_VEC2)
vector2_attributes.push_back(Attribute_Vector2({attribute_name, location}, {}));
else if (type == GL_FLOAT_VEC3)
vector3_attributes.push_back(Attribute_Vector3({attribute_name, location}, {}));
else if (type == GL_FLOAT_VEC4)
vector4_attributes.push_back(Attribute_Vector4({attribute_name, location}, {}));
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
}
JGL::Shader::Shader(const char* vertex_shader_file, const char* fragment_shader_file) {
shader_type = ShaderType::COMBINED;
jlog::Debug("Compiling shader program from files: " + std::string(vertex_shader_file) + ", " + std::string(fragment_shader_file) + "...");
load(vertex_shader_file, ShaderType::VERTEX);
load(fragment_shader_file, ShaderType::FRAGMENT);
link();
jlog::Debug("Shader compilation success.");
}
JGL::Shader::Shader(const std::string& vertex_shader_text, const std::string& fragment_shader_text) {
shader_type = ShaderType::COMBINED;
jlog::Debug("Compiling shader program from strings...");
load(vertex_shader_text, ShaderType::VERTEX);
load(fragment_shader_text, ShaderType::FRAGMENT);
link();
jlog::Debug("Shader compilation success.");
}
void JGL::Shader::ResetLocalUniforms() {
@@ -198,27 +228,30 @@ void JGL::Shader::SetUF(const std::string& uniform_name, float value) {
for (auto& u : float_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUI(const std::string& uniform_name, int value) {
for (auto& u : int_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUB(const std::string& uniform_name, bool value) {
for (auto& u : bool_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
@@ -226,72 +259,147 @@ void JGL::Shader::SetUV2(const std::string& uniform_name, const Vector2& value)
for (auto& u : vector2_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUV3(const std::string& uniform_name, const Vector3& value) {
for (auto& u : vector3_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUV3(const std::string& uniform_name, const Color3& value) {
for (auto& u : vector3_uniforms) {
if (u.name == uniform_name) {
u.value = {value.RedChannelNormalized(), value.BlueChannelNormalized(), value.RedChannelNormalized()};
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUV4(const std::string& uniform_name, const Vector4& value) {
for (auto& u : vector4_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUV4(const std::string& uniform_name, const Color4& value) {
for (auto& u : vector4_uniforms) {
if (u.name == uniform_name) {
u.value = {value.RedChannelNormalized(), value.BlueChannelNormalized(), value.RedChannelNormalized(), value.AlphaChannelNormalized()};
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUMat2(const std::string& uniform_name, const Matrix2x2& value) {
for (auto& u : matrix2x2_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUMat3(const std::string& uniform_name, const Matrix3x3& value) {
for (auto& u : matrix3x3_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetUMat4(const std::string& uniform_name, const Matrix4x4& value) {
for (auto& u : matrix4x4_uniforms) {
if (u.name == uniform_name) {
u.value = value;
break;
return;
}
}
jlog::Error("Setting uniform " + uniform_name + " but there is no uniform by that name?");
}
void JGL::Shader::SetAV2(const std::string& attribute_name, const std::vector<Vector2>& value) {
for (auto& a : vector2_attributes) {
if (a.name == attribute_name) {
a.value = value;
return;
}
}
jlog::Error("Setting attribute " + attribute_name + " but there is no attribute by that name?");
}
void JGL::Shader::SetAV2(const std::string& attribute_name, const Vector2* value, size_t size) {
for (auto& a : vector2_attributes) {
if (a.name == attribute_name) {
// Jesus, Memory bandwidth go brrrrrrrr.
// Guess that's what I get for wanting Fixed-Function-esque Shader Programs. - Redacted
a.value.resize(size);
// Can't use memcpy because "Vec2 - Vec4 are not trivially copyable?"
std::copy(value, value + size, a.value.begin());
return;
}
}
jlog::Error("Setting attribute " + attribute_name + " but there is no attribute by that name?");
}
void JGL::Shader::SetAV3(const std::string& attribute_name, const std::vector<Vector3>& value) {
for (auto& a : vector3_attributes) {
if (a.name == attribute_name) {
a.value = value;
return;
}
}
jlog::Error("Setting attribute " + attribute_name + " but there is no attribute by that name?");
}
void JGL::Shader::SetAV3(const std::string& attribute_name, const Vector3* value, size_t size) {
for (auto& a : vector3_attributes) {
if (a.name == attribute_name) {
a.value.resize(size);
std::copy(value, value + size, a.value.begin());
return;
}
}
jlog::Error("Setting attribute " + attribute_name + " but there is no attribute by that name?");
}
void JGL::Shader::SetAV4(const std::string& attribute_name, const std::vector<Vector4>& value) {
for (auto& a : vector4_attributes) {
if (a.name == attribute_name) {
a.value = value;
return;
}
}
jlog::Error("Setting attribute " + attribute_name + " but there is no attribute by that name?");
}
void JGL::Shader::SetAV4(const std::string& attribute_name, const Vector4* value, size_t size) {
for (auto& a : vector4_attributes) {
if (a.name == attribute_name) {
a.value.resize(size);
std::copy(value, value + size, a.value.begin());
return;
}
}
jlog::Error("Setting attribute " + attribute_name + " but there is no attribute by that name?");
}
void JGL::Shader::SubmitUniforms(bool clear_uniforms_from_local_store) {
@@ -338,6 +446,87 @@ void JGL::Shader::SubmitUniforms(bool clear_uniforms_from_local_store) {
glUseProgram(current_program);
}
void JGL::Shader::ListUniforms() {
for (const auto& u : float_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : int_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : bool_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : vector2_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : vector3_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : vector4_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : matrix2x2_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : matrix3x3_uniforms)
std::cout << u.name << std::endl;
for (const auto& u : matrix4x4_uniforms)
std::cout << u.name << std::endl;
}
void JGL::Shader::SubmitAttributes() {
GLuint current_program;
glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&current_program);
if (current_program != shader_program_handle)
glUseProgram(shader_program_handle);
for (const auto& a : vector2_attributes)
if (a.location != -1)
glEnableVertexAttribArray(a.location),
glVertexAttribPointer(a.location, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), a.value.data());
for (const auto& a : vector3_attributes)
if (a.location != -1)
glEnableVertexAttribArray(a.location),
glVertexAttribPointer(a.location, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), a.value.data());
for (const auto& a : vector4_attributes)
if (a.location != -1)
glEnableVertexAttribArray(a.location),
glVertexAttribPointer(a.location, 4, GL_FLOAT, GL_FALSE, sizeof(Vector4), a.value.data());
if (current_program != shader_program_handle)
glUseProgram(current_program);
}
void JGL::Shader::ResetAttributes() {
GLuint current_program;
glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&current_program);
for (auto& a : vector2_attributes)
if (a.location != -1)
glDisableVertexAttribArray(a.location),
a.value.resize(0),
a.value.shrink_to_fit();
for (auto& a : vector3_attributes)
if (a.location != -1)
glDisableVertexAttribArray(a.location),
a.value.resize(0),
a.value.shrink_to_fit();
for (auto& a : vector4_attributes)
if (a.location != -1)
glDisableVertexAttribArray(a.location),
a.value.resize(0),
a.value.shrink_to_fit();
if (current_program != shader_program_handle)
glUseProgram(current_program);
}