我在openGL的固定管道上花费了很多时间,最近我开始学习可编程管道。我知道我的painter和shader类不是问题,因为它们可用于固定功能管道。我似乎无法让glDrawArrays终其一生。
我不确定我的错误是否在于我如何在着色器中或其他地方设置顶点缓冲区对象。我也调试了我的代码并在整个显示函数中设置了断点,它似乎永远不会超过glDrawArrays(),(即它在glDrawArrays处遇到了一个断点,但以后都没有见到,不确定为什么。)
输出的只是白屏,没有别的。
这是我的代码:
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;
}
片段着色器:
#version 140
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 0.0, 1.0, 1.0);
}
编辑:代码已根据Joey Dewd,keltar和genpfault的建议进行了更新。
我不再卡在glDrawArrays上,也就是说,我不再是白色屏幕,而是黑色屏幕。这使我认为我的缓冲区仍然无法正确设置。或者可能是我缺少顶点数组缓冲区初始化(vaoObject)所需的其他东西?
最佳答案
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)
。您需要传递一个单独的size参数:
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;
}
关于c++ - glDrawArrays意外行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22598820/