glDrawElements崩溃(OpenGL 3.2/Windows 7) [英] glDrawElements crash (OpenGL 3.2 / Windows 7)
问题描述
我试图在OpenGL 3.2中绘制一个简单的四边形,但是当我调用"glDrawElements"时,应用程序崩溃并显示访问冲突读取位置0x00000000".
I'm trying to draw a simple quad in OpenGL 3.2 however the application crashes with "Access violation reading location 0x00000000" when I call "glDrawElements".
我认为问题是Vertex Buffer数据错误,但是我不确定如何解决此问题/对其进行调试(OpenGL跟踪非常棒,但我也不知道如何启用它……)
I assume the issue is that the Vertex Buffer data is wrong, but I am unsure how to fix the issue / debug it (an OpenGL trace would be fantastic but I do not know how to enable this either...)
初始化代码:
std::vector<CUShort> Indices;
const CUShort IndicesArray[] = { 0, 1, 2, 2, 0, 3 };
for(size_t j = 0; j < 1; j++) {
for(size_t i = 0; i < sizeof(IndicesArray) / sizeof(*IndicesArray); i++) {
Indices.push_back(4 * j + IndicesArray[i]);
}
}
glGenBuffers(1, &m_Elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Indices.size() * sizeof(CUShort), &Indices[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &m_Array);
glBindVertexArray(m_Array);
glGenBuffers(1, &m_Buffer);
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexColorVertex), NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_TRUE, sizeof(TexColorVertex), (const GLvoid*)offsetof(TexColorVertex, Color));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexColorVertex), (const GLvoid*)offsetof(TexColorVertex, Position));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(TexColorVertex), (const GLvoid*)offsetof(TexColorVertex, Texcoord));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
绘图代码:
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
TexColorVertex Vertices[4];
glm::vec4 SpritePos = glm::vec4(0, 0, 1024.0f, 384.0f);
Vertices[0].Position = glm::vec2(SpritePos.x, SpritePos.y);
Vertices[1].Position = glm::vec2(SpritePos.x, SpritePos.w);
Vertices[2].Position = glm::vec2(SpritePos.z, SpritePos.w);
Vertices[3].Position = glm::vec2(SpritePos.z, SpritePos.y);
Color Kittens = Color::HotPink();
Vertices[0].Color = glm::vec4(Kittens.R(), Kittens.G(), Kittens.B(), 1.0f);
Vertices[1].Color = glm::vec4(Kittens.R(), Kittens.G(), Kittens.B(), 1.0f);
Vertices[2].Color = glm::vec4(Kittens.R(), Kittens.G(), Kittens.B(), 1.0f);
Vertices[3].Color = glm::vec4(Kittens.R(), Kittens.G(), Kittens.B(), 1.0f);
Vertices[0].Texcoord = glm::vec2(0.0f, 0.0f);
Vertices[1].Texcoord = glm::vec2(0.0f, 1.0f);
Vertices[2].Texcoord = glm::vec2(1.0f, 1.0f);
Vertices[3].Texcoord = glm::vec2(1.0f, 0.0f);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(Vertices), sizeof(Vertices), Vertices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Elements);
glBindVertexArray(m_Array);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLvoid*)0);
顶点结构声明如下:
struct TexColorVertex
{
TexColorVertex(void) { }
TexColorVertex(glm::vec2 const& Position, glm::vec2 const& Texcoord) :
Position(Position), Texcoord(Texcoord)
{ }
glm::vec2 Position;
glm::vec2 Texcoord;
glm::vec4 Color;
};
有人对如何解决这个问题并绘制一个占据屏幕一半的简单四边形有任何建议吗?
Does anyone have any suggestions on how to fix this and draw a simple quad that takes up half the screen?
推荐答案
虽然 user3256930 确实提出了关于缓冲区的分配大小,实际上并不是崩溃的原因.
While user3256930 does bring up a valid point about the allocated size of your buffer, that is actually not the cause of your crash.
问题不是glDrawElements (...)
时出现了.该调用尝试取消引用 NULL 指针,该指针是一个红色标记,表示没有任何内容绑定到GL_ELEMENT_ARRAY_BUFFER
.
The problem is not with glBufferSubData (...)
, but rather with the call to glDrawElements (...)
. This call is attempting to dereference a NULL pointer, which is a red flag that nothing is bound to GL_ELEMENT_ARRAY_BUFFER
.
当没有任何内容绑定到GL_ELEMENT_ARRAY_BUFFER
时,传递给glDrawElements (...)
的指针实际上是指向客户端内存的指针,而不是到Buffer Object( server >)内存.
When nothing is bound to GL_ELEMENT_ARRAY_BUFFER
, then the pointer you pass to glDrawElements (...)
is an actual pointer to client memory rather than an offset into Buffer Object (server) memory.
- 顶点属性状态[指针,启用/禁用]
- 元素数组缓冲区绑定 (
GL_ELEMENT_ARRAY_BUFFER
)
现在,考虑这两个调用的顺序:
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, m_Elements);
glBindVertexArray (m_Array);
首先,您将某些内容绑定到GL_ELEMENT_ARRAY_BUFFER
( m_Elements ),然后立即绑定一个顶点数组对象( m_Array ),该对象将替换您刚绑定的元素数组缓冲区通过绑定,它可以在内部进行跟踪.
First you bind something to GL_ELEMENT_ARRAY_BUFFER
(m_Elements) and immediately afterwards you bind a Vertex Array Object (m_Array), which replaces the element array buffer you just bound with the binding it keeps track of internally.
您应该考虑(1)使用VAO持久引用单个元素数组缓冲区,或者(2)颠倒这两个调用的顺序.
You should consider either (1) using your VAO to persistently reference a single element array buffer or (2) reversing the order of these two calls.
如果您的顶点数组对象"( m_Array )将始终与相同的元素数组缓冲区一起使用,那么我建议您使用第一种方法.只需在初始化中移动以下代码即可实现:
If your Vertex Array Object (m_Array) will always be used with the same element array buffer, then I would suggest you use the first approach. This can be implemented simply by moving the following code in your initialization:
glGenVertexArrays (1, &m_Array);
glBindVertexArray (m_Array);
要 之前 :
To come before:
glGenBuffers (1, &m_Elements);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, m_Elements);
glBufferData (GL_ELEMENT_ARRAY_BUFFER, Indices.size() * sizeof(CUShort), &Indices[0], GL_STATIC_DRAW);
使用这种方法,无需在图形代码中将任何内容明确绑定到GL_ELEMENT_ARRAY_BUFFER
.
With this approach, nothing needs to be explicitly bound to GL_ELEMENT_ARRAY_BUFFER
in your drawing code.
这篇关于glDrawElements崩溃(OpenGL 3.2/Windows 7)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!