gpt4 book ai didi

c++ - 使用VBO通过加载波前对象绘制立方体

转载 作者:行者123 更新时间:2023-11-30 05:01:16 25 4
gpt4 key购买 nike

我需要使用 VBO 通过加载波前对象来绘制立方体。通过绘制三角形。这是对象:

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 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
f 2//1 3//1 1//1
f 4//2 7//2 3//2
f 8//3 5//3 7//3
f 6//4 1//4 5//4
f 7//5 1//5 3//5
f 4//6 6//6 8//6
f 2//1 4//1 3//1
f 4//2 8//2 7//2
f 8//3 6//3 5//3
f 6//4 2//4 1//4
f 7//5 5//5 1//5
f 4//6 2//6 6//6

我还有一个自己填充的更酷的数组,它等于面数的 3 倍,即 36 个索引

float colours[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
}

我将我的顶点、法线、颜色信息存储到绑定(bind)到 VBO 缓冲区的数组中:

 float* vbo = new float[78]

按照vertices|normals|colours的顺序就是24indices|18indices|36indices,我测试过效果很好

我使用另一个数组来存储顶点索引信息,它是 36indices ,例如: f 2//1 3//1 1//1 我在我的数组中存储为 2/3/1

 int *element = new int[36];

我已经测试过它运行良好,我将我的 vbo 初始化如下:

 static void init(void){
.......
Gluint vbo_id,index_id;

glGenBuffers(1,&vbo_id);
glGenBuffers(1,&index_id);
glBindBuffer(GL_ARRAY_BUFFER,vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);

glBufferData(GL_ARRAY_BUFFER,sizeof(vbo),vbo,GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(element),element,GL_STATIC_DRAW); }

我的画在这里

 static void display(void){
.......
glBindBuffer(GL_ARRAY_BUFFER,vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3,GL_FLOAT,0,0);
glNormalPointer(GL_FLOAT,0,(void*)(24*sizeof(float)));//binding
glColorPointer(3,GL_FLOAT,0,(void*)(42*sizeof(float)));

for(int i=0;i<12;i++){

glBegin(GL_TRIANGLES);
glArrayElement(element[i]);
glArrayElement(element[i+1]);
glArrayElement(element[i+2]);
glEnd();

}
/* have try this one too:
glDrawElements(GL_TRIANGLES,3,GL_INT,0) */


glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
}

但是屏幕上什么也没有显示。我的绑定(bind)方法是否正确,当我用索引绘制时,我的导师告诉我,如果我绑定(bind)顶点和法线,并且颜色正确,它将通过绘制顶点索引自动匹配。

最佳答案

vbo的类型是float*,所以sizeof(vbo)不是数组的大小,其中vbo 指向,但它是指针的大小。参见 sizeof .
注意,glBufferData的第3个参数必须是以字节为单位的缓冲区大小。

float* vbo = new float[78] 的大小为 78 * sizeof(float)78 * sizeof(*vbo)
int *element = new int[36] 的大小为 36 * sizeof(int)36 * sizeof(*element)< br/>但 sizeof(vbo) 是指向数组的指针的大小或与 sizeof(float*) 相同。

这意味着您必须像这样更改代码:

glBufferData(GL_ARRAY_BUFFER, 78*sizeof(float), vbo, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36*sizeof(int), element, GL_STATIC_DRAW);

glDrawElements的第二个参数必须是索引的数量,第三个参数必须是 GL_UNSIGNED_BYTEGL_UNSIGNED_SHORTGL_UNSIGNED_INT,具体取决于索引的数据类型:

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);

请注意,对于索引数组(元素)的数据类型,您应该更喜欢使用unsigned int * 而不是int*


你的假设是错误的。您不能将 24 个顶点坐标、18 个法 vector 和 36 种颜色与不同的索引数组直接混合在一个 Vertex Array Object 中。 .

每个顶点位置的顶点属性构成一组数据。这意味着您必须创建顶点坐标、法 vector 和颜色的元组。

进一步查看 Rendering meshes with multiple indices

我建议使用 std::vector并以某种方式这样做:

#include <vector>

// 8  vertex coordiantes: 8 * 3 float 
std::vector<float> v{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f };

// 6 normal vectors: 6 * 3 float
std::vector<float> nv{
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f };

// 12 colors coordiantes: 12 * 3 float
std::vector<float> c{
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f };

// 12 faces 3*2 indices/face: 12 * 3 * 2 unsigned int 
std::vector<unsigned int> indices{
2, 1, 3, 1, 1, 1,
4, 2, 7, 2, 3, 2,
8, 3, 5, 3, 7, 3,
6, 4, 1, 4, 5, 4,
7, 5, 1, 5, 3, 5,
4, 6, 6, 6, 8, 6,
2, 1, 4, 1, 3, 1,
4, 2, 8, 2, 7, 2,
8, 3, 6, 3, 5, 3,
6, 4, 2, 4, 1, 4,
7, 5, 5, 5, 1, 5,
4, 6, 2, 6, 6, 6 };

创建顶点数组数据

// final vertex attributes 12 * 3 *(3 + 3 + 3) floats
// x0 y0 z0 nvx0 nvy0 nvz0 cr0 cg0 cb0
// x1 y1 z1 nvx1 nvy1 nvz1 cr1 cg1 cb1
std::vector<float> va;

const unsigned int no_of_faces = 12;
for (unsigned int f=0; f<no_of_faces; ++f )
{
for (unsigned int t=0; t<3; ++t )
{
unsigned int vi = indices[(f*3+t)*2]-1; // vertex index
unsigned int ni = indices[(f*3+t)*2+1]-1; // normal vector index
unsigned int ci = f; // color index

va.insert(va.end(), v.begin() + vi*3, v.begin() + vi*3+3); // insert vertex coordinate
va.insert(va.end(), nv.begin() + ni*3, nv.begin() + ni*3+3); // insert normal vector
va.insert(va.end(), c.begin() + ci*3, c.begin() + ci*3+3); // insert color
}
}

创建 Vertex Buffer Object :

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, va.size()*sizeof(*va.data()), va.data(), GL_STATIC_DRAW );

定义通用顶点属性数据的数组:

glVertexPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glNormalPointer( GL_FLOAT, 9*sizeof(*va.data()), (void*)(3*sizeof(*va.data())) );
glEnableClientState( GL_NORMAL_ARRAY );
glColorPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), (void*)(6*sizeof(*va.data())) );
glEnableClientState( GL_COLOR_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

绘制数组:

glDrawArrays( GL_TRIANGLES, 0, 36 );

预览:

cube

关于c++ - 使用VBO通过加载波前对象绘制立方体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50376506/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com