OpenGL GLFW,三角形不渲染
OpenGL GLFW, triangle not rendering
我一直在尝试在 macOS 上渲染三角形,但它不起作用。
这是我的代码:
#include <iostream>
#include <glm/glm.hpp>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
void OnError(int errorCode, const char* msg){
throw std::runtime_error(msg);
}
int main(){
glfwSetErrorCallback(OnError);
if (!glfwInit()){
throw std::runtime_error("glfwInit failed");
}
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(512, 512, "Title", NULL, NULL);
if (!window){
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK){
glfwTerminate();
return -1;
}
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
float points[] = {
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0
};
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
GLuint vao = 0;
glGenBuffers(1, &vao);
glBindVertexArray(vao);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
const char* vertex_shader =
"#version 410\n"
"in vec3 vp;"
"void main(){"
" gl_Position = vec4(vp, 1.0);"
" };";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
const char* fragment_shader =
"#version 410\n"
"out vec4 frag_colour;"
"void main(){"
" frag_colour = vec4(0.0, 1.0, 0.0, 1.0);"
" };";
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
while (!glfwWindowShouldClose(window)){
//glViewport(0, 0, 512, 512);
//glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
顶点数组对象名称必须由 glGenVertexArrays
rather than glGenBuffers
:
生成
glGenBuffers(1, &vao);
glGenVertexArrays(1, &vao);
状态顶点数组规范和启用状态存储在顶点数组对象中。创建对象名称并绑定(创建)顶点数组对象。然后可以指定并启用顶点数组:
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
在绘制几何之前,绑定顶点数组对象就足够了:
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
请注意,在您的应用程序中创建了核心配置文件 OpenGL Context (GLFW_OPENGL_CORE_PROFILE
)。这导致默认的顶点数组对象 (0) 无效。
glVertexAttribPointer
and glEnableVertexAttribArray
之类的指令会改变顶点数组对象的状态。如果调用此函数时未绑定命名顶点数组对象,则会导致 INVALID_OPERATION 错误。
此外,您还创建了一个 3.2 核心配置文件 OpneGL 上下文。 OpenGL 3.2对应的GLSL版本是1.50.
更改顶点和片段着色器中的版本规范:
#version 410
#version 150
最终三角形:
我建议检查着色器编译是否成功以及程序对象是否链接成功。
如果着色器编译成功可以通过glGetShaderiv
和参数GL_COMPILE_STATUS
来检查。例如:
#include <iostream>
#include <vector>
bool CompileStatus( GLuint shader )
{
GLint status = GL_TRUE;
glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
if (status == GL_FALSE)
{
GLint logLen;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetShaderInfoLog( shader, logLen, &written, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
return status != GL_FALSE;
}
程序链接是否成功可以通过glGetProgramiv
和参数GL_LINK_STATUS
检查。例如:
bool LinkStatus( GLuint program )
{
GLint status = GL_TRUE;
glGetProgramiv( program, GL_LINK_STATUS, &status );
if (status == GL_FALSE)
{
GLint logLen;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetProgramInfoLog( program, logLen, &written, log.data() );
std::cout << "link error:" << std::endl << log.data() << std::endl;
}
return status != GL_FALSE;
}
编译着色器后调用函数,分别链接程序:
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
CompileStatus(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
CompileStatus(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
LinkStatus(shader_program);
我一直在尝试在 macOS 上渲染三角形,但它不起作用。
这是我的代码:
#include <iostream>
#include <glm/glm.hpp>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
void OnError(int errorCode, const char* msg){
throw std::runtime_error(msg);
}
int main(){
glfwSetErrorCallback(OnError);
if (!glfwInit()){
throw std::runtime_error("glfwInit failed");
}
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(512, 512, "Title", NULL, NULL);
if (!window){
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK){
glfwTerminate();
return -1;
}
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
float points[] = {
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0
};
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
GLuint vao = 0;
glGenBuffers(1, &vao);
glBindVertexArray(vao);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
const char* vertex_shader =
"#version 410\n"
"in vec3 vp;"
"void main(){"
" gl_Position = vec4(vp, 1.0);"
" };";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
const char* fragment_shader =
"#version 410\n"
"out vec4 frag_colour;"
"void main(){"
" frag_colour = vec4(0.0, 1.0, 0.0, 1.0);"
" };";
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
while (!glfwWindowShouldClose(window)){
//glViewport(0, 0, 512, 512);
//glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
顶点数组对象名称必须由 glGenVertexArrays
rather than glGenBuffers
:
glGenBuffers(1, &vao);
glGenVertexArrays(1, &vao);
状态顶点数组规范和启用状态存储在顶点数组对象中。创建对象名称并绑定(创建)顶点数组对象。然后可以指定并启用顶点数组:
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
在绘制几何之前,绑定顶点数组对象就足够了:
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
请注意,在您的应用程序中创建了核心配置文件 OpenGL Context (GLFW_OPENGL_CORE_PROFILE
)。这导致默认的顶点数组对象 (0) 无效。
glVertexAttribPointer
and glEnableVertexAttribArray
之类的指令会改变顶点数组对象的状态。如果调用此函数时未绑定命名顶点数组对象,则会导致 INVALID_OPERATION 错误。
此外,您还创建了一个 3.2 核心配置文件 OpneGL 上下文。 OpenGL 3.2对应的GLSL版本是1.50.
更改顶点和片段着色器中的版本规范:
#version 410
#version 150
最终三角形:
我建议检查着色器编译是否成功以及程序对象是否链接成功。
如果着色器编译成功可以通过glGetShaderiv
和参数GL_COMPILE_STATUS
来检查。例如:
#include <iostream>
#include <vector>
bool CompileStatus( GLuint shader )
{
GLint status = GL_TRUE;
glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
if (status == GL_FALSE)
{
GLint logLen;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetShaderInfoLog( shader, logLen, &written, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
return status != GL_FALSE;
}
程序链接是否成功可以通过glGetProgramiv
和参数GL_LINK_STATUS
检查。例如:
bool LinkStatus( GLuint program )
{
GLint status = GL_TRUE;
glGetProgramiv( program, GL_LINK_STATUS, &status );
if (status == GL_FALSE)
{
GLint logLen;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetProgramInfoLog( program, logLen, &written, log.data() );
std::cout << "link error:" << std::endl << log.data() << std::endl;
}
return status != GL_FALSE;
}
编译着色器后调用函数,分别链接程序:
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
CompileStatus(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
CompileStatus(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
LinkStatus(shader_program);