问题描述
编辑:在 glDrawElements() 之后使用 glGetError() 时,我收到错误“警告统一 'u_Color' 不存在”。我正在使用如下所示的基本着色器,并在我的 RenderObject 管道中为着色器设置统一。有谁知道我需要添加什么才能识别制服?
大家好,我正在尝试将对象渲染到屏幕上,我已经使管道成功工作,但我似乎无法使用 glDrawElements 或 glDrawArrays 绘制任何内容。我通过在 renderer.Draw() 函数中调用 glClearColor(1.0f,0.0f,1.0f) 来测试管道,我得到了红色背景。我认为它要么与缓冲区数据以某种方式丢失有关,positionsArr 和indicesArr 具有额外分配的内存,这在传递给glDrawElements 时会导致问题,尽管这不会阻止glDrawArrays 工作,但它也不起作用,或也许我没有在 glGenBuffers 中分配足够的空间,或者我没有想到的东西。
管道:
void RenderObject(Renderer* renderer,std::vector<float> objectColor,std::vector<float> positions,std::vector<int> indices) {
/*
postions: float {
x,x,y,z,z
};
indices (shape using class Shape): int {
ex. 1,2,3
2,3,1
};
translationCoord: float {
x,z
}
textureColor: float {
r,g,b,a
}
*/
/*
positions = {
-0.5f,-0.5f,0.5f,0.5f
}
indices = {
0,1,0
}
MAX_ARRAY_ALLOCATION = 15
*/
float positionsArr[MAX_ARRAY_ALLOCATION];
int indicesArr[MAX_ARRAY_ALLOCATION];
VectorToArray<int>(indicesArr,indices);
VectorToArray<float>(positionsArr,positions);
VertexBuffer vb(positionsArr,positions.size() * sizeof(float));
VertexBufferLayout layout;
VertexArray va;
layout.Push<float>((int)positions.size() / 2);
va.AddBuffer(vb,layout);
if (!firstObjectRender) {
if (!firstTextureRender) {
Shader shader(SHADER_SOURCE);
appShader = shader;
firstObjectRender = true;
}
}
IndexBuffer ib(indicesArr,indices.size());
appShader.Bind();
appShader.SetUniform4f("u_Color",glm::vec4(objectColor[0],objectColor[1],objectColor[2],objectColor[3]));
va.Bind();
vb.Bind();
renderer->Draw(va,ib,appShader,indicesArr);
va.Unbind();
vb.Unbind();
ib.Unbind();
appShader.Unbind();
}
VectorToArray 函数:
template<typename T> void VectorToArray(T* arr,std::vector<T> vect) {
for (int i = 0; i < vect.size(); i++) {
try {
if (i == MAX_ARRAY_ALLOCATION) throw(true);
arr[i] = vect[i];
}
catch (bool error) {
std::cout << "nano::Nano::VectorToArray vector greater than max array size\n";
}
}
}
着色器:
const char* shaderProgram = "#version 330 core\n"
"layout(location = 0) in vec4 position;\n"
"void main() {\n"
"gl_Position = position;\n"
"}\0";
const char* fragmentProgram = "#version 330 core\n"
"layout(location = 0) out vec4 color;\n"
"uniform vec4 u_Color;\n"
"void main() {\n"
"gl_FragColor = u_Color;\n"
"}\n\0";
VertexBuffer 类:
VertexBuffer::VertexBuffer() {
}
VertexBuffer::VertexBuffer(const void* data,unsigned int size) {
glGenBuffers(1,&m_RendererID);
glBindBuffer(GL_ARRAY_BUFFER,m_RendererID);
glBufferData(GL_ARRAY_BUFFER,size,data,GL_STATIC_DRAW);
}
VertexBuffer::~VertexBuffer() {
glDeleteBuffers(1,&m_RendererID);
}
void VertexBuffer::Bind() const {
glBindBuffer(GL_ARRAY_BUFFER,m_RendererID);
}
void VertexBuffer::Unbind() const {
glBindBuffer(GL_ARRAY_BUFFER,0);
}
VertexBufferLayout 类:
struct VertexBufferElement {
unsigned int count;
unsigned int type;
unsigned char normalized;
static unsigned int GetSizeOfType(unsigned int type) {
switch (type) {
case GL_FLOAT: return 4;
case GL_UNSIGNED_INT: return 4;
case GL_UNSIGNED_BYTE : return 1;
}
return 0;
}
};
class VertexBufferLayout {
private:
std::vector<VertexBufferElement> m_Elements;
unsigned int m_Stride;
public:
VertexBufferLayout() : m_Stride(0) {};
template<typename T> void Push(unsigned int count) {
static_assert(false);
}
template<> void Push<float>(unsigned int count) {
VertexBufferElement ve = { GL_FLOAT,count,GL_FALSE };
m_Elements.push_back(ve);
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_FLOAT);
}
template<> void Push<unsigned int>(unsigned int count) {
VertexBufferElement ve = { GL_UNSIGNED_INT,GL_FALSE };
m_Elements.push_back(ve);
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_INT);
}
template<> void Push<unsigned char>(unsigned int count) {
VertexBufferElement ve = { GL_UNSIGNED_BYTE,GL_TRUE };
m_Elements.push_back(ve);
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_BYTE);
}
inline const std::vector<VertexBufferElement> GetElements() const { return m_Elements; }
inline unsigned int GetStride() const { return m_Stride; }
};
VertexArray 类:
VertexArray::VertexArray() {
glGenVertexArrays(1,&m_RendererID);
}
VertexArray::~VertexArray() {
glDeleteVertexArrays(1,&m_RendererID);
}
void VertexArray::AddBuffer(const VertexBuffer& vb,const VertexBufferLayout& layout) {
Bind();
vb.Bind();
const auto& elements = layout.GetElements();
unsigned int offset = 0;
for (unsigned int i = 0; i < elements.size(); i++) {
const auto& element = elements[i];
glEnableVertexAttribArray(i);
glVertexAttribPointer(i,element.count,element.type,element.normalized,layout.GetStride(),(const void*)offset);
offset += element.count * VertexBufferElement::GetSizeOfType(element.type);
}
}
void VertexArray::Bind() const {
glBindVertexArray(m_RendererID);
}
void VertexArray::Unbind() const {
glBindVertexArray(0);
}
着色器类:
Shader::Shader() {
}
Shader::Shader(const std::string& filepath) : m_FilePath(filepath),m_RendererID(0){
m_RendererID = CreateShader(shaderProgram,fragmentProgram);
}
Shader::~Shader() {
glDeleteProgram(m_RendererID);
}
void Shader::Bind() const {
glUseProgram(m_RendererID);
}
void Shader::Unbind() const {
glUseProgram(0);
}
unsigned int Shader::CreateShader(const std::string& vertexShader,const std::string& fragmentShader) {
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER,vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER,fragmentShader);
glAttachShader(program,vs);
glAttachShader(program,fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
void Shader::SetUniform1i(const std::string& name,int value) {
GLint location = GetUniformLocation(name);
glUniform1i(location,value);
}
void Shader::SetUniform1f(const std::string& name,float value) {
GLint location = GetUniformLocation(name);
glUniform1f(location,value);
}
void Shader::SetUniform2f(const std::string& name,const glm::vec2& value) {
GLint location = GetUniformLocation(name);
glUniform2f(location,value.x,value.y);
}
void Shader::SetUniform3f(const std::string& name,const glm::vec3& value) {
GLint location = GetUniformLocation(name);
glUniform3f(location,value.y,value.z);
}
void Shader::SetUniform4f(const std::string& name,const glm::vec4& value) {
GLint location = GetUniformLocation(name);
glUniform4f(location,value.z,value.w);
}
void Shader::SetUniformMat4f(const std::string& name,const glm::mat4& matrix) {
glUniformMatrix4fv(GetUniformLocation(name),GL_FALSE,&matrix[0][0]);
}
GLint Shader::GetUniformLocation(const std::string& name) {
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
return m_UniformLocationCache[name];
GLint location = glGetUniformLocation(m_RendererID,name.c_str());
if (location == -1)
std::cout << "Warining: uniform '" << name << "' doesn't exist!" << std::endl;
m_UniformLocationCache[name] = location;
return location;
}
渲染器类:
void Renderer::Clear() const {
glClear(GL_COLOR_BUFFER_BIT);
}
void Renderer::Draw(const VertexArray& va,const IndexBuffer& ib,const Shader& shader,int indices[]) const {
shader.Bind();
va.Bind();
ib.Bind();
glDrawElements(GL_TRIANGLES,ib.GetCount(),GL_UNSIGNED_SHORT,indices);
//glDrawArrays(GL_TRIANGLES,ib.GetCount());
}
我是如何实现的:
const unsigned int SCR_WIDTH = 960;
const unsigned int SCR_HEIGHT = 540;
class Test : public nano::Nano {
private:
std::vector<nano::Shape> shapes;
public:
Test() {
}
void InitializeObjects() {
std::vector<float> positions = {
-0.5f,0.5f
};
nano::Shape tempShape = nano::Shape::Shape("rect",positions);
shapes.push_back(tempShape);
}
void OnCreate() override {
InitializeObjects();
}
void OnRender(float deltaTime) override {
Renderer renderer;
std::vector<float> color = { 1.0f,1.0f };
while (!glfwWindowShouldClose(nano::Nano::GetWindow()))
{
nano::Nano::OnInput();
renderer.Clear();
//glClearColor(1.0f,1.0f);
for (auto& object : shapes) {
nano::Nano::RenderObject(&renderer,color,object.GetPosition(),object.GetIndices());
}
nano::Nano::ManageRender();
}
}
void OnInput() override {
}
};
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)