让我指导您解决我可以立即在该代码中看到的明显错误。
首先明显的第一个错误:您声称要绘制100 点,但您的dots_vert 数组只有99 元素长。这在以下循环中重复,您从0 到98 总共99 次。
首先:
GLfloat dots_vert[100];
for (int i = 0; i < 100; ++i)
{
[...]
}
这里还有一个巨大的错误,但我们会留到以后,让我们现在继续。
第二个错误是关于OpenGL API和计算机图形学的知识。首先,您的目标是将点数传递给 GPU,因此您需要 glVertexAttribPointer 函数,这就是您想出来的。你想做的第一件事就是look at the glVertexAttribPointer reference documentation,这样你就知道你需要什么了。你需要一个index、一个size、一个type、一个normalized标志、一个stride和一个offset。
让我们看看参考文档对size 参数的描述:
尺寸
指定每个通用顶点属性的组件数。必须是 1、2、3、4。此外,glVertexAttribPointer 接受符号常量 GL_BGRA。初始值为 4。
这对于确定您尝试传递给 GPU 的数据类型至关重要。您将参数设置为3,这意味着您有一个x、一个y 和一个z。但前面的代码与此相矛盾。对于初学者,您的dots_vert 数组的长度为100 元素,并且您想绘制100 点,因此每个点有足够的100/100 = 1 组件,而不是3。但更糟糕的是,for 循环的内部与此更矛盾,所以让我们回过头来检查我之前提到的错误。
错误三:您的for 循环由if {} else {} 语句组成,如果循环的索引为偶数(@987654353 @),否则为 -50.0f 和 50.0f 之间的随机值。假设每个点都有1 分量,这意味着您只生成x 坐标,因此您在单个维度中工作。
显然这不是您打算做的,还因为您的一半积分将是0.0f,因此它们都会重叠。所以我假设您试图为x 和y 生成一个随机值,并将z 设置为0.0f,这样会更有意义。首先,每个点都有3 组件,因此您需要一个包含100*3 = 300 元素的数组。所以首先,让我们修复之前的代码:
GLfloat dots_vert[300];
for (int i = 0; i < 300; ++i)
{
[...]
}
好多了。现在我们需要为每个点生成一个随机的x 和y valye,并将z 设置为0.0f,因为我们不需要它。您想在一个循环中一次完成所有组件,因此您希望您的循环逐步通过3,而不是1,所以让我们再次修复之前的代码:
GLfloat dots_vert[300];
for (int i = 0; i < 300; i += 3)
{
[...]
}
现在我们可以在一个循环中同时生成x、y 和z。这是理解计算机图形如何工作的关键部分,特别是在 OpenGL API 的上下文中。 OpenGL 使用坐标系,原点在屏幕中间,x 轴水平移动(正x 指向您的右侧),y 轴垂直移动(正y 指向上方),并且z 轴直接穿过屏幕(正z 指向屏幕外,朝向您)。现在这是非常重要的部分:x、y 和 z 被裁剪为特定范围的值;超出此范围的任何内容都将被忽略。对于所有坐标,范围从-1.0f 到1.0f。上面或下面的任何东西都不会被绘制。
因此,如果您想让100 指向屏幕内,忽略超出本练习范围的投影,您需要在-1.0f 到@987654391 中生成x 和y @ range,而不是 -50.0f 到 50.0f,就像你在那里做的那样。您可以将z 保留为0.0f,在这种情况下并不重要。这就是为什么您的大多数点都落在屏幕之外的原因:在这个范围内,从统计上讲,大约 98% 的点会落在剪辑空间之外并被忽略。
所以最终这就是你想要的:
GLfloat dots_vert[300];
for (int i = 0; i < 300; i += 3)
{
dots_vert[i] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is x
dots_vert[i+1] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is y
dots_vert[i+2] = 0.0f; // this is z
}
最后提醒一下:当您执行glDrawArrays(GL_POINTS, 0, 100); 时,您是在告诉 GPU 绘制 100 个点。每个点由您在glVertexAttribPointer 函数的size 参数中指定的许多组件组成。在这种情况下,您想绘制100 点,每个点由3 组件组成,因此GPU 需要一个100*3 = 300 浮点数组。数字。任何不足都可能导致分段错误甚至更糟糕的未定义行为(这意味着任何事情都可能发生),因此请密切注意您正在做的事情并确保您确切知道要传递给 GPU 的数据类型因为你最终可能会得到一个无意义的结果,你会被困在试图找出问题所在。在这种情况下,您基本上没有要检查的代码,因此很容易修复,但是当您最终得到相当数量的代码时(您最终会),这样的错误可能意味着浪费数小时甚至数天试图找出错误。
作为奖励,请随意忽略这一点:从技术上讲,一个点是由4 组件组成的。这个组件被称为w,它的使用超出了本练习的范围,所以不要担心,只要记住它应该始终设置为1.0f,除非你正在做投影。
所以从技术上讲,你也可以这样做:
GLfloat dots_vert[400];
for (int i = 0; i < 400; i += 4)
{
dots_vert[i] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is x
dots_vert[i+1] = ((GLfloat)rand() / (GLfloat)RAND_MAX)*2.0f - 1.0f; // this is y
dots_vert[i+2] = 0.0f; // this is z
dots_vert[i+3] = 1.0f; // this is w
}
然后你将glVertexAttribPointer的size参数设置为4而不是3,结果应该是完全一样的。