Add Attributes to Shader.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m40s
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m40s
This commit is contained in:
5
assets/shader_programs/test_fragment.glsl
Normal file
5
assets/shader_programs/test_fragment.glsl
Normal file
@@ -0,0 +1,5 @@
|
||||
#version 120
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(1, 1, 1, 1);
|
||||
}
|
7
assets/shader_programs/test_vertex.glsl
Normal file
7
assets/shader_programs/test_vertex.glsl
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 120
|
||||
|
||||
attribute vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position.x, position.y, 1.0, 1.0);
|
||||
}
|
@@ -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();
|
||||
};
|
4
main.cpp
4
main.cpp
@@ -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};
|
||||
|
@@ -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(),
|
||||
|
@@ -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*)¤t_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*)¤t_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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user