我需要一些帮助来制定正确的算法,用数据填充顶点浮点缓冲区数组。。。
由于在我的设置中,每个顶点都有9个属性(XYZ、UV、RGBA),并且我使用四边形进行绘制,因此每个面总共有36个索引。我正在画立方体,所以这是6个面,总共有216(9*4*6)个索引。而不是仅仅迭代缓冲区来填充以下内容:
public void AddVertex(int x, int y, int z, float u, float v, Color4 color)
{
if (vCount >= vertex_data.Length)
return;
else
{
vertex_data[vCount++] = x;
vertex_data[vCount++] = y;
vertex_data[vCount++] = z;
vertex_data[vCount++] = u;
vertex_data[vCount++] = v;
vertex_data[vCount++] = color.R;
vertex_data[vCount++] = color.G;
vertex_data[vCount++] = color.B;
vertex_data[vCount++] = color.A;
}
}
我想使用偏移量直接针对GPU上要更新的缓冲区中的位置(通过使用BufferSubData)。然而,问题是将立方体(XYZ)的相对位置值转换为缓冲区数组中的位置,这样我就可以更新它的值。
这就是我迭代立方体的方式,以及我试图获得正确位置的方式。。。
for (int x = 0; x < Chunk.DEFAULT_SIZE; x++)
{
for (int y = 0; y < Chunk.DEFAULT_SIZE; y++)
{
for (int z = 0; z < Chunk.DEFAULT_SIZE; z++)
{
<...>
offset = (x + size * (y + size * z)) * 216;
SetVertex(offset, face_i.X + absX, face_i.Y + absY, face_i.Z + -absZ, u, v, color);
//SetVertex (...) would be called 3 more times, and "offset" would be supplemented by 0,9,18, and 27 (totalling 36 indices).
<...>
}
}
}
我甚至尝试过对XYZ值进行位偏移:
int offset = 216 * (x<<10) + 216 * (y<<5) + 216*z;
这只在某些情况下有效。我是不是走错了路?上面代码的结果只创建了多维数据集的底面,但它确实以所有正确的间隔创建了它们。
我要做的第一件事是编写代码,在给定坐标、面和顶点的情况下,为您提供要修改的顶点地址的偏移量。这将为您在寻址数据指针时省去很多麻烦。这可能看起来像这样:
size_t get_offset(int x, int y, int z, face_enum face, vertex_enum vertex) {
size_t x_offset = x * Chunk.DEFAULT_SIZE * Chunk.DEFAULT_SIZE;
size_t y_offset = y * Chunk.DEFAULT_SIZE;
size_t z_offset = z;
size_t cube_offset = x_offset + y_offset + z_offset;
size_t face_offset = convert_face_enum_to_index(face); //I'm here assuming that all the possible enums map to indexes in the range [0,5]
size_t quad_offset = cube_offset * 6 + face_offset; //Multiplied by six for six faces
size_t vertex_offset = convert_vertex_enum_to_index(vertex); //I'm here assuming that all the possible enums map to indexes in the range [0,3]
size_t vertex_location = quad_offset * 4 + vertex_offset; //Multiplied by four for four vertices per quad.
const size_t num_of_floats_per_vertex = 9; //Based on your problem description, this should be correct
return vertex_location * num_of_floats_per_vertex;
}
public void modify_vertex(float * location, float x, float y, float z, float u, float v, Color4 color) {
location[0] = x;
location[1] = y;
location[2] = z;
location[3] = u;
location[4] = v;
location[5] = color.R;
location[6] = color.G;
location[7] = color.B;
location[8] = color.A;
}
如果所有添加或修改顶点数据的尝试都是以这种方式完成的,这将使您的生活更加简单。一旦你完成了这项工作,你就可以编写这样的代码:
for(cube qube : cubes) { //Depends on your implementation. If you've literally stored all the cubes in a cube[][][] array, then the triple-nested code you wrote above would be adequate.
for(face_enum face = FACE0; face <= FACE5; face++) { //I'm assuming that face_enum has an increment operator; this may need to be adjusted depending on what you write.
for(vertex_enum vertex = VERTEX0; vertex <= VERTEX3; vertex++) { //same deal here.
size_t vertex_offset = get_offset(qube.x, qube.y, qube.z, face, vertex);
float * data_offset = my_mapped_vertex_buffer + vertex_offset;
modify_vertex(data_offset, /*insert appropriate data here*/);
}
}
}
然后,只要正确设置了顶点缓冲区对象(以及所有相关的属性指针),这将以一致且易于修改的方式(从程序员的角度来看)存储所有相关的渲染数据。
当然,您必须确保顶点缓冲区足够大,可以存储每个多维数据集,但这仍然是旧代码的问题。