У меня есть блок кода, который должен помочь мне использовать несколько шейдеров и связанных с ними VAO/VBO.
#pragma once
#include"shader/_Shader.h"
#include"includes.h"
namespace SHADER
{
enum class ShaderID
{
SH_00 = 0,
SH_01 = 1, SH_02,..., SH_50,
};
#define MAX_SHADER_ID 50
class Shader_Binder
{
private:
struct Data
{
ShaderID id;
Shader m_shader;
std::vector m_VAOs;
std::vector m_VBOs;
};
ShaderID m_CurrentShader = ShaderID::SH_00; // Track current shader
unsigned int m_CurrentVAO = 0; // Track current VAO
unsigned int m_CurrentVBO = 0; // Track current VBO
std::unordered_mapm_Data;
public:
// Static method to get the single instance of the class
static Shader_Binder& getInstance()
{
static Shader_Binder instance; // Guaranteed to be destroyed, instantiated on first use
return instance;
}
// Deleted copy constructor and assignment operator to prevent copying
Shader_Binder(const Shader_Binder&) = delete;
Shader_Binder& operator=(const Shader_Binder&) = delete;
/* Creates a new shader, binds it and returns a ID */
ShaderID CreateNewShader(const std::string vShader = "", const std::string fShader = "", const std::string gShader = "");
/* Binds the shader passed in and returns a ID */
ShaderID CreateNewShader(Shader& shader);
/* Binds the shader, VAO and VBO*/
void bind(ShaderID id = ShaderID::SH_00, int vaoid = -1, int vboid = -1);
/* Unbinds the shader, VAO and VBO*/
void unbind(ShaderID id = ShaderID::SH_00, int vaoid = -1, int vboid = -1);
/* Creates a new VAO on the given shader id, binds it and returns the value of the created VAO. */
unsigned int CreateNewVAO(ShaderID id);
/* Creates a new VBO on the given shader id, binds it and returns the value of the created VBO. */
unsigned int CreateNewVBO(ShaderID id);
/* Returns a pointer to the shader object relative to the id passed in*/
Shader* getShader(ShaderID id);
/* Sets the vertex attributes based on the id of the shader passed
* vaoIndex is set to 0 by default ,
* considering there are no multiple vao's created for the same shader */
void setVertexAttribs(ShaderID id, unsigned int Gl_location_index, int size,
unsigned int type, GLboolean normalized, int stride, const void* pointer,
unsigned int vaoIndex = 0);
/*
* Assumes GL_DYNAMIC_DRAW as the default data usage.
* Requires the size of the buffer to be sent, even if the usage is GL_DYNAMIC_DRAW.
* Assumes the required shaders and others are bound before using.
* Set the usage to GL_STATIC_DRAW if the data is to be static and other params are passed.
* Assumes GL_ARRAY_BUFFER as the default target to be used
*/
void setBufferData(GLenum usage = GL_DYNAMIC_DRAW, GLsizeiptr size = 0,
const void* data = nullptr, GLenum target = GL_ARRAY_BUFFER);
/*
* Updates the buffer data if the usage was GL_DYNAMIC_DRAW.
* Assumes the required shaders and others are bound before using.
* Uses glBufferSubData() for the task
* Considers GL_ARRAY_BUFFER as the default target
*/
void UpdateBufferData(GLintptr offset, GLsizeiptr size, const void* data, GLenum target = GL_ARRAY_BUFFER);
/*unbinds the last used (or whichever currently bound) shader and vao and vbo */
void reset();
private:
bool isIdUsed(ShaderID id);
Shader_Binder() {}
~Shader_Binder() {}
};
}
typedef SHADER::ShaderID ShaderID;
static SHADER::Shader_Binder& Binder = SHADER::Shader_Binder::getInstance();
Единственная проблема, с которой я столкнулся, - это во время Shader* getShader(ShaderID id);
чье определение
Shader* Shader_Binder::getShader(ShaderID id)
{
return &m_Data.at(id).m_shader;
}
и все, что он должен сделать, это дать мне ссылку на объект шейдера с идентификатором шейдера, который я сохранил на карте.
Я попробовал вызвать функцию с именем Setuniform3f() это была одна из функций-членов внутри объекта шейдера, и, видимо, она не работает, и я получаю GL_INVALID_OPERATION.
Я попробовал сделать это вне функции, и это сработало: p>
Binder.getShader(shaderID)->Setuniform3f("uColor", color.r, color.g, color.b); //this doesn't work
auto x=glGetUniformLocation(Binder.getShader(shaderID)->Program_id, "uColor");
glUniform3f(x, color.r, color.g, color.b); // this works
Я не понимаю, почему это происходит. Я пытался удалить указатель из функции или использовать & в качестве типа возвращаемого значения, но это все равно не помогает.
РЕДАКТИРОВАТЬ:Это определения Setuniform3f, а также привязки и функция, в которой я их вызывал:
void Opengl_Draw::Draw_line(glm::vec3 from, glm::vec3 to, glm::vec4 color)
{
Binder.bind(shaderID, vao, vbo);
auto id = Binder.getShader(shaderID)->Program_id;
float data[] = {
from.x,from.y,from.z,
to.x,to.y,to.z
};
Binder.UpdateBufferData(0, sizeof(data), data);
//Binder.getShader(shaderID).get().Setuniform3f("uColor", color.r, color.g, color.b);
auto x=glGetUniformLocation(Binder.getShader(shaderID)->Program_id, "uColor");
glUniform3f(x, 1.0f, 0.0f, 1.0f);
glDrawArrays(GL_LINES, 0, 2);
Binder.unbind(shaderID, vao, vbo);
}
void Shader_Binder::bind(ShaderID id, int vaoid, int vboid)
{
if (!isIdUsed(id)) return;
// Bind the shader and update tracking
if (m_CurrentShader != id)
{
m_Data[id].m_shader.Bind();
m_CurrentShader = id;
}
else
{
MessageBoxA(NULL, "Shader id not found or is 0 ... escaping the binding function... ", "Binding error", MB_OK);
return;
}
// Bind the VAO and update tracking if needed
if (vaoid != -1 && m_CurrentVAO != vaoid)
{
GL_CHECK(glBindVertexArray(vaoid));
m_CurrentVAO = vaoid;
}
// Bind the VBO and update tracking if needed
if (vboid != -1 && m_CurrentVBO != vboid)
{
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vboid));
m_CurrentVBO = vboid;
}
}
void Shader_Binder::unbind(ShaderID id, int vaoid, int vboid)
{
if (!isIdUsed(id)) return;
// Unbind the VAO only if it's the current one
if (vaoid != -1 && m_CurrentVAO == vaoid)
{
GL_CHECK(glBindVertexArray(0));
m_CurrentVAO = 0;
}
// Unbind the VBO only if it's the current one
if (vboid != -1 && m_CurrentVBO == vboid)
{
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
m_CurrentVBO = 0;
}
// Unbind the shader only if it's actually bound
if (m_CurrentShader == id)
{
m_Data[id].m_shader.Unbind();
m_CurrentShader = ShaderID::SH_00; // Or some default "unbound" state
}
}
// GL_CHECK is just a macro I used for error checking, and this, I think is not related to the question
void Shader::Bind() const
{
glUseProgram(Program_id);
}
void Shader::Unbind() const
{
glUseProgram(0);
}
void Shader::Setuniform3f(const std::string& name, float v1, float v2, float v3)
{
glUniform3f(GetUniformLocation(name), v1, v2, v3);
}
unsigned int Shader::GetUniformLocation(const std::string& name)
{
Bind();
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
{
return m_UniformLocationCache[name];
}
int location = glGetUniformLocation(Program_id, name.c_str());
if (location == -1)
{
MessageBoxA(NULL, std::string("Warning! Uniform " + name + " is unused or not found or does no exist!").c_str(), "UNIFORM LOCATION WARNING!!!", MB_OK);
}
else
m_UniformLocationCache[name] = location;
Unbind();
return location;
}
// I just did a caching system with a small error checking here, nothing special.
Подробнее здесь: https://stackoverflow.com/questions/790 ... engl-class
Возврат объекта класса шейдера для использования универсальной функции в классе opengl дает GL_INVALID_OPERATION. ⇐ C++
Программы на C++. Форум разработчиков
1728840567
Anonymous
У меня есть блок кода, который должен помочь мне использовать несколько шейдеров и связанных с ними VAO/VBO.
#pragma once
#include"shader/_Shader.h"
#include"includes.h"
namespace SHADER
{
enum class ShaderID
{
SH_00 = 0,
SH_01 = 1, SH_02,..., SH_50,
};
#define MAX_SHADER_ID 50
class Shader_Binder
{
private:
struct Data
{
ShaderID id;
Shader m_shader;
std::vector m_VAOs;
std::vector m_VBOs;
};
ShaderID m_CurrentShader = ShaderID::SH_00; // Track current shader
unsigned int m_CurrentVAO = 0; // Track current VAO
unsigned int m_CurrentVBO = 0; // Track current VBO
std::unordered_mapm_Data;
public:
// Static method to get the single instance of the class
static Shader_Binder& getInstance()
{
static Shader_Binder instance; // Guaranteed to be destroyed, instantiated on first use
return instance;
}
// Deleted copy constructor and assignment operator to prevent copying
Shader_Binder(const Shader_Binder&) = delete;
Shader_Binder& operator=(const Shader_Binder&) = delete;
/* Creates a new shader, binds it and returns a ID */
ShaderID CreateNewShader(const std::string vShader = "", const std::string fShader = "", const std::string gShader = "");
/* Binds the shader passed in and returns a ID */
ShaderID CreateNewShader(Shader& shader);
/* Binds the shader, VAO and VBO*/
void bind(ShaderID id = ShaderID::SH_00, int vaoid = -1, int vboid = -1);
/* Unbinds the shader, VAO and VBO*/
void unbind(ShaderID id = ShaderID::SH_00, int vaoid = -1, int vboid = -1);
/* Creates a new VAO on the given shader id, binds it and returns the value of the created VAO. */
unsigned int CreateNewVAO(ShaderID id);
/* Creates a new VBO on the given shader id, binds it and returns the value of the created VBO. */
unsigned int CreateNewVBO(ShaderID id);
/* Returns a pointer to the shader object relative to the id passed in*/
Shader* getShader(ShaderID id);
/* Sets the vertex attributes based on the id of the shader passed
* vaoIndex is set to 0 by default ,
* considering there are no multiple vao's created for the same shader */
void setVertexAttribs(ShaderID id, unsigned int Gl_location_index, int size,
unsigned int type, GLboolean normalized, int stride, const void* pointer,
unsigned int vaoIndex = 0);
/*
* Assumes GL_DYNAMIC_DRAW as the default data usage.
* Requires the size of the buffer to be sent, even if the usage is GL_DYNAMIC_DRAW.
* Assumes the required shaders and others are bound before using.
* Set the usage to GL_STATIC_DRAW if the data is to be static and other params are passed.
* Assumes GL_ARRAY_BUFFER as the default target to be used
*/
void setBufferData(GLenum usage = GL_DYNAMIC_DRAW, GLsizeiptr size = 0,
const void* data = nullptr, GLenum target = GL_ARRAY_BUFFER);
/*
* Updates the buffer data if the usage was GL_DYNAMIC_DRAW.
* Assumes the required shaders and others are bound before using.
* Uses glBufferSubData() for the task
* Considers GL_ARRAY_BUFFER as the default target
*/
void UpdateBufferData(GLintptr offset, GLsizeiptr size, const void* data, GLenum target = GL_ARRAY_BUFFER);
/*unbinds the last used (or whichever currently bound) shader and vao and vbo */
void reset();
private:
bool isIdUsed(ShaderID id);
Shader_Binder() {}
~Shader_Binder() {}
};
}
typedef SHADER::ShaderID ShaderID;
static SHADER::Shader_Binder& Binder = SHADER::Shader_Binder::getInstance();
Единственная проблема, с которой я столкнулся, - это во время Shader* getShader(ShaderID id);
чье определение
Shader* Shader_Binder::getShader(ShaderID id)
{
return &m_Data.at(id).m_shader;
}
и все, что он должен сделать, это дать мне ссылку на объект шейдера с идентификатором шейдера, который я сохранил на карте.
Я попробовал вызвать функцию с именем Setuniform3f() это была одна из функций-членов внутри объекта шейдера, и, видимо, она не работает, и я получаю GL_INVALID_OPERATION.
Я попробовал сделать это вне функции, и это сработало: p>
Binder.getShader(shaderID)->Setuniform3f("uColor", color.r, color.g, color.b); //this doesn't work
auto x=glGetUniformLocation(Binder.getShader(shaderID)->Program_id, "uColor");
glUniform3f(x, color.r, color.g, color.b); // this works
Я не понимаю, почему это происходит. Я пытался удалить указатель из функции или использовать & в качестве типа возвращаемого значения, но это все равно не помогает.
[b]РЕДАКТИРОВАТЬ:[/b]Это определения Setuniform3f, а также привязки и функция, в которой я их вызывал:
void Opengl_Draw::Draw_line(glm::vec3 from, glm::vec3 to, glm::vec4 color)
{
Binder.bind(shaderID, vao, vbo);
auto id = Binder.getShader(shaderID)->Program_id;
float data[] = {
from.x,from.y,from.z,
to.x,to.y,to.z
};
Binder.UpdateBufferData(0, sizeof(data), data);
//Binder.getShader(shaderID).get().Setuniform3f("uColor", color.r, color.g, color.b);
auto x=glGetUniformLocation(Binder.getShader(shaderID)->Program_id, "uColor");
glUniform3f(x, 1.0f, 0.0f, 1.0f);
glDrawArrays(GL_LINES, 0, 2);
Binder.unbind(shaderID, vao, vbo);
}
void Shader_Binder::bind(ShaderID id, int vaoid, int vboid)
{
if (!isIdUsed(id)) return;
// Bind the shader and update tracking
if (m_CurrentShader != id)
{
m_Data[id].m_shader.Bind();
m_CurrentShader = id;
}
else
{
MessageBoxA(NULL, "Shader id not found or is 0 ... escaping the binding function... ", "Binding error", MB_OK);
return;
}
// Bind the VAO and update tracking if needed
if (vaoid != -1 && m_CurrentVAO != vaoid)
{
GL_CHECK(glBindVertexArray(vaoid));
m_CurrentVAO = vaoid;
}
// Bind the VBO and update tracking if needed
if (vboid != -1 && m_CurrentVBO != vboid)
{
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vboid));
m_CurrentVBO = vboid;
}
}
void Shader_Binder::unbind(ShaderID id, int vaoid, int vboid)
{
if (!isIdUsed(id)) return;
// Unbind the VAO only if it's the current one
if (vaoid != -1 && m_CurrentVAO == vaoid)
{
GL_CHECK(glBindVertexArray(0));
m_CurrentVAO = 0;
}
// Unbind the VBO only if it's the current one
if (vboid != -1 && m_CurrentVBO == vboid)
{
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
m_CurrentVBO = 0;
}
// Unbind the shader only if it's actually bound
if (m_CurrentShader == id)
{
m_Data[id].m_shader.Unbind();
m_CurrentShader = ShaderID::SH_00; // Or some default "unbound" state
}
}
// GL_CHECK is just a macro I used for error checking, and this, I think is not related to the question
void Shader::Bind() const
{
glUseProgram(Program_id);
}
void Shader::Unbind() const
{
glUseProgram(0);
}
void Shader::Setuniform3f(const std::string& name, float v1, float v2, float v3)
{
glUniform3f(GetUniformLocation(name), v1, v2, v3);
}
unsigned int Shader::GetUniformLocation(const std::string& name)
{
Bind();
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
{
return m_UniformLocationCache[name];
}
int location = glGetUniformLocation(Program_id, name.c_str());
if (location == -1)
{
MessageBoxA(NULL, std::string("Warning! Uniform " + name + " is unused or not found or does no exist!").c_str(), "UNIFORM LOCATION WARNING!!!", MB_OK);
}
else
m_UniformLocationCache[name] = location;
Unbind();
return location;
}
// I just did a caching system with a small error checking here, nothing special.
Подробнее здесь: [url]https://stackoverflow.com/questions/79082868/returning-a-object-of-a-shader-class-to-use-a-uniform-function-in-a-opengl-class[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия