纹理从屏幕底部绘制

时间:2018-03-10 02:32:41

标签: c++ opengl

我对原因感到有些困惑。

由于某种原因我的绘图功能我的纹理是从下往上绘制的。

因为我的代码做错了所以0是底部。 宽度正常从左到右绘制。

void Texture::draw(float x, float y)
{
    // OpenGL calls
    glDisable(GL_LIGHTING);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    GLfloat vertices_position[] = {
        x, y,
        x + m_width, y,
        x + m_width, y + m_height,
        x, y + m_height,
    };
    GLfloat texture_coord[] = {
        1.0f, 1.0f, // top right
        1.0f, 0.0f,// bottom right
        0.0f, 0.0f,// bottom left
        0.0f, 1.0f,// top left 
    };

    // snap to pixel
    int shiftX = (int)(x + 0.5f);
    int shiftY = (int)(y + 0.5f);


    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, vertices_position);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, 0, texture_coord);

    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    //glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);
    float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
    glColor4fv(color);

    glPushMatrix();
    //glTranslatef(m_width, 1.0f, 0);
    //glRotatef(90, 0.0f, 0, 1);

    glBindTexture(GL_TEXTURE_2D, m_object);
    glDrawArrays(GL_QUADS, 0, 4);

    glPopMatrix();

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glDisable(GL_BLEND);
    glDisable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
    glBindTexture(GL_TEXTURE_2D, 0);
}

编辑: 这修复了我的图像的旋转

GLfloat vertices_position[] = {
    x + m_width, y,
    x + m_width, y + m_height,
    x, y + m_height,
    x, y
};

2 个答案:

答案 0 :(得分:2)

请参阅OpenGL 4.6 API core profile specification; 8.5. TEXTURE IMAGE SPECIFICATION; page 214

  

纹理图像的元素(i,j,k)称为纹素(对于二维纹理或一维数组纹理, k 是无关;对于一维纹理, j k 都是无关紧要的)。纹理化片段中使用的纹理值是通过在着色器中对纹理进行采样来确定的,但可能与任何实际纹理元素不对应。见图8.3。

     

textureimage

     

图8.3。纹理图像和用于访问它的坐标。这是一个二维纹理,宽度为8,高度为4.一维纹理由单个水平条纹组成。 α和β,也用于混合相邻纹素以获得纹理值。


请参阅基元类型GL_QUAD的基元的顺序:

quad

这意味着您的代码会产生以下结果:

GLfloat vertices_position[] = {
    x, y,
    x + m_width, y,
    x + m_width, y + m_height,
    x, y + m_height,
};
GLfloat texture_coord[] = {
    1.0f, 1.0f, 
    1.0f, 0.0f
    0.0f, 0.0f,
    0.0f, 1.0f,
};

            x, y           x + m_width, y              1.0f, 1.0f           1.0f, 0.0f
                o------->o                                        o------->o              
                         |                                                 |
                         |                                                 |
                         v                                                 v
                o<-------o                                        o<-------o 
x, y + m_height           x + m_width, y + m_height    0.0f, 1.0f            0.0f, 0.0f

要实现您想要的效果,您必须更改纹理坐标:

GLfloat texture_coord[] = {
    0.0f, 1.0f, 
    1.0f, 1.0f,
    1.0f, 0.0f,
    0.0f, 0.0f 
};

            x, y           x + m_width, y              0.0f, 1.0f           1.0f, 1.0f
                o------->o                                        o------->o         
                         |                                                 |
                         |                                                 |
                         v                                                 v
                o<-------o                                        o<-------o 
x, y + m_height           x + m_width, y + m_height    0.0f, 0.0f            1.0f, 0.0f

或顶点坐标:

GLfloat vertices_position[] = {
    x + m_width, y,
    x + m_width, y + m_height,
    x, y + m_height,
    x, y
};

            x, y          x + m_width, y               0.0f, 1.0f           1.0, 1.0
                o        o                                        o        o
                ^        |                                        ^        |
                |        |                                        |        |
                |        v                                        |        v
                o<-------o                                        o<-------o 
x, y + m_height           x + m_width, y + m_height    0.0f, 0.0f           1.0f, 0.0f


关于以下评论的答案的延伸:

如果你想在singel数组中编码纹理坐标( x,y,z,u,v

GLfloat vertex_attributes[] = {
    x,           y,            z,  0.0f,  1.0f,
    x + m_width, y,            z,  1.0f,  1.0f,
    x + m_width, y + m_height, z,  1.0f,  0.0f,
    x,           y + m_height, z,  0.0f,  0.0f
};

然后你必须在glVertexPointerglTexCoordPointer

中设置 stride 参数
GLsizei stride = 5 * sizeof(GLfloat); // 5 because of x, y, z, u, v

GLfloat *vertex_coordinates  = vertex_attributes;
GLfloat *texture_coordiantes = vertex_attributes; + 3 // 3 because of x, y, z

glVertexPointer(3, GL_FLOAT, stride, vertex_coordinates);
glTexCoordPointer(2, GL_FLOAT, stride, texture_coordiantes);


答案的第二部分,关于以下评论:

Fixed Function Pipeline中,纹理坐标由纹理矩阵变换。如果应该翻转v-cooridnate,那么必须反转纹理矩阵的y轴(参见glMatrixMode):

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1.0f, -1.0f, 1.0f);

注意,不要忘记在'glOrtho'(glMatrixMode(GL_PROJECTION);)之前正确设置矩阵模式。

答案 1 :(得分:0)

不,你没有做错任何事。 OpenGL的坐标系是Y-up,因此0位于底部。

您可以通过更改纹理坐标以翻转其Y坐标来解决此问题。像这样:

GLfloat texture_coord[] = {
    1.0f, 0.0f, // top right
    1.0f, 1.0f,// bottom right
    0.0f, 1.0f,// bottom left
    0.0f, 0.0f,// top left 
};

或者,如果您的整个模型垂直翻转,您可以像这样翻转顶点:

GLfloat vertices_position[] = {
    x, y + m_height,
    x + m_width, y + m_height,
    x + m_width, y,
    x, y,
};