多个对象无法渲染?
Posted
技术标签:
【中文标题】多个对象无法渲染?【英文标题】:Multiple objects fail to render? 【发布时间】:2020-06-01 21:18:16 【问题描述】:我应该在屏幕上显示两个方块,但是当我运行它时,我看到的只是一个虚无的屏幕。
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
struct Shaderprogramsource
std::string VertexSouce;
std::string FragmentSource;
;
static Shaderprogramsource Parseshader(const std::string& filepath)
std::ifstream stream(filepath);
enum class Shadertype
VERTEX = 0,
FRAGMENT = 1,
NONE = 5
;
std::string line;
std::stringstream ss[3];
Shadertype type = Shadertype::NONE;
while (getline(stream, line))
if (line.find("#shader") != std::string::npos)
if (line.find("vertex") != std::string::npos)
type = Shadertype::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = Shadertype::FRAGMENT;
else
ss[(int)type] << line << "\n";
return Shaderprogramsource ss[0].str(), ss[1].str() ;
static int CompileShader(unsigned int type, const std::string& Source)
unsigned int id = glCreateShader(type);
const char* src = Source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << message;
return 0;
return id;
static unsigned int CreateShader(
const std::string& Vertexshader,
const std::string& Fragmentshader)
unsigned int program = glCreateProgram();
unsigned int vertex = CompileShader(GL_VERTEX_SHADER, Vertexshader);
unsigned int fragment = CompileShader(GL_FRAGMENT_SHADER, Fragmentshader);
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
glValidateProgram(program);
return program;
int main(void)
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(800, 800, "Hello World", NULL, NULL);
if (!window)
glfwTerminate();
return -1;
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (GLEW_OK == glewInit())
float vertices[] = -0.1, -0.1,
0.1, -0.1,
0.1, 0.1,
-0.1, 0.1 ;
float vertices2[] = -0.1,0.1,
0.1, 0.1,
0.1, 0.3,
-0.1, 0.3 ;
unsigned int indices[] =
0, 1, 2,
2, 3, 0
;
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
unsigned int vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
unsigned int buffer1;
unsigned int vbo;
glGenBuffers(1, &buffer1);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
Shaderprogramsource source = Parseshader("res/shaders/Basic.Shader");
unsigned int shader =
CreateShader(source.VertexSouce, source.FragmentSource);
glUseProgram(shader);
int location = glGetUniformLocation(shader, "Color_u");
if (location > -1)
glUniform4f(location, 0.8f, 0.0f, 0.0f, 1.0f);
std::cout << source.VertexSouce;
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glBindBuffer(GL_ARRAY_BUFFER, vao);
glBindBuffer(GL_ARRAY_BUFFER, vao2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glUseProgram(shader);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
glDeleteProgram(shader);
glfwTerminate();
return 0;
着色器:
#shader vertex
#version 330 core
layout(location = 0) in vec3 position;
void main()
gl_Position = vec4(position.x, position.y, position.z, 1.0);
;
#shader fragment
#version 330 core
layout(location = 0) out vec4 color;
uniform vec4 Color_u;
void main()
color = Color_u;
;
【问题讨论】:
【参考方案1】:各种各样的笨蛋:
如果第一行以魔法#shader
指令以外的任何内容开头,Parseshader()
将被破坏,因为 NONE
设置为 5 并且 ss[(int)type]
索引 + 赋值将直接从 3 元素 @987654327 的末尾走开@ 大批。将NONE
下拉至2
。
您的着色器中只有一个顶点属性 (0
),但您正在尝试设置 1
。
这不是 VAO 的工作方式根本。 VAO从未成为glBindBuffer()
的有效参数。 Intead,绑定一个 VAO,然后设置您的顶点属性绑定/布局:
unsigned int vao1 = 0;
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(0);
然后当您想绘制时,您可以重新绑定 VAO 并立即绘制,跳过所有 glBindBuffer()
/glVertexAttribPointer()
/glEnableVertexAttribArray()
设置。
大家一起:
// g++ -g main.cpp `pkg-config --cflags --libs glfw3 glew`
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <sstream>
#include <string>
const char* const shaderSource = R"GLSL(
#shader vertex
#version 330 core
layout(location = 0) in vec3 position;
void main()
gl_Position = vec4(position.x, position.y, position.z, 1.0);
;
#shader fragment
#version 330 core
layout(location = 0) out vec4 color;
uniform vec4 Color_u;
void main()
color = Color_u;
;
)GLSL";
struct Shaderprogramsource
std::string VertexSouce;
std::string FragmentSource;
;
static Shaderprogramsource Parseshader(const std::string& shaderString)
std::stringstream stream( shaderString );
enum class Shadertype
VERTEX = 0,
FRAGMENT = 1,
NONE = 2
;
std::string line;
std::stringstream ss[3];
Shadertype type = Shadertype::NONE;
while( std::getline(stream, line) )
if (line.find("#shader") != std::string::npos)
if (line.find("vertex") != std::string::npos)
type = Shadertype::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = Shadertype::FRAGMENT;
else
ss[(int)type] << line << '\n';
return Shaderprogramsource ss[0].str(), ss[1].str() ;
static int CompileShader(unsigned int type, const std::string& Source)
unsigned int id = glCreateShader(type);
const char* src = Source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << message;
return 0;
return id;
static unsigned int CreateShader( const std::string& Vertexshader, const std::string& Fragmentshader )
unsigned int program = glCreateProgram();
unsigned int vertex = CompileShader(GL_VERTEX_SHADER, Vertexshader);
unsigned int fragment = CompileShader(GL_FRAGMENT_SHADER, Fragmentshader);
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
glValidateProgram(program);
return program;
int main( int argc, char** argv )
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
glfwTerminate();
return -1;
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (GLEW_OK == glewInit())
unsigned int buffer1;
glGenBuffers(1, &buffer1);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
float vertices1[] =
-0.1, -0.1,
0.1, -0.1,
0.1, 0.1,
-0.1, 0.1,
;
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);
unsigned int buffer2;
glGenBuffers(1, &buffer2);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
float vertices2[] =
-0.1, 0.1,
0.1, 0.1,
0.1, 0.3,
-0.1, 0.3,
;
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
unsigned int indices[] =
0, 1, 2,
2, 3, 0,
;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
unsigned int vao1 = 0;
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(0);
unsigned int vao2 = 0;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(0);
Shaderprogramsource source = Parseshader( shaderSource );
unsigned int shader = CreateShader(source.VertexSouce, source.FragmentSource);
glUseProgram(shader);
int location = glGetUniformLocation(shader, "Color_u");
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
if (location > -1)
glUniform4f(location, 0.8f, 0.0f, 0.0f, 1.0f);
glBindVertexArray(vao1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
if (location > -1)
glUniform4f(location, 0.0f, 0.8f, 0.0f, 1.0f);
glBindVertexArray(vao2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glDeleteProgram(shader);
glfwTerminate();
return 0;
【讨论】:
为什么必须用 VAO 重新绑定所有内容?只是好奇。 @Jerryoff:“重新绑定一切”是什么意思?您是说在 VAO 设置期间重新绑定 buffer1/buffer2/ebo 吗? 是的缓冲区。 @Jerryoff:您必须重新绑定,因为glBindVertexArray()
调用会将绑定点重置为 VAO 中的任何内容。由于在这些绑定点默认为零之前尚未绑定 VAO,这意味着从客户端内存(兼容性上下文)或无效缓冲区对象(核心上下文)中提取。以上是关于多个对象无法渲染?的主要内容,如果未能解决你的问题,请参考以下文章