使用单个 GL_TRIANGLE_STRIP 的多维数据集
Cube using single GL_TRIANGLE_STRIP
是否可以仅使用一个 GL_TRIANGLE_STRIP
绘制整个立方体?
显然我在这里关心的只是立方体组合,它还不如拉伸成任何一种盒子或类似的物体。
是的,经过一些试验,我自己找到了答案。想象你的立方体的角是黑白交替的。沿着两个黑色角之间的每个面绘制三角形边。这样,对角线在立方体内部形成一个四面体。对于 [0,1]³ 立方体,可能的坐标序列如下:
Vertex Triangle Face
------+-----------+-----
0 0 0
0 1 0
1 0 0 000 010 100 **0
1 1 0 100 010 110 **0
1 1 1 100 110 111 1**
0 1 0 111 110 010 *1*
0 1 1 111 010 011 *1*
0 0 1 011 010 001 0**
1 1 1 011 001 111 **1
1 0 1 111 001 101 **1
1 0 0 111 101 100 1**
0 0 1 100 101 001 *0*
0 0 0 100 001 000 *0*
0 1 0 000 001 010 0**
来自 Evans、Skiena 和 Varshney 的论文 Optimizing Triangle Strips for Fast Rendering:
对于那些懒惰的人(比如我),这里是 rob mayoff 的答案的复制粘贴版本;)
static const GLfloat cube_strip[] = {
-1.f, 1.f, 1.f, // Front-top-left
1.f, 1.f, 1.f, // Front-top-right
-1.f, -1.f, 1.f, // Front-bottom-left
1.f, -1.f, 1.f, // Front-bottom-right
1.f, -1.f, -1.f, // Back-bottom-right
1.f, 1.f, 1.f, // Front-top-right
1.f, 1.f, -1.f, // Back-top-right
-1.f, 1.f, 1.f, // Front-top-left
-1.f, 1.f, -1.f, // Back-top-left
-1.f, -1.f, 1.f, // Front-bottom-left
-1.f, -1.f, -1.f, // Back-bottom-left
1.f, -1.f, -1.f, // Back-bottom-right
-1.f, 1.f, -1.f, // Back-top-left
1.f, 1.f, -1.f // Back-top-right
};
可能对某些人有用,这是一个几何着色器,它将接受一个点并输出一个单位立方体的三角形带
#version 410
layout(points) in;
layout(triangle_strip, max_vertices = 12) out;
uniform mat4 mvp;
void main() {
vec4 center = gl_in[0].gl_Position;
vec4 dx = mvp[0];
vec4 dy = mvp[1];
vec4 dz = mvp[2];
vec4 p1 = center;
vec4 p2 = center + dx;
vec4 p3 = center + dy;
vec4 p4 = p2 + dy;
vec4 p5 = p1 + dz;
vec4 p6 = p2 + dz;
vec4 p7 = p3 + dz;
vec4 p8 = p4 + dz;
gl_Position = p7;
EmitVertex();
gl_Position = p8;
EmitVertex();
gl_Position = p5;
EmitVertex();
gl_Position = p6;
EmitVertex();
gl_Position = p2;
EmitVertex();
gl_Position = p8;
EmitVertex();
gl_Position = p4;
EmitVertex();
gl_Position = p7;
EmitVertex();
gl_Position = p3;
EmitVertex();
gl_Position = p5;
EmitVertex();
gl_Position = p1;
EmitVertex();
gl_Position = p2;
EmitVertex();
gl_Position = p3;
EmitVertex();
gl_Position = p4;
EmitVertex();
}
此版本还有纹理坐标和法线,以备不时之需。
我用 WebGL 对此进行了测试,立方体的纹理映射正确,但由于每个角确实需要三个纹理坐标 - 每个面一个。因此,您可以使用这些 UV 对立方体的 4 个面进行纹理贴图,但顶部和底部将没有适当的纹理。
const Cube = function () {
const u0 = 0;
const u1 = 1;
const v0 = 0;
const v1 = 1 / 3;
const v2 = 2 / 3;
const v3 = 1;
const verticies = [
+1, +1, -1,
-1, +1, -1,
+1, -1, -1,
-1, -1, -1,
+1, +1, +1,
-1, +1, +1,
-1, -1, +1,
+1, -1, +1,
];
const uvs = [
u0, v3,
u0, v0,
u0, v2,
u0, v1,
u1, v3,
u1, v0,
u1, v1,
u1, v2,
];
const indexes = [3, 2, 6, 7, 4, 2, 0, 3, 1, 6, 5, 4, 1, 0];
const v = [];
const u = [];
for (var i = 0; i < indexes.length; i++) {
const corner = indexes[i];
v.push(verticies[corner * 3 + 0]);
v.push(verticies[corner * 3 + 1]);
v.push(verticies[corner * 3 + 2]);
u.push(uvs[corner * 2 + 0]);
u.push(uvs[corner * 2 + 1]);
}
return {
verticies: v,
uvs: u,
normals: v
};
};
上面提到的论文中三角形的缠绕方向错了,但是有没有简单的修正,将顶点的顺序颠倒,就会变成正面朝外(而不是向内)。
1 2 5 6 7 2 4 1 3 5 8 7 3 4
这是单位立方体的一组顶点。
您可以对此应用转换并渲染边界框(轴对齐或定向)。
static const std::array<float> cube_strip = {
+0.5, +0.5, -0.5, // Back-top-right
-0.5, +0.5, -0.5, // Back-top-left
+0.5, -0.5, -0.5, // Back-bottom-right
-0.5, -0.5, -0.5, // Back-bottom-left
-0.5, -0.5, +0.5, // Front-bottom-left
-0.5, +0.5, -0.5, // Back-top-left
-0.5, +0.5, +0.5, // Front-top-left
+0.5, +0.5, -0.5, // Back-top-right
+0.5, +0.5, +0.5, // Front-top-right
+0.5, -0.5, -0.5, // Back-bottom-right
+0.5, -0.5, +0.5, // Front-bottom-right
-0.5, -0.5, +0.5, // Front-bottom-left
+0.5, +0.5, +0.5, // Front-top-right
-0.5, +0.5, +0.5, // Front-top-left
};
是否可以仅使用一个 GL_TRIANGLE_STRIP
绘制整个立方体?
显然我在这里关心的只是立方体组合,它还不如拉伸成任何一种盒子或类似的物体。
是的,经过一些试验,我自己找到了答案。想象你的立方体的角是黑白交替的。沿着两个黑色角之间的每个面绘制三角形边。这样,对角线在立方体内部形成一个四面体。对于 [0,1]³ 立方体,可能的坐标序列如下:
Vertex Triangle Face
------+-----------+-----
0 0 0
0 1 0
1 0 0 000 010 100 **0
1 1 0 100 010 110 **0
1 1 1 100 110 111 1**
0 1 0 111 110 010 *1*
0 1 1 111 010 011 *1*
0 0 1 011 010 001 0**
1 1 1 011 001 111 **1
1 0 1 111 001 101 **1
1 0 0 111 101 100 1**
0 0 1 100 101 001 *0*
0 0 0 100 001 000 *0*
0 1 0 000 001 010 0**
来自 Evans、Skiena 和 Varshney 的论文 Optimizing Triangle Strips for Fast Rendering:
对于那些懒惰的人(比如我),这里是 rob mayoff 的答案的复制粘贴版本;)
static const GLfloat cube_strip[] = {
-1.f, 1.f, 1.f, // Front-top-left
1.f, 1.f, 1.f, // Front-top-right
-1.f, -1.f, 1.f, // Front-bottom-left
1.f, -1.f, 1.f, // Front-bottom-right
1.f, -1.f, -1.f, // Back-bottom-right
1.f, 1.f, 1.f, // Front-top-right
1.f, 1.f, -1.f, // Back-top-right
-1.f, 1.f, 1.f, // Front-top-left
-1.f, 1.f, -1.f, // Back-top-left
-1.f, -1.f, 1.f, // Front-bottom-left
-1.f, -1.f, -1.f, // Back-bottom-left
1.f, -1.f, -1.f, // Back-bottom-right
-1.f, 1.f, -1.f, // Back-top-left
1.f, 1.f, -1.f // Back-top-right
};
可能对某些人有用,这是一个几何着色器,它将接受一个点并输出一个单位立方体的三角形带
#version 410
layout(points) in;
layout(triangle_strip, max_vertices = 12) out;
uniform mat4 mvp;
void main() {
vec4 center = gl_in[0].gl_Position;
vec4 dx = mvp[0];
vec4 dy = mvp[1];
vec4 dz = mvp[2];
vec4 p1 = center;
vec4 p2 = center + dx;
vec4 p3 = center + dy;
vec4 p4 = p2 + dy;
vec4 p5 = p1 + dz;
vec4 p6 = p2 + dz;
vec4 p7 = p3 + dz;
vec4 p8 = p4 + dz;
gl_Position = p7;
EmitVertex();
gl_Position = p8;
EmitVertex();
gl_Position = p5;
EmitVertex();
gl_Position = p6;
EmitVertex();
gl_Position = p2;
EmitVertex();
gl_Position = p8;
EmitVertex();
gl_Position = p4;
EmitVertex();
gl_Position = p7;
EmitVertex();
gl_Position = p3;
EmitVertex();
gl_Position = p5;
EmitVertex();
gl_Position = p1;
EmitVertex();
gl_Position = p2;
EmitVertex();
gl_Position = p3;
EmitVertex();
gl_Position = p4;
EmitVertex();
}
此版本还有纹理坐标和法线,以备不时之需。
我用 WebGL 对此进行了测试,立方体的纹理映射正确,但由于每个角确实需要三个纹理坐标 - 每个面一个。因此,您可以使用这些 UV 对立方体的 4 个面进行纹理贴图,但顶部和底部将没有适当的纹理。
const Cube = function () {
const u0 = 0;
const u1 = 1;
const v0 = 0;
const v1 = 1 / 3;
const v2 = 2 / 3;
const v3 = 1;
const verticies = [
+1, +1, -1,
-1, +1, -1,
+1, -1, -1,
-1, -1, -1,
+1, +1, +1,
-1, +1, +1,
-1, -1, +1,
+1, -1, +1,
];
const uvs = [
u0, v3,
u0, v0,
u0, v2,
u0, v1,
u1, v3,
u1, v0,
u1, v1,
u1, v2,
];
const indexes = [3, 2, 6, 7, 4, 2, 0, 3, 1, 6, 5, 4, 1, 0];
const v = [];
const u = [];
for (var i = 0; i < indexes.length; i++) {
const corner = indexes[i];
v.push(verticies[corner * 3 + 0]);
v.push(verticies[corner * 3 + 1]);
v.push(verticies[corner * 3 + 2]);
u.push(uvs[corner * 2 + 0]);
u.push(uvs[corner * 2 + 1]);
}
return {
verticies: v,
uvs: u,
normals: v
};
};
上面提到的论文中三角形的缠绕方向错了,但是有没有简单的修正,将顶点的顺序颠倒,就会变成正面朝外(而不是向内)。
1 2 5 6 7 2 4 1 3 5 8 7 3 4
这是单位立方体的一组顶点。 您可以对此应用转换并渲染边界框(轴对齐或定向)。
static const std::array<float> cube_strip = {
+0.5, +0.5, -0.5, // Back-top-right
-0.5, +0.5, -0.5, // Back-top-left
+0.5, -0.5, -0.5, // Back-bottom-right
-0.5, -0.5, -0.5, // Back-bottom-left
-0.5, -0.5, +0.5, // Front-bottom-left
-0.5, +0.5, -0.5, // Back-top-left
-0.5, +0.5, +0.5, // Front-top-left
+0.5, +0.5, -0.5, // Back-top-right
+0.5, +0.5, +0.5, // Front-top-right
+0.5, -0.5, -0.5, // Back-bottom-right
+0.5, -0.5, +0.5, // Front-bottom-right
-0.5, -0.5, +0.5, // Front-bottom-left
+0.5, +0.5, +0.5, // Front-top-right
-0.5, +0.5, +0.5, // Front-top-left
};