我今天刚开始从本教程开始学习OpenGL:http://openglbook.com/the-book/
我到了第2章,在那里画了一个三角形,我理解除了VAO之外的一切(这个首字母缩略词好吗?).本教程有以下代码:
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
Run Code Online (Sandbox Code Playgroud)
虽然我知道代码是必要的,但我不知道它的作用.虽然我从不使用VaoId(除了销毁它),但如果没有它,代码就无法运行.我假设这是因为它需要被绑定,但我不知道为什么.这个确切的代码是否只需要成为每个OpenGL程序的一部分?该教程将VAO解释为:
顶点数组对象(或VAO)是描述顶点属性如何存储在顶点缓冲区对象(或VBO)中的对象.这意味着VAO不是存储顶点数据的实际对象,而是顶点数据的描述符.顶点属性可以通过glVertexAttribPointer函数及其两个姐妹函数glVertexAttribIPointer和glVertexAttribLPointer来描述,我们将在下面探讨其中的第一个.
我不明白VAO如何描述顶点属性.我没有以任何方式描述它们.它是否从glVertexAttribPointer获取信息?我想这一定是它.VAO只是glVertexAttribPointer信息的目的地吗?
另外,我遵循的教程是否可以接受?有什么我应该注意的或更好的教程可以遵循?
我最近写一些的OpenGL 3.3代码与顶点数组对象(VAO)并测试它以后英特尔图形适配器,我发现,我感到失望,该元件阵列缓冲器结合显然不是VAO状态的一部分,作为呼叫:
glBindVertexArray(my_vao);
glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_INTEGER, 0);
Run Code Online (Sandbox Code Playgroud)
没有效果,而:
glBindVertexArray(my_vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, my_index_buffer); // ?
glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_INTEGER, 0);
Run Code Online (Sandbox Code Playgroud)
渲染几何体.我认为这是在英特尔执行的OpenGL(因为它是在GL_ARB_vertex_array_object即使在GL_OES_vertex_array_object明确提出(和)该元素阵列的一个单纯的错误是保存状态的一部分),但随后在移动的NVIDIA Quadro 4200发生这不好玩.
它是我的代码中的驱动程序错误,规格错误或错误吗?代码在GeForce 260和480上完美运行.
有没有类似的经历?
什么也奇怪的是,GL_EXT_direct_state_access不具有结合元件阵列缓冲器到VAO的函数(但是它确实有功能来指定顶点ATTRIB阵列,因此阵列缓冲器).GPU制造商是否违反规范并欺骗我们,或者是什么?
编辑:
我原本不打算显示任何源代码,因为我认为这里没有必要.但是根据要求,这是重现问题的最小测试用例:
static GLuint n_vertex_buffer_object, p_index_buffer_object_list[3];
static GLuint p_vao[2];
bool InitGLObjects()
{
const float p_quad_verts_colors[] = {
1, 0, 0, -1, 1, 0,
1, 0, 0, 1, 1, 0,
1, 0, 0, 1, -1, 0,
1, 0, 0, -1, -1, 0, // red quad
0, 0, 1, -1, 1, 0,
0, 0, 1, …Run Code Online (Sandbox Code Playgroud) 有人会关心解释VertexBuffer,VertexArray,VertexBufferObject和VertexArrayObject之间的区别吗?我甚至不确定这些是否是针对不同事物的所有术语,但我已经看到它们都出现在OpenGL规范中.
我知道VertexBuffer只包含顶点而没有其他任何东西,一旦绑定,一旦我设置了顶点指针,我就可以使用DrawArrays来绘制它.我已经多次这样做了.
我正在使用我认为的VertexArray,它存储所设置的任何顶点缓冲区的状态,以及任何顶点指针.绑定VertexArray会自动绑定顶点缓冲区并设置顶点指针.我也成功地使用了这个(大部分).
但什么是VertexBufferObject和VertexArrayObject?他们更好吗?VertexArray不能给我我需要的一切吗?
我正在努力用顶点数组制作一些中等简单的形状,我正在取得一些进展,但现在我想绘制2个(或更多)三角形扇形对象.有没有办法只打一个电话gl.glDrawArrays(GL.GL_TRIANGLE_FAN,...或者我是否需要为每个粉丝单独打电话?
Wikipedia的Triangle strip文章描述了一种叫做原始重启的东西,但是OpenGL的Vertex规范让我觉得这不适用于顶点数组.
绘制多个三角扇的正确方法是什么?这是我目前的绘制方法:
public void draw(GL gl){
if(vertices.length == 0)
return;
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
gl.glColorPointer(3, GL.GL_FLOAT, 0, colorBuff);
gl.glNormalPointer(GL.GL_FLOAT,0, normalBuff);
// drawArrays count is num of points, not indices.
gl.glDrawArrays(GL.GL_TRIANGLES, 0, triangleCount);
gl.glDrawArrays(GL.GL_QUADS, triangleCount, quadCount);
gl.glDrawArrays(GL.GL_TRIANGLE_FAN, triangleCount+quadCount, fanCount);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_COLOR_ARRAY);
gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
}
Run Code Online (Sandbox Code Playgroud)
我更新了相关的抽奖部分,如下所示:
for(int i = 0; i < fanLength.length; i++){
gl.glDrawArrays(GL.GL_TRIANGLE_FAN,
triangleCount+quadCount+fanDist[i], fanLength[i]);
}
Run Code Online (Sandbox Code Playgroud)
fanDist是此风扇启动的偏移量(从风扇的起点开始),fanLength是此风扇的长度.
这看起来确实有用,这很好,但是,这是正确的方法吗?有没有更好的办法?
我试图绘制地形与GL_TRIANGLE_STRIP和glDrawElements,但我有一个很艰难的时间去了解背后的东西指数glDrawElements...
这是我到目前为止所拥有的:
void Terrain::GenerateVertexBufferObjects(float ox, float oy, float oz) {
float startWidth, startLength, *vArray;
int vCount, vIndex = -1;
// width = length = 256
startWidth = (width / 2.0f) - width;
startLength = (length / 2.0f) - length;
vCount = 3 * width * length;
vArray = new float[vCount];
for(int z = 0; z < length; z++) {
// vIndex == vIndex + width * 3 || width * 3 = 256 * …Run Code Online (Sandbox Code Playgroud) 我目前正在使用与Superbible第5版一起提供的GLTools课程.我正在查看GLTriangleBatch类,它具有以下代码:
// Create the master vertex array object
glGenVertexArrays(1, &vertexArrayBufferObject);
glBindVertexArray(vertexArrayBufferObject);
// Create the buffer objects
glGenBuffers(4, bufferObjects);
#define VERTEX_DATA 0
#define NORMAL_DATA 1
#define TEXTURE_DATA 2
#define INDEX_DATA 3
// Copy data to video memory
// Vertex data
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_VERTEX);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pVerts, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Normal data
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_NORMAL);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pNorms, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[TEXTURE_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*2, pTexCoords, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_TEXTURE0, 2, …Run Code Online (Sandbox Code Playgroud) opengl collision-detection vertex-buffer vertex vertex-array
哪个是立方体纹理的最佳方式(最低内存,最快速度)?过了一会儿,我找到了这个解决方案:
数据结构:
GLfloat Cube::vertices[] =
{-0.5f, 0.0f, 0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 1.0f, 0.5f, -0.5f, 1.0f, 0.5f,
-0.5f, 1.0f, -0.5f, 0.5f, 1.0f, -0.5f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, -0.5f,
0.5f, 0.0f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 1.0f, -0.5f, 0.5f, 1.0f, 0.5f,
-0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 1.0f, 0.5f, -0.5f, 1.0f, -0.5f
};
GLfloat Cube::texcoords[] = { 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0,
0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0,
0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0,
0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0
};
GLubyte Cube::cubeIndices[24] = {0,1,2,3, 4,5,6,7, …Run Code Online (Sandbox Code Playgroud) 人们总是告诉我至少使用顶点阵列.但我认为这不是一个好主意,因为我正在使用glPushMatrix()它glTranslatef/glRotatef来定位3d世界中的对象.
那么,我应该停止使用glPushMatrix()并"手动"计算世界中旋转/移动的顶点位置,然后将它们的顶点数据推入顶点数组然后立即渲染它们吗?
但是,当我为屏幕上的所有对象使用不同的纹理表面时,所有这些都会变得更加混乱,这些对象也是深度排序的.
所以:
我做得对吗?
另外,我应该如何为我要排序的对象设计数据结构?例如,std::vector用于存储每个对象的顶点数据是否合适?还是有更好的选择吗?我当时认为std::vector存储所有这些数据看起来像:
struct GameObject {
int TexID;
float z; // we will sort by this
vector<VTCNStruct> VertexData; // store each point of the object here (including color/normal/texcoord points).
};
vector<GameObject> GameObjectBuffer; // push all sortable objects here
Run Code Online (Sandbox Code Playgroud)
此外,在步骤4:std::vector在这种情况下是否可以使用已经存在的?我有这个想法,我必须使用原始数组,比如new float[100]将顶点数组发送到我的GPU,或者我可以某种std::vector方式(有效地)以某种方式使用我已经存在的排序,而不是每次纹理ID更改时都创建新的缓冲区?
我试图让我的渲染功能工作.我正在使用顶点数组.这是我的顶点结构.
struct Vertex
{
float x, y, z; // The x, y and z floating point values
float u, v; // The u - v texture coordinates
float padding[3]; // needs to be multiple of 32
};
Run Code Online (Sandbox Code Playgroud)
这是我的渲染代码:
// Render the mesh
void WLD::render(GLuint* textures, long curRegion, CFrustum cfrustum)
{
int num = 0;
// Set up my indices
GLuint indicies[3];
// Cycle through the PVS
while(num < regions[curRegion].visibility.size())
{
int i = regions[curRegion].visibility[num];
if(!regions[i].dead && regions[i].meshptr != NULL)
{ …Run Code Online (Sandbox Code Playgroud) 我编写了一个无法正常工作的 C++ Obj 文件加载器。问题是在解析一个简单的 obj 文件时,如下所示:
# Blender v2.62 (sub 0) OBJ File: ''
# www.blender.org
mtllib cube.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn -1.000000 -0.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn 1.000000 -0.000000 0.000000
vn 1.000000 0.000000 0.000001
vn -0.000000 1.000000 0.000000
vn 0.000000 -1.000000 0.000000 …Run Code Online (Sandbox Code Playgroud)