Текстурные пропуски OpenGL White Line

Как побочный проект, который у меня был некоторое время, я пытался создать немного Voxel ландшафта. Однако, к моему ужасу, текстуры, кажется, не работают должным образом. Я сопоставляю текстуру с помощью GL_REPEAT и GL_NEAREST. Текстура находится в листе спрайта и имеет размер 16x16. В настоящее время я использую текстуры Minecraft для отладки. Я пытался исправить это, перемещая текстуру 1, но это тоже не сработало.

Вот код, который обрабатывает это:

void Chunk::CreateCube(int x, int y, int z, bool activeStates[], int ID)
{

        double TEXTURE_SIZE = 256;
        glm::vec3 p1(x-BLOCK_RENDER_SIZE, y-BLOCK_RENDER_SIZE, z+BLOCK_RENDER_SIZE); //left bottom  front
        glm::vec2 t1(0.5/TEXTURE_SIZE, 0.5/TEXTURE_SIZE);
        glm::vec3 p2(x+BLOCK_RENDER_SIZE, y-BLOCK_RENDER_SIZE, z+BLOCK_RENDER_SIZE); //right bottom front
        glm::vec2 t2(1-(0.5/TEXTURE_SIZE), 0.5/TEXTURE_SIZE);
        glm::vec3 p3(x+BLOCK_RENDER_SIZE, y+BLOCK_RENDER_SIZE, z+BLOCK_RENDER_SIZE); // right top front
        glm::vec2 t3(1-(0.5/TEXTURE_SIZE), 1-(0.5/TEXTURE_SIZE));
        glm::vec3 p4(x-BLOCK_RENDER_SIZE, y+BLOCK_RENDER_SIZE, z+BLOCK_RENDER_SIZE); // left top front
        glm::vec2 t4(0.5/TEXTURE_SIZE, 1-(0.5/TEXTURE_SIZE));
        glm::vec3 p5(x+BLOCK_RENDER_SIZE, y-BLOCK_RENDER_SIZE, z-BLOCK_RENDER_SIZE); // right bottom back
        glm::vec2 t5(0.5/TEXTURE_SIZE, 0.5/TEXTURE_SIZE);
        glm::vec3 p6(x-BLOCK_RENDER_SIZE, y-BLOCK_RENDER_SIZE, z-BLOCK_RENDER_SIZE); // left bottom back
        glm::vec2 t6(1-(0.5/TEXTURE_SIZE), 0.5/TEXTURE_SIZE);
        glm::vec3 p7(x-BLOCK_RENDER_SIZE, y+BLOCK_RENDER_SIZE, z-BLOCK_RENDER_SIZE); // left top back
        glm::vec2 t7(1-(0.5/TEXTURE_SIZE), 1-(0.5/TEXTURE_SIZE));
        glm::vec3 p8(x+BLOCK_RENDER_SIZE, y+BLOCK_RENDER_SIZE, z-BLOCK_RENDER_SIZE); // right top back
        glm::vec2 t8(0.5/TEXTURE_SIZE, 1-(0.5/TEXTURE_SIZE));

        int numCols = 16;
        int numRows = 16;

        double u = ((double)(ID % numCols) / (double)numCols);
        double v = ((double)(ID / numRows) / (double)numRows);
        double TILE_TEXTURE_SIZE = 16;

        glm::vec3 n1;


        if(activeStates[5] == false)
        {
                // Front Face Normal
                n1 = glm::vec3(0.0f, 0.0f, 1.0f);
                //Triangle 1
                vertexData.push_back(p1);
                uvData.push_back(glm::vec2(t1.x/TILE_TEXTURE_SIZE + u, t1.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p2);
                uvData.push_back(glm::vec2(t2.x/TILE_TEXTURE_SIZE + u, t2.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p3);
                uvData.push_back(glm::vec2(t3.x/TILE_TEXTURE_SIZE + u, t3.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
                //Triangle 2
                vertexData.push_back(p1);
                uvData.push_back(glm::vec2(t1.x/TILE_TEXTURE_SIZE + u, t1.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p3);
                uvData.push_back(glm::vec2(t3.x/TILE_TEXTURE_SIZE + u, t3.y/TILE_TEXTURE_SIZE + v ));
                normalData.push_back(n1);

                vertexData.push_back(p4);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
        }

        if(activeStates[4] == false)
        {
                // Back
                n1 = glm::vec3(0.0f, 0.0f, -1.0f);
                //Triangle 1
                vertexData.push_back(p5);
                uvData.push_back(glm::vec2(t5.x/TILE_TEXTURE_SIZE + u, t5.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p6);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p7);
                uvData.push_back(glm::vec2(t7.x/TILE_TEXTURE_SIZE + u, t7.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
                //Triangle 2
                vertexData.push_back(p5);
                uvData.push_back(glm::vec2(t5.x/TILE_TEXTURE_SIZE + u, t5.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p7);
                uvData.push_back(glm::vec2(t7.x/TILE_TEXTURE_SIZE + u, t7.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p8);
                uvData.push_back(glm::vec2(t8.x/TILE_TEXTURE_SIZE + u, t8.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
        }
        if(activeStates[1] == false)
        {
                // Right
                n1 = glm::vec3(1.0f, 0.0f, 0.0f);
                //Triangle 1
                vertexData.push_back(p2);
                uvData.push_back(glm::vec2(t2.x/TILE_TEXTURE_SIZE + u, t2.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p5);
                uvData.push_back(glm::vec2(t5.x/TILE_TEXTURE_SIZE + u, t5.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p8);
                uvData.push_back(glm::vec2(t8.x/TILE_TEXTURE_SIZE + u, t8.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
                //Triangle 2
                vertexData.push_back(p2);
                uvData.push_back(glm::vec2(t2.x/TILE_TEXTURE_SIZE + u, t2.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p8);
                uvData.push_back(glm::vec2(t8.x/TILE_TEXTURE_SIZE + u, t8.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p3);
                uvData.push_back(glm::vec2(t3.x/TILE_TEXTURE_SIZE + u, t3.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
        }
        if(activeStates[0] == false)
        {
                // left
                n1 = glm::vec3(-1.0f, 0.0f, 0.0f);
                //Triangle 1
                vertexData.push_back(p6);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p1);
                uvData.push_back(glm::vec2(t1.x/TILE_TEXTURE_SIZE + u, t1.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p4);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
                //Triangle 2
                vertexData.push_back(p6);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p4);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p7);
                uvData.push_back(glm::vec2(t7.x/TILE_TEXTURE_SIZE + u, t7.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
        }
        if(activeStates[3] == false)
        {
                // Top
                n1 = glm::vec3(0.0f, 1.0f, 0.0f);
                //Triangle 1
                vertexData.push_back(p4);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p3);
                uvData.push_back(glm::vec2(t1.x/TILE_TEXTURE_SIZE + u, t1.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p8);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
                //Triangle 2
                vertexData.push_back(p4);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p8);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p7);
                uvData.push_back(glm::vec2(t7.x/TILE_TEXTURE_SIZE + u, t7.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
        }

        if(activeStates[2] == false)
        {
                // Bottom
                n1 = glm::vec3(0.0f, -1.0f, 0.0f);

                //Triangle 1
                vertexData.push_back(p6);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p5);
                uvData.push_back(glm::vec2(t1.x/TILE_TEXTURE_SIZE + u, t1.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p2);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
                //Triangle 2
                vertexData.push_back(p6);
                uvData.push_back(glm::vec2(t6.x/TILE_TEXTURE_SIZE + u, t6.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p2);
                uvData.push_back(glm::vec2(t4.x/TILE_TEXTURE_SIZE + u, t4.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);

                vertexData.push_back(p1);
                uvData.push_back(glm::vec2(t7.x/TILE_TEXTURE_SIZE + u, t7.y/TILE_TEXTURE_SIZE + v));
                normalData.push_back(n1);
        }

        /*glm::vec2 t1(0.5/256, 0.5/256);

        glm::vec2 t2(1-(0.5/256), 0.5/256);

        glm::vec2 t3(1-(0.5/256), 1-(0.5/256));

        glm::vec2 t4(0.5/256, 1-(0.5/256));

        glm::vec2 t5(0.5/256, 0.5/256);

        glm::vec2 t6(1-(0.5/256), 0.5/256);

        glm::vec2 t7(1-(0.5/256), 1-(0.5/256));

        glm::vec2 t8(0.5/256, 1-(0.5/256));
        */

        /*
        for(int i = 0; i < vertexData.size(); i+=3)
        {

        // get the three vertices that make the faces
        glm::vec3 p1 = vertexData[i+0];
        glm::vec3 p2 = vertexData[i+1];
        glm::vec3 p3 = vertexData[i+2];

        glm::vec3 v1 = p2 - p1;
        glm::vec3 v2 = p3 - p1;
        glm::vec3 normal = glm::cross( v1,v2 );

        normal = glm::normalize(normal);

        normalData[i+0] = normal;
        normalData[i+1] = normal;
        normalData[i+2] = normal;

        }
        */
}



GLuint Graphics3D::loadTexture(const char* theFileName)
{
        ILuint imageID;                

        GLuint textureID;              

        ILboolean success;

        ILenum error;                          

        ilGenImages(1, &imageID);      

        ilBindImage(imageID);          

        success = ilLoadImage(theFileName);

        if (success)
        {

                ILinfo ImageInfo;
                iluGetImageInfo(&ImageInfo);
                if (ImageInfo.Origin == IL_ORIGIN_UPPER_LEFT)
                {
        //              iluFlipImage();
                }

                success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);


                if (!success)
                {
                        error = ilGetError();
                        std::cout << "Image conversion failed - IL reports error: " << error << " - " << iluErrorString(error) << std::endl;
                }


                glGenTextures(1, &textureID);

        glBindTexture(GL_TEXTURE_2D, textureID);


                glTexImage2D(GL_TEXTURE_2D,                             // Type of texture
                        0,                              // Pyramid level (for mip-mapping) - 0 is the top level
                        ilGetInteger(IL_IMAGE_BPP),     // Image colour depth
                        ilGetInteger(IL_IMAGE_WIDTH),   // Image width
                        ilGetInteger(IL_IMAGE_HEIGHT),  // Image height
                        0,                              // Border width in pixels (can either be 1 or 0)
                        ilGetInteger(IL_IMAGE_FORMAT),  // Image format (i.e. RGB, RGBA, BGR etc.)
                        GL_UNSIGNED_BYTE,               // Image data type
                        ilGetData());                   // The actual image data itself
                /*
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                */

        //      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        //      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

                if(GLEW_EXT_texture_filter_anisotropic)
                {

                        GLfloat maximumAnisotropy;
                        //get the value
                        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy);
                        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maximumAnisotropy);
                }

                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
        //      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        //      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                glGenerateMipmap(GL_TEXTURE_2D);


        }
        else
        {
                error = ilGetError();
                std::cout << "Image load failed - IL reports error: " << error << " - " << iluErrorString(error) << std::endl;

        }

        ilDeleteImages(1, &imageID);

        std::cout << "Texture creation successful." << std::endl;

        return textureID;

}

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

2 ответа

Это почти наверняка связано с включением некоторой формы фильтрации.

Отмечу, что вы включаете анизотропную фильтрацию. Даже без MIP-картографирования это приведет к извлечению пикселей за пределами вашей суб-текстуры, вызывая артефакты, подобные тем, что вы видите здесь.

Вам действительно нужно отключить это, а также избавиться от мип-карт.

Кроме того, я думаю, что ваша ультрафиолетовая генерация выключена и содержит некоторые ошибки. Это, вероятно, не проблема здесь, но я бы порекомендовал их исправить.

Например, здесь вы добавляете половину текселя:

glm::vec2 t1(0.5/TEXTURE_SIZE, 0.5/TEXTURE_SIZE);

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

Затем вы делаете это:

double u = ((double)(ID % numCols) / (double)numCols);
double v = ((double)(ID / numRows) / (double)numRows);

Вы должны использовать одно и то же значение для деления и по модулю ID, Это работает только потому, что у вас одинаковое количество строк и столбцов.

Наконец, вы рассчитываете UVs следующим образом:

t1.x/TILE_TEXTURE_SIZE + u

Делить на размер плитки неправильно. Так должно быть * TILE_SIZE / TEXTURE_SIZE, К счастью для вас это происходит одинаково (256 / 16 = 16). Если у вас есть текстуры разных размеров, это не сработает.

Ваша основная проблема в том, что у вас есть несколько изображений в одной большой текстуре. Это вызовет проблемы с любым типом фильтрации текстур, такой как mipmapping и анизотропная фильтрация. Вы НЕ хотите отключить фильтрацию текстур. Вместо этого вы должны логически рассматривать каждое изображение как отдельное изображение. Самый простой способ сделать это - сделать каждую плитку отдельной текстурой. Это немного медленно, поэтому для лучшей производительности вы должны вместо этого использовать Array Texture.

Другие вопросы по тегам