Как сгладить текстуру по нескольким квадрам в opengl - PullRequest
1 голос
/ 02 мая 2019

Я пытаюсь текстурировать модель деревянного стола с помощью растрового изображения, которое я нашел и изменил в размерах, однако проблема, с которой я столкнулся, заключается в том, что каждый квадрат, составляющий поверхность стола, отчетливо виден, когда текстура применяется. Как мне сделать так, чтобы это выглядело как одна гладкая текстура?

void Table::DrawTableTop()
{
    glPushMatrix();
    //draw tabletop

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texid);

    glBegin(GL_QUADS);
    glMaterialfv(GL_FRONT, GL_SPECULAR, static_cast<GLfloat*>(specular));
    glMaterialf(GL_FRONT, GL_SHININESS, static_cast<GLfloat>(shininess));

    float unitx = 1.0f / (float)(xsize * 2 + 1);
    float unity = 1.0f / (float)(zsize * 2 + 1);

    for (int i = -xsize; i <= xsize; i++)
    {
        for (int j = -zsize; j <= zsize; j++)
        {
            glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, static_cast<GLfloat*>(wDiffuse));
            //top
            glNormal3f(0.0f, 1.0f, 0.0f);
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10));
            glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j) + scale[2]);
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10 + 1));
            glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j));
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20), unity * static_cast<float>(j + 10 + 1));
            glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j));
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 ), unity * static_cast<float>(j + 10));
            glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j) + scale[2]);
        }
    }

    glEnd();

    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);

    glPopMatrix();

Значения xsize и zsize равны 20 и 10 соответственно

Мне бы хотелось, чтобы текстура выглядела так, как если бы она была загружена в один большой квад, но, очевидно, использовала несколько квадов для улучшения освещения и т. Д.

Вот как выглядит текстурированное изображение:

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Текстуры на плитках переворачиваются вдоль оси Y.Измените координаты текстуры:

if (tex) 
    glTexCoord2f(
        unitx * static_cast<float>(i + 20 + 1),
        unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j) + scale[2]);

if (tex) 
    glTexCoord2f(
        unitx * static_cast<float>(i + 20 + 1),
        unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j));

if (tex)
    glTexCoord2f(
        unitx * static_cast<float>(i + 20),
        unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j));

if (tex)
    glTexCoord2f(
        unitx * static_cast<float>(i + 20 ),
        unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j) + scale[2]);
1 голос
/ 02 мая 2019

Вы перепутались со второй текстурной координатой.Вы устанавливаете его на j + 20, когда позиция вершины имеет + scale[0], и на j + 20 + 1, когда позиция вершины не имеет + scale[0].В результате все ваши полосы «инвертированы».

Чтобы исправить это, используйте:

if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j) + scale[2]);
if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j));
if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20), unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j));
if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 ), unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j) + scale[2]);

Однако, лучший способ - извлечь расчет положения вершины следующим образом:

struct Vertex {
    float texcoord[2];
    float position[3];
};

Vertex vertex_at(float scale[3], float unitx, float unity, int i, int j)
{
    Vertex ret;
    ret.texcoord[0] = unitx*(i + 20);
    ret.texcoord[1] = unity*(j + 10);
    ret.position[0] = scale[0]*i;
    ret.position[1] = 0;
    ret.position[2] = scale[2]*j;
    return ret;
}

И используйте это так:

for (int i = -xsize; i <= xsize; i++)
{
    for (int j = -zsize; j <= zsize; j++)
    {
        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, static_cast<GLfloat*>(wDiffuse));
        //top
        glNormal3f(0.0f, 1.0f, 0.0f);
        Vertex v[4] = {
            vertex_at(scale, unitx, unity, i + 1, j + 1),
            vertex_at(scale, unitx, unity, i + 1, j),
            vertex_at(scale, unitx, unity, i, j),
            vertex_at(scale, unitx, unity, i, j + 1),
        };
        for(int k = 0; k < 4; ++k) {
            if (tex) glTexCoord2fv(v[k].texcoord);
            glVertex3fv(v[k].position);
        }
    }
}

Таким образом, легче следить за тем, что происходит, и вы на шаг ближе к использованию VAO: просто объедините все эти Vertex структуры вбуферизуйте и установите указатели attrib.

...