Выборка текстуры OpenGL различается в зависимости от положения камеры

Я рендеринг местности на основе точек из загруженных данных карты высот — но точки меняют свое текстурирование в зависимости от того, где находится положение камеры. Чтобы продемонстрировать ошибку (и тот факт, что это не происходит из-за проблемы z-буферизации), я сделал снимки экрана с точками рендеринга с фиксированным размером 5 пикселей из очень немного разных положений камеры (с тем же углом), как показано ниже:

PS: Изображения достаточно велики, если вы перетащите их на новую вкладку, но не понимаете, что стек их так сильно уменьшит.

Состояние 1:
Состояние 1 изображение

Состояние 2:
State 2 image

Код для генерации точек относительно прост, поэтому я публикую его просто для исключения опции — mapArray — это одномерный массив с плавающей точкой, который скопирован в VBO:

for(j = 0; j < mHeight; j++)
{
for(i = 0; i < mWidth; i++)
{
height = bitmapImage[k];

mapArray[k++] = 5 * i;
mapArray[k++] = height;
mapArray[k++] = 5 * j;
}
}

Я нахожу более вероятным, что мне нужно настроить свой фрагментный шейдер, потому что я не очень хорош с шейдерами — хотя я не уверен, где я мог ошибиться с таким простым кодом, и думаю, что он, вероятно, просто не подходит для цели (с точки зрения рендеринг). Сильфон — мой фрагментный шейдер:

in varying vec2 TexCoordA;
uniform sampler2D myTextureSampler;

void main(){
gl_FragColor = texture2D(myTextureSampler, TexCoordA.st) * gl_Color;
}

Изменить (запрошенная информация):
OpenGL версии 4.4 флаги текстуры не используются.

TexCoordA передается в шейдер непосредственно из моего вершинного шейдера без каких-либо изменений. Самостоятельно рассчитал УФ, используя это:

float* UVs = new float[mNumberPoints * 2];
k = 0;
for(j = 0; j < mHeight; j++)
{
for(i = 0; i < mWidth; i++)
{
UVs[k++] = (1.0f/(float)mWidth) * i;
UVs[k++] = (1.0f/(float)mHeight) * j;
}
}

8

Решение

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

Вы можете попытаться исправить это, не сэмплируя углы текселя, а пытаясь сэмплировать центры текселя (добавьте половину размера текселя к координатам точечной текстуры).

Другая вещь, которую вы можете попробовать, — это компенсировать точный рендеринг субпикселя, вычисляя разницу между растеризованной целочисленной координатой (которую вы должны вычислить в шейдере) и реальной позицией. Этого может быть достаточно, чтобы сделать выборочные тексели более стабильными.

Наконец, размер имеет значение. Если ваша текстура велика, ошибки в интерполяции текстурных координат с конечной точностью могут привести к появлению таких артефактов. Почему бы не использовать GL_TEXTURE_2D_ARRAY с отдельным слоем для каждой цветной плитки? Вы также можете зажать S а также T texcoords к краю текстуры, чтобы избежать этого более элегантно.

0

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

Просто предположение: как настроены параметры рендеринга вашей точки? Возможно расстояние затухания (GL_POINT_DISTANCE_ATTENUATION ) вместе с GL_POINT_SIZE_MIN а также GL_POINT_SIZE_MAX вызывают различные размеры фрагментов в зависимости от положения камеры. С другой стороны, я помню, что при использовании вершинного шейдера эти функции отключены, и вершинный шейдер должен определиться с размером. Я сделал это один раз, используя

//point size calculation based on z-value as done by distance attenuation
float psFactor = sqrt( 1.0 / (pointParam[0] + pointParam[1] * camDist + pointParam[2] * camDist * camDist) );
gl_PointSize   = pointParam[3] * psFactor;

где pointParam содержит три коэффициента и минимальный размер точки:

uniform vec4 pointParam;   // parameters for point size calculation [a b c min]

Вы можете поиграть, установив размер точки в вершинном шейдере напрямую с помощью gl_PointSize = [value],

0

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