OpenGL拒绝绘制三角形。

4

我正在尝试在OpenGL窗口中绘制一个大三角形。我的程序可以编译和运行,但是在窗口中只出现了黑屏。

我已经检查了多个教程,并且看起来我的步骤都是正确的... 我是否漏掉了一些显而易见的东西?

这就是整个程序:

#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#include <GLUT/glut.h>

GLuint VBO;

struct vector {
  float _x;
  float _y;
  float _z;
  vector() { }
  vector(float x, float y, float z) { _x = x; _y = y; _z = z; }
};

void render()
{
  glClear(GL_COLOR_BUFFER_BIT);

  glEnableVertexAttribArray(0);
  glBindBuffer(GL_ARRAY_BUFFER, VBO);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

  glDrawArrays(GL_TRIANGLES, 0, 3);

  glDisableVertexAttribArray(0);

  glutSwapBuffers();
}

void create_vbo()
{
  vector verts[3];
  verts[0] = vector(-1.0f, -1.0f, 0.0f);
  verts[1] = vector(1.0f, -1.0f, 0.0f);
  verts[2] = vector(0.0f, 1.0f, 0.0f);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
    glutInitWindowSize(1024, 768);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Triangle Test");
    glutDisplayFunc(render);

    glewInit();

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    create_vbo();
    glutMainLoop();

    return 0;
}

更新:事实证明,不使用“程序”(即编译的着色器文件)进行绘制会产生未定义的行为(您的显卡越新,它就越有可能工作)。由于我的显卡处于边缘位置,仅支持OpenGL 2.1,因此很难找到一个适当的着色器示例来使用 - 看起来似乎有许多不同的教程在不同阶段编写的OpenGL演变。
我的顶点着色器(整个文件):
void main()
{
  gl_Position = ftransform();
}

我的片段着色器(完整文件):

void main()
{
    gl_FragColor = vec4(0.4,0.4,0.8,1.0);
}

我使用了来自OpenGL教程网站的示例LoadShaders函数来创建程序,现在我也可以看到三角形了!(感谢@chbaker0指导我正确方向。)

它为我绘制了一个三角形。你能否尝试用仅包含浮点数的数组替换你的“向量”数组,并将其上传到缓冲区?从技术上讲,C++不能保证这些结构体的布局方式。 - chbaker0
没意识到这个问题!我尝试上传一个float[9]的数组,但仍然没有三角形。你说代码对你来说是可以工作的,这是有用的信息...难道是OpenGL版本的问题吗?我在程序中打印了glGetString(GL_VERSION),得到的结果是2.1 NVIDIA-10.0.43 310.41.05f0。我没有使用OpenGL 2.0之外的任何功能,对吗? - Elliot Nelson
我有一个OpenGL 4.4兼容上下文,所以这是非常可能的。我现在正在查看一些文档。 - chbaker0
1
有一些想法:您正在使用可编程管线功能,而没有使用着色器,因此我们可能正在经历OpenGL未定义的行为。由于我使用的是AMD显卡,而您使用的是NVidia,它们可能会有不同的响应。但是我不确定;我只亲自使用过OpenGL 3.3+核心上下文。 - chbaker0
@chbaker0,果然是着色器的问题。如果您愿意,可以以答案形式发布。我也会更新问题并提供我的确切步骤。 - Elliot Nelson
显示剩余2条评论
2个回答

2
我不知道这是否对您有帮助,但在您的 create_vbo() 函数中,您有以下代码:
  glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

请尝试使用以下方法:

  glBufferData( GL_ARRAY_BUFFER, sizeof( verts[0] * 3 ), &verts[0], GL_STATIC_DRAW );

在 create_vbo() 函数的末尾添加这个函数调用。
// This MUST BE LAST! Used to Stop The Buffer!
glBindBuffer( GL_ARRAY_BUFFER, 0 ); 

我很难看出你的错误。在我的项目中,我有一些vbos,但我也使用vaos。我的代码能够在OpenGL 2.0-4.5中工作,但对于旧版本,由于API中废弃的函数,逻辑会分裂。我也不使用glut。希望这可以帮助你。

我还注意到另一件事情,你是否注意到了你的顶点绕组顺序?意思是它们被OpenGL以逆时针顺序或顺时针顺序使用了吗?背面剔除打开还是关闭?在设置和配置OpenGL上下文时需要考虑许多因素。我已经有一段时间没有使用旧版本的OpenGL了,但我知道一旦开始使用特定版本或更新版本,你将不得不提供自己的模型视图投影矩阵,这只是需要考虑的一些事情。


0
我遇到的问题是在没有定义着色器程序的情况下使用管线功能。规范说这应该可以工作,但在我的显卡上并没有工作(有关更多详细信息,请参见我的问题更新)。感谢所有评论者引导我朝正确的方向前进。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接