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

Как побочный проект, который у меня был некоторое время, я пытался создать немного Voxel ландшафта. Однако, к моему ужасу, текстуры, кажется, не работают должным образом. Я сопоставляю текстуру с помощью GL_REPEAT и GL_NEAREST. Текстура находится в листе спрайта и имеет размер 16×16. В настоящее время я использую текстуры 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;

}

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

1

Решение

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

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

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

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

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

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). Если у вас текстуры разных размеров, это не сработает.

0

Другие решения

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

0

По вопросам рекламы [email protected]