c++ - 为什么顶点数组对象会导致错误?
问题描述
我有一个可以工作的opengl程序......直到我尝试使用顶点数组对象。我已经尝试来回更改代码好几天了,但找不到问题所在。
这是代码的一部分。glCall(...) 是一个用于错误检查的辅助函数。
static struct {
GLint color;
GLuint vertices;
GLuint mvpMatrix;
const char * vertexCode =
R"___(
#version 330 core
in vec4 vPosition;
uniform vec4 uColor;
uniform mat4 mvp_matrix;
out vec4 fColor;
void main() {
gl_Position = mvp_matrix * vPosition;
fColor = uColor;
}
)___";
const char * fragmentCode =
R"__(
#version 330 core
in vec4 fColor;
out vec4 FragColor;
void main() {
gl_FragColor = fColor;
})__";
} program1;
static Matrix<float> mvpMatrix;
static double screenWidth, screenHeight;
static ShaderProgram squareShaderProgram;
static GLuint vertexArray;
static GLuint vertexBuffer;
//Square
static const vector<float> squareVertices = { 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 1.f };
static const vector<float> squareColors = {.8, .8, 1., 1};
static void setDimensions(double width, double height){
screenWidth = width;
screenHeight = height;
}
static bool initDrawModule(double width, double height) {
//GLuint vao; <----------------------- //This seems to be the problem
//glCall(glGenVertexArrays(1, &vao));
//glCall(glBindVertexArray(vao));
squareShaderProgram.initProgram(program1.vertexCode, program1.fragmentCode);
if (!squareShaderProgram.getProgram()) {
cerr << "Could not create shader program in " << __FILE__ << ":" << __LINE__ << endl;
return false;
}
glCall(squareShaderProgram.use());
program1.vertices = squareShaderProgram.getAttribute("vPosition");
program1.color = squareShaderProgram.getUniform("uColor");
program1.mvpMatrix = squareShaderProgram.getUniform("mvp_matrix");
setDimensions(width, height);
return false;
}
static void drawSquare(Vec p, double a, double sx, double sy){
squareShaderProgram.use();
{
mvpMatrix = mvpMatrix.RotationZ(a / 180.);
mvpMatrix.scale(sx, sy, 1);
mvpMatrix.scale(1. / screenWidth, 1. / screenHeight, 1);
mvpMatrix.setTranslation(
p.x / screenWidth * 2 - 1.,
p.y / screenHeight * 2 - 1.,
p.z
);
glCall(glUniformMatrix4fv(program1.mvpMatrix, 1, GL_FALSE, mvpMatrix));
}
glCall(glEnableVertexAttribArray(program1.vertices));
glCall(glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer))
glCall(glVertexAttribPointer( //<----- this fails
program1.vertices,
2,
GL_FLOAT,
GL_FALSE,
0,
&squareVertices[0]));
glCall(glUniform4fv(program1.color, 1, &squareColors[0]));
glCall(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
glDisableVertexAttribArray(program1.vertices);
}
static void render() {
static float x = 0;
drawSquare(Vec(.1 + x, 50, 1), 20 + x * 2, 100,100);
x += 20;
}
bool init() {
return initDrawModule(512, 512);
}
void die(string message);
void checkSDLError(int line = -1);
int main(int argc, char *argv[])
{
SDL_Window *mainwindow;
SDL_GLContext maincontext;
// Create our window centered at 512x512 resolution
mainwindow = SDL_CreateWindow("sdl-window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!mainwindow) {
die("Unable to create window");
}
checkSDLError(__LINE__);
maincontext = SDL_GL_CreateContext(mainwindow);
checkSDLError(__LINE__);
init();
SDL_GL_SetSwapInterval(1);
for (int i = 0; i < 10; ++i) {
glClearColor ( 0.1 * i, 0.0, 0.0, 1.0 );
glClear ( GL_COLOR_BUFFER_BIT );
render();
SDL_GL_SwapWindow(mainwindow);
SDL_Delay(200);
}
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(mainwindow);
SDL_Quit();
return 0;
}
我唯一知道的是,当我取消注释 initDrawModule() 开头的行时,glVertexAttribPointer(在代码中标记)失败并显示“GL_INVALID_OPERATION”。到底是怎么回事?
解决方案
GL_INVALID_OPERATION
是由 的最后一个参数,glVertexAttribPointer
指向数据的指针引起的。
在兼容性配置文件中,如果顶点缓冲区对象 0 已绑定,则 的最后一个参数glVertexAttribPointer
被视为指向顶点数组数据的指针。
如果绑定了命名的顶点缓冲区对象,则 的最后一个参数glVertexAttribPointer
是此缓冲区内的偏移量。
你混合了这两种情况,你绑定了一个命名缓冲区对象,但你也传递了一个指向顶点数组数据的指针:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(program1.vertices, 2, GL_FLOAT, GL_FALSE, 0, &squareVertices[0]);
如果要使用顶点缓冲区对象,则必须使用glBufferData
来创建和初始化缓冲区对象的数据存储:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLsizeiptr size_in_bytes = ...; // size of the buffer data in bytes
glBufferData(GL_ARRAY_BUFFER, size_in_bytes, &squareVertices[0], GL_STATIC_DRAW);
命名顶点缓冲区可用于定义通用顶点属性数据数组:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(program1.vertices, 2, GL_FLOAT, GL_FALSE, 0, NULL);
另请参见顶点缓冲区对象。
推荐阅读
- .net-core - 如何在 gremlin.net 中更新/添加顶点属性
- python - 使用 PIL 和 BytesIO 通过 python 中的套接字发送图像时,图像似乎被随机截断
- autodesk-forge - Forge Viewer BoxSelection Extension - 如何设置选择的深度
- java - 在独立的本地环境中运行 solr start (SOLR 8) 时出现 javax.naming.NoInitialContextException
- angular - 如何测试订阅的价值变化?
- r - 在 rmarkdown 的 ggplot 中为 pdf ( 乳胶 ) 添加希腊字母
- android-studio - 使用 android FFMPEG 库处理有限的视频帧
- excel - 使用 VBA 宏处理然后删除 html/xml 标记
- r - 如何将 RStudio 连接到 OneDrive Excel 文件?
- python - 无法使用 CBV 提交 ModelForm