我花了很多时间使用openGL的固定管道,最近我开始学习可编程管道。我知道我的画家,着色器类不是问题,因为它们使用固定功能管道的东西。我似乎无法让glDrawArrays为我的生活工作。
我不确定我的错误是在我如何设置顶点缓冲区对象,在我的着色器或其他地方。我也调试了我的代码并在整个显示函数中设置了断点,它似乎永远不会超过glDrawArrays(),(它在glDrawArrays上遇到一个断点,但之后没有点击,不知道为什么。)< / p>
输出的只是一个白色的屏幕,没有别的。
继承我的代码:
float vertices[] = { 0.75, 0.75, 0.0, 1.0,
0.75, -0.75, 0.0, 1.0,
-0.75, -0.75, 0.0, 1.0 };
GLuint vertexBufferObject;
GLuint positionLocation;
GLuint vaoObject;
void initVertexBuffer(GLuint& vertexBufferObject, float* vertexData, unsigned int size, GLenum GL_DRAW_TYPE)
{
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, size, vertexData, GL_DRAW_TYPE);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void main(int argc, char* argv[])
{
painter.initEngine(argc, argv, 500, 500, 0, 0, "2D3D");
painter.initGlutFuncs(display, resize, Input::MouseButtonClick, Input::MouseDrag, keyboard);
defaultShader.init("default.vert", "default.frag");
defaultShader.link();
initVertexBuffer(vertexBufferObject, vertices, sizeof(vertices), GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoObject);
glBindVertexArray(vaoObject);
positionLocation = glGetAttribLocation(defaultShader.id(), "position");
painter.startMainLoop();
}
void display()
{
painter.clearDisplay();
defaultShader.bind();
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
std::cout << Framework::glErrorCheck() << std::endl;
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(positionLocation);
glBindBuffer(GL_ARRAY_BUFFER, 0);
defaultShader.unbind();
painter.flushAndSwapBuffers();
}
顶点着色器:
#version 140
in vec4 position;
void main()
{
gl_Position = position;
}
Fragment Shader:
#version 140
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 0.0, 1.0, 1.0);
}
编辑:使用Joey Dewd,keltar和genpfault的建议更新了代码。 我不再挂在glDrawArrays上,也就是说,我没有看到白屏,而是一个黑屏。这让我觉得我的缓冲区仍然没有正确设置。或者可能,我遗漏了顶点数组缓冲区初始化所需的其他内容(vaoObject)?
答案 0 :(得分:4)
void initVertexBuffer(GLuint vertexBufferObject, float* vertexData, GLenum GL_DRAW_TYPE)
{
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DRAW_TYPE);
^^^^^^^^^^^^^^^^^^ nnnnope
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
sizeof(vertexData)
in this context is not what you seem to hope it is。
根据你的64位编辑,它可能是4或8。即,sizeof
指向浮点指针。 不 sizeof(vertices)
。
您需要传入一个单独的大小参数:
void initVertexBuffer(GLuint& vertexBufferObject, float* vertexData, unsigned int size, GLenum GL_DRAW_TYPE)
{
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, size, vertexData, GL_DRAW_TYPE);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
...
void main(int argc, char* argv[])
{
...
initVertexBuffer(vertexBufferObject, vertices, sizeof(vertices), GL_STATIC_DRAW);
...
}
或者像std::vector
这样的连续(重要!)标准容器:
template< typename Container >
void initVertexBuffer(GLuint& vertexBufferObject, const Container& vertexData, GLenum GL_DRAW_TYPE)
{
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof( typename Container::value_type ), &vertexData[0], GL_DRAW_TYPE);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
完整示例:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <vector>
using namespace std;
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 );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
void initVertexBuffer(GLuint& vertexBufferObject, float* vertexData, unsigned int size, GLenum GL_DRAW_TYPE)
{
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, size, vertexData, GL_DRAW_TYPE);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GLuint prog;
GLuint vaoObject;
void init()
{
const char* vert = GLSL
(
140,
in vec4 position;
void main()
{
gl_Position = position;
}
);
const char* frag = GLSL
(
140,
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 0.0, 1.0, 1.0);
}
);
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
glGenVertexArrays(1, &vaoObject);
glBindVertexArray(vaoObject);
float vertices[] =
{
0.75, 0.75, 0.0, 1.0,
0.75, -0.75, 0.0, 1.0,
-0.75, -0.75, 0.0, 1.0
};
GLuint vertexBufferObject;
initVertexBuffer(vertexBufferObject, vertices, sizeof(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
GLuint positionLocation = glGetAttribLocation(prog, "position");
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram( prog );
glBindVertexArray(vaoObject);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitContextVersion( 3, 1 );
glutInitContextProfile( GLUT_COMPATIBILITY_PROFILE );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
答案 1 :(得分:2)
glGenBuffers(1, &vertexBufferObject);
将顶点缓冲区的id保存在局部变量中。这个值在绘图调用中不再可用,并且不修改全局vertexBufferObject
(但缓冲区仍然存在 - 您只是丢失了它的ID并且不能再使用它了。甚至无法破坏它)