opengl 为什么在Open GL中,纹理离x坐标越远,翻转效果就越不一样

oprakyz7  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(173)

我正在尝试在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

envsm3lx

envsm3lx1#

我想这和视角有关
你是正确的,为了快速确认它,你可以简单地将投影矩阵更改为正交而不是透视:

projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

您的相机位于(0,0,3)处,在负z方向上观察,垂直FOV为45度(更水平)。当观察靠近屏幕左(或右)边缘的对象时,您观察的方向不仅仅是负z方向:因为透视关系,它是介于-z和-x(或+x)之间的值。如果希望纹理在正确的时刻切换,则需要考虑此方向。
基本上,对于每个(平面)对象,您需要计算它和相机之间的向量,并在该向量平行于对象表面时切换纹理。
因为每个对象都只是一个平面,所以可以通过“在曲面中”取两个向量的叉积来计算法向量(数学上:“平行于表面的平面”)。例如,两个向量,每个向量在不同的顶点对之间。因为你的例子是简单的,你也可以只取model的第三列作为法向量(但是如果你改变了对象的运动,你需要小心)。
一旦你有了一个法向量(不需要对其进行归一化),你就可以用moneyPositions[i] - glm::vec3(0.0f, 0.0f, -3.0f)计算相机到对象的向量。然后,取这两个向量的点积:如果结果是肯定的,你正在看物体表面的一侧;如果是负的,你就看到了另一面。相应地切换纹理。

相关问题