我正在尝试让透明度混合在我的立方体上正常工作,但我遇到了一些障碍。我已经通过简单地以正确的顺序绘制多个立方体来混合它们,但让它在立方体本身的面上工作要困难得多。
我想要解决这个问题的方法是重新排序 EBO 中的索引,以便它以正确的顺序绘制面。我已经得到它来重新排序索引,问题是它们的排序不正确。
我这样做的方法是用这个方法:
void GECCube::SortIndicies(glm::mat4 ModelMatrix)
{
glm::vec4 View = glm::vec4{0.0f, 0.0f, -3.0f, 0.f};
unsigned int NewIndices[36];
std::multimap<float, std::vector<unsigned int>> SortedMap;
for (int i = 0; i < 12; i += 2)
{
glm::vec4 Tri1 = glm::vec4{
(Vertices[Indices[i * 3] * 3] + Vertices[Indices[(i * 3) + 1] * 3] + Vertices[Indices[(i * 3) + 2] * 3]) / 3, //X
(Vertices[Indices[i * 3] * 4] + Vertices[Indices[(i * 3) + 1] * 4] + Vertices[Indices[(i * 3) + 2] * 4]) / 3, //Y
(Vertices[Indices[i * 3] * 5] + Vertices[Indices[(i * 3) + 1] * 5] + Vertices[Indices[(i * 3) + 2] * 5]) / 3, //Z
0.f
};
glm::vec4 Tri2 = glm::vec4{
(Vertices[Indices[(i + 1) * 3] * 3] + Vertices[Indices[((i + 1) * 3) + 1] * 3] + Vertices[Indices[((i + 1) * 3) + 2] * 3]) / 3, //X
(Vertices[Indices[(i + 1) * 3] * 4] + Vertices[Indices[((i + 1) * 3) + 1] * 4] + Vertices[Indices[((i + 1) * 3) + 2] * 4]) / 3, //Y
(Vertices[Indices[(i + 1) * 3] * 5] + Vertices[Indices[((i + 1) * 3) + 1] * 5] + Vertices[Indices[((i + 1) * 3) + 2] * 5]) / 3, //Z
0.f
};
glm::vec4 PlaneMed = glm::vec4{(Tri1.x + Tri2.x) / 2, (Tri1.y + Tri2.y) / 2 , (Tri1.z + Tri2.z) / 2, 0 };
float Distance = glm::length(View - (ModelMatrix * PlaneMed));
std::vector<unsigned int> TransportVector = std::vector<unsigned int>{ Indices[i * 3] , Indices[(i * 3) + 1] , Indices[(i * 3) + 2],
Indices[(i + 1) * 3] , Indices[((i + 1) * 3) + 1] , Indices[((i + 1) * 3) + 2] };
SortedMap.insert(std::pair<float, std::vector<unsigned int>>(Distance, TransportVector));
}
auto MapIterator = SortedMap.begin();
for (int i = 0; i < 12; i += 2)
{
NewIndices[i * 3] = MapIterator->second[0];
NewIndices[(i * 3) + 1] = MapIterator->second[1];
NewIndices[(i * 3) + 2] = MapIterator->second[2];
NewIndices[(i + 1) * 3] = MapIterator->second[3];
NewIndices[((i + 1) * 3) + 1] = MapIterator->second[4];
NewIndices[((i + 1) * 3) + 2] = MapIterator->second[5];
if (i != 10) { MapIterator++; }
}
std::copy(std::begin(NewIndices), std::end(NewIndices), std::begin(Indices));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}
我还没有对相机做一些更复杂的事情,所以现在它只是在位置
0,0,-3.0
我认为我做错的地方是在计算相机和飞机之间的距离时。即这个:
float Distance = glm::length(View - (ModelMatrix * Plane));
最初我只想使用
View - Plane
,但我意识到这会给每个索引相同的值,所以我考虑如何将模型集成到距离中。我的原因是,由于着色器使用模型矩阵在正确的位置进行绘制,因此我应该能够使用它来找到模型空间中平面的正确位置。但我认为我错了。
所有这些都在绘制函数中汇集在一起(它绘制多个立方体):
...
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, it->second * 0.9f * std::clamp((float) sinf(( float )SDL_GetTicks() / 1000.f) + 1.5f, 0.f, 3.f));
float angle = 20.0f * ((i + 1)/20) * ( float )SDL_GetTicks() / 200 * glm::radians(50.0f);
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
OGLCMain->MainCube.SortIndicies(model);
int modelLoc = glGetUniformLocation(OGLCMain->ShaderProgram, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
...
因此,我通过更改使用相机前矢量上的矢量的点积来计算的距离代码来使系统工作
Plane = ModelMatrix * Plane
float Distance = glm::dot((CameraPos - Plane), CameraFront);
并通过更改平面 med 的计算方式为:
glm::vec4 Plane = glm::vec4{
(Vertices[(Indices[(i) * 3] * 5)] + Vertices[(Indices[((i) * 3) + 1] * 5)] + Vertices[(Indices[((i) * 3) + 2] * 5)] + Vertices[(Indices[((i + 1) * 3) + 1] * 5)]) / 4.f,
(Vertices[(Indices[(i) * 3] * 5) + 1] + Vertices[(Indices[((i) * 3) + 1] * 5) + 1] + Vertices[(Indices[((i) * 3) + 2] * 5) + 1] + Vertices[(Indices[((i + 1) * 3) + 1] * 5) + 1]) / 4.f,
(Vertices[(Indices[(i) * 3] * 5) + 2] + Vertices[(Indices[((i) * 3) + 1] * 5) + 2] + Vertices[(Indices[((i) * 3) + 2] * 5) + 2] + Vertices[(Indices[((i + 1) * 3) + 1] * 5) + 2]) / 4.f,
1.f };
我还颠倒了它放回原处的顺序:
auto MapIterator = SortedMap.begin();
for (int i = 11; i > 0; i -= 2)
{
NewIndices[i * 3] = MapIterator->second[0];
NewIndices[(i * 3) + 1] = MapIterator->second[1];
NewIndices[(i * 3) + 2] = MapIterator->second[2];
NewIndices[(i - 1) * 3] = MapIterator->second[3];
NewIndices[((i - 1) * 3) + 1] = MapIterator->second[4];
NewIndices[((i - 1) * 3) + 2] = MapIterator->second[5];
MapIterator++;
}
并将距离计算更改为:
float Distance = -glm::dot((CameraPos - Plane), CameraFront);
但是! 这应该不重要,因为这两者都颠倒了顺序,从而净值 0 变化。
为了清楚起见,我在这个项目中使用的顶点和索引数组如下所示:
GLfloat TempVertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // A 0
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // B 1
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // C 2
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // D 3
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // E 4
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // F 5
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // G 6
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // H 7
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, // D 8
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // A 9
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, // E 10
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // H 11
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // B 12
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, // C 13
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // G 14
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, // F 15
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // A 16
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // B 17
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, // F 18
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, // E 19
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, // C 20
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, // D 21
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // H 22
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // G 23
};
unsigned int TempIndices[] = {
// front and back
0, 3, 2,
2, 1, 0,
4, 5, 6,
6, 7 ,4,
// left and right
11, 8, 9,
9, 10, 11,
12, 13, 14,
14, 15, 12,
// bottom and top
16, 17, 18,
18, 19, 16,
20, 21, 22,
22, 23, 20
};