我正在尝试在Open GL中制作一个“翻钱”场景,其中每一美元是一个4个顶点的2D矩形。我试着Map2个纹理到它的背面和正面视图的一美元,至少旋转它的y轴。我尝试改变纹理的基础上,当一美元得到翻转,这意味着它的rigt顶部顶点在x轴得到小于其中心或原点。当它的x被翻转时,我基本上使另一个纹理激活并绑定它,反之亦然,所以这就是我如何改变纹理(我不知道是否有更好的方法来做到这一点)。然后我在for循环中用索引绘制每个美元矩形,这样一个场景中就有10个矩形。代码如下:
这里是我的顶点和矩形的索引,以及一组向量来转换模型矩阵,使美元出现在屏幕上的不同部分。我的纹理坐标在x中是从-1开始的,因为当x变为负值时,后面的纹理会水平翻转,所以我应用GL_MIRRORED_REPEAT,当它翻转时,它只是镜像,所以它看起来是正确的:
float vertices[] = {
// positions // texture coords
0.5f, 0.5f, 0.0f, -1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, -1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left
};
// separate array to calculate current vertex position
float verticesPos[] = {
// positions
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
// for translating model matrix and placing dollars in different parts of a screen
glm::vec3 moneyPositions[] = {
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
在游戏循环之前,我还创建了视图和投影矩阵:
glm::mat4 view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
unsigned int viewLoc = glGetUniformLocation(shaders.ID, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glm::mat4 projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f);
unsigned int projectionLoc = glGetUniformLocation(shaders.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
绘制矩形和绑定纹理部分:
for (int i = 0; i < 10; ++i)
{
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, moneyPositions[i]);
model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
shaders.setMat4("model", &model[0][0]);
// calculate the current vertex positions
glm::vec3 updatedVertices[4];
for (int j = 0; j < sizeof(verticesPos) / sizeof(float); j += 3)
{
glm::vec4 pos(verticesPos[j], verticesPos[j + 1], verticesPos[j + 2], 1.0f);
glm::vec4 modelPos = model * pos;
updatedVertices[j / 3] = glm::vec3(modelPos[0], modelPos[1], modelPos[2]);
}
// check if right top vertex on the x axis is less than the origin and bind the rear(back) texture, otherwise bind front texture
if (updatedVertices[0].x < moneyPositions[i].x)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture2);
}
else
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
}
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
我的问题是:为什么我的中心美元矩形(在原点0.0,0.0,0.0)翻转纹理正常没有任何问题,而其他矩形则有延迟,似乎他们离中心越远翻转纹理所需的延迟越多,即使if语句中的计算应该是正确的,并且纹理应该在x翻转与每个矩形的原点相关时立即改变。另外,我注意到在x为负的左手边,纹理翻转的时间比它应该翻转的时间早,而在右手边,它翻转的时间晚。我认为这与透视有关,因为即使我以相同的Angular 和速度旋转每个矩形,它们似乎都以不同的速度轻微旋转。Here's the visual output of the program
1条答案
按热度按时间envsm3lx1#
我想这和视角有关
你是正确的,为了快速确认它,你可以简单地将投影矩阵更改为正交而不是透视:
您的相机位于(0,0,3)处,在负z方向上观察,垂直FOV为45度(更水平)。当观察靠近屏幕左(或右)边缘的对象时,您观察的方向不仅仅是负z方向:因为透视关系,它是介于-z和-x(或+x)之间的值。如果希望纹理在正确的时刻切换,则需要考虑此方向。
基本上,对于每个(平面)对象,您需要计算它和相机之间的向量,并在该向量平行于对象表面时切换纹理。
因为每个对象都只是一个平面,所以可以通过“在曲面中”取两个向量的叉积来计算法向量(数学上:“平行于表面的平面”)。例如,两个向量,每个向量在不同的顶点对之间。因为你的例子是简单的,你也可以只取
model
的第三列作为法向量(但是如果你改变了对象的运动,你需要小心)。一旦你有了一个法向量(不需要对其进行归一化),你就可以用
moneyPositions[i] - glm::vec3(0.0f, 0.0f, -3.0f)
计算相机到对象的向量。然后,取这两个向量的点积:如果结果是肯定的,你正在看物体表面的一侧;如果是负的,你就看到了另一面。相应地切换纹理。