绘制三角形不起作用:我只看到黑屏和鼠标
Posted
技术标签:
【中文标题】绘制三角形不起作用:我只看到黑屏和鼠标【英文标题】:Drawing triangle doesn't work: I just see a black screen and my mouse 【发布时间】:2014-05-23 15:26:10 【问题描述】:我将 GLEW 用于现代 OpenGL 函数,将 GLFW 用于窗口。我正在尝试绘制一个三角形,但它编译并运行但不绘制三角形有问题,我只看到一个黑屏和我的鼠标。 这是我的代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <glew.h>
#include <GLFW\glfw3.h>
#include <glm\glm.hpp>
const GLchar* vertexSource =
"#version 150 core\n"
"in ver2 position;"
"void main()"
" gl_Position = vec4(position, 0.0, 1.0);"
"";
const GLchar* fragmentSource =
"#version 150 core\n"
"out vec4 outColor;"
"void main()"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"";
int main()
//GLFW init:
if (!glfwInit())
fprintf(stderr, "Failed to init GLFW");
glfwTerminate();
//Hints:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//Creating window:
GLFWwindow* window = glfwCreateWindow(800, 600, "Engine", glfwGetPrimaryMonitor(), nullptr);
glfwMakeContextCurrent(window);
//Glew initialize:
glewExperimental = GL_TRUE;
glewInit();
//Create vertex array object:
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//Create vertex buffer object:
GLuint vbo;
glGenBuffers(1, &vbo);
//Our triangle data:
GLfloat vertices[] =
0.0f, 0.5f, //Vertex 1 (X, Y)
0.5f, -0.5f, //Vertex 2 (X, Y)
-0.5f, -0.5f //Vertex 3 (X, Y)
;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//Create and compile the vertex shader:
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
//Create and compile the fragment shader:
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
//Creating shaders program:
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
//The loop:
while (!glfwWindowShouldClose(window))
//Escape key:
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
return 0;
【问题讨论】:
【参考方案1】:"in ver2 position;"
^^^^
ver2
是什么?我怀疑你的 GLSL 编译器也知道。
尝试vec2
并检查您的着色器编译/链接状态/日志:
struct Program
static GLuint Load( const char* vert, const char* geom, const char* frag )
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
private:
static void CheckStatus( GLuint obj )
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = 0 ;
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( -1 );
static void AttachShader( GLuint program, GLenum type, const char* src )
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
;
【讨论】:
哇,我不敢相信这是问题所在.. ty.【参考方案2】:您不需要使用glBindFragDataLocation
,而是在片段着色器中写入gl_FragColor
:
const GLchar* fragmentSource =
"#version 150 core\n"
"void main()"
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
"";
否则你需要用glDrawBuffers
指定写入哪个缓冲区
【讨论】:
发帖者使用的是核心配置文件,其中gl_FragColor
已弃用。但是无论如何都不需要glBindFragDataLocation
调用。如果片段着色器只有一个out
,它会自动写入第一个绘制缓冲区(默认帧缓冲区默认为GL_BACK
,FBO 为GL_COLOR_ATTACHMENT0
)。
@RetoKoradi:实际上,我从未在规范中找到这样的保证。规范中的所有内容是 GL 将自动分配任何未手动分配位置的输出到某些未使用的颜色编号。出于显而易见的原因,每个现实世界的实现都从 0 开始赋值,但就规范而言,依赖它仍然是未定义的行为。
@derhass:已指定。 GLSL 4.4 规范:“如果在着色器文本中未分配位置或索引的输出变量具有通过 OpenGL API 指定的位置,则将使用 API 分配的位置。否则,链接器将为此类变量分配位置。所有此类分配的颜色索引都将为零。” ES 3.0 GLSLS 规范:“如果只有一个输出,则不需要指定位置,在这种情况下它默认为零。”
@RetoKoradi:实际上并非如此。之前我自己也犯过同样的错误:颜色number和颜色index是有区别的。颜色 number 是这里的相关部分。 index 仅用于多输入混合。请注意,如果规范要求所有输出(如果使用多个输出)都绑定到相同的数字 0,那也会很奇怪......不过,ES 3.0 规范是另一回事。
@derhass:好的,是的,我明白你在说什么。确实没有明确指定链接器将从 0 开始分配位置。如果驱动程序不以这种方式处理它,很多软件都会中断,但理论上你是对的。 ES 参考很重要,因为他们非常努力地将 ES 规范保持为完整 OpenGL 的子集。因此,如果在 ES 中保证行为,但在 OpenGL 中不保证,那将是非常不可取的。以上是关于绘制三角形不起作用:我只看到黑屏和鼠标的主要内容,如果未能解决你的问题,请参考以下文章
iOS startMonitoringForRegion 在睡眠模式下不起作用(黑屏)