Возврат объекта класса шейдера для использования универсальной функции в классе opengl дает GL_INVALID_OPERATION.C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Возврат объекта класса шейдера для использования универсальной функции в классе opengl дает GL_INVALID_OPERATION.

Сообщение 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

Я не понимаю, почему это происходит. Я пытался удалить указатель из функции или использовать & в качестве типа возвращаемого значения, но это все равно не помогает.
РЕДАКТИРОВАТЬ:Это определения 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»