Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心
Posted
技术标签:
【中文标题】Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心【英文标题】:Opengl 3.3 doesn't draw anything. Using GLSL 330 Core 【发布时间】:2015-03-29 23:31:07 【问题描述】:我正在遵循this site 的指南并停止学习第 2 课。起初我尝试编写自己的代码,但在它不起作用后,我只是从网站上获取了代码。除了glClearColor
,它仍然没有绘制任何东西。
我做了什么:
-
检查编译和链接。工作正常
检查错误。不确定我是否做得对,但似乎一切正常(我收到 1280 错误,但我读过 GLEW 会导致它,可以忽略)。
将
glUseProgram
移动到主循环中,但没有得到任何结果。
更改了颜色并尝试修改着色器。还是什么都没有
我将发布我目前拥有的代码(来自网站的原始代码):
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <glew.h>
#include <glfw3.h>
#include <glm/glm.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
int max(int i, int j)
if (i > j) return i;
return j;
GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path)
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if (VertexShaderStream.is_open())
std::string Line = "";
while (getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if (FragmentShaderStream.is_open())
std::string Line = "";
while (getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\n\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage(max(InfoLogLength, int(1)));
std::cout << "Checking program\n";
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
std::cout << "END";
return ProgramID;
int main(void)
if (!glfwInit())
std::cout << "Cannot init glfw";
return -1;
//glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
// Open a window and create its OpenGL context
GLFWwindow* window; // (In the accompanying source code, this variable is global)
window = glfwCreateWindow(1024, 768, "Tutorial 01", NULL, NULL);
if (window == NULL)
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
glfwTerminate();
return -1;
glfwMakeContextCurrent(window); // Initialize GLEW
glewExperimental = GL_TRUE; // Needed in core profile
if (glewInit() != GLEW_OK)
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
static const GLfloat g_vertex_buffer_data[] =
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
;
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
GLuint programID = LoadShaders("res\\vertex.glsl", "res\\fragment.glsl");
do
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
// Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
return 0;
fragment.glsl
#version 330 core
out vec3 color;
void main()
color = vec3(1,1,0);
vertex.glsl
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main()
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
【问题讨论】:
此代码与核心配置文件不兼容。在核心配置文件中需要使用顶点数组对象 (VAO)。 @RetoKoradi 感谢您的评论。它解决了这种情况。您介意将其作为答案,以便我将其标记为正确吗? 你是如何解决这个问题的?我和你的处境一样,希望得到一些帮助 @RakshithRavi 我建议你看看我接受的答案。已经一年多了,我不确定我是如何解决的,但答案确实有帮助。 【参考方案1】:OpenGL 核心配置文件需要使用顶点数组对象 (VAO)。这在规范的“已弃用和删除的功能”中:
客户端顶点和索引数组 - 所有顶点数组属性和元素数组索引指针必须引用缓冲区对象。默认的顶点数组对象(名称为零)也已弃用。在未绑定缓冲区对象或未绑定顶点数组对象时调用 VertexAttribPointer 会产生 INVALID_OPERATION 错误,当未绑定顶点数组对象时调用任何数组绘制命令也会产生错误。
您使用的教程建议将此代码用作初始化的一部分:
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
这足以让教程代码正常工作。为了在更复杂的应用程序中有效地使用 VAO,您可能希望为每个对象创建一个 VAO。然后,这将跟踪对象的完整顶点设置状态,并允许您在绘制之前通过单个 glBindVertexArray()
调用来设置状态。
【讨论】:
以上是关于Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心的主要内容,如果未能解决你的问题,请参考以下文章