Я только начал изучать openGL и получаю этот артефакт при текстурировании сферы с помощью мипмапов. В основном, когда фрагмент выбирает край моей текстуры, он обнаруживает разрыв (скажем, от 1 до 0) и выбирает наименьшее mipmap, которое создает этот уродливый шов:
уродливый шов http://cdn.imghack.se/images/6bbe0ad0173cac003cd5dddc94bd43c7.png
Поэтому я попытался вручную переопределить градиенты, используя textureGrad:
//fragVert is the original vertex from the vertex shader
vec2 ll = vec2((atan(fragVert.y, fragVert.x) / 3.1415926 + 1.0) * 0.5, (asin(fragVert.z) / 3.1415926 + 0.5));
vec2 ll2 = ll;
if (ll.x < 0.01 || ll.x > 0.99)
ll2.x = .5;
vec4 surfaceColor = textureGrad(material.tex, ll, dFdx(ll2), dFdy(ll2));
Теперь я получаю два шва вместо одного. Как я могу избавиться от них? И почему код выше генерирует 2 шва?
2 eams http://cdn.imghack.se/images/44a38ef13cc2cdd801967c9223fdd2d3.png
Вы не можете сказать по двум изображениям, но 2 шва находятся по обе стороны от оригинального шва.
Ответы:
Основываясь на опубликованном вами коде шейдера, вы не интерполируете UV-координаты из вершин - скорее всего, вы интерполируете трехмерную позицию (
fragVert
), а затем вычисляете UV-координаты путем преобразования в сферические координаты.Ваш анализ верен в том, что наименьшее значение mipmap выбирается при наличии разрыва, поскольку выбор mipmap основан на производных, которые оцениваются численно по UV, используемым в соседних пикселях. Когда один пиксель имеет u = 0, а другой - u = 1, вы получите очень большую производную. Ваша попытка исправить имеет ту же проблему в том, что большие производные встречаются вокруг u = 0,01 и u = 0,99, поэтому два шва появляются по обе стороны от того места, где был первоначальный шов.
Относительно простой подход к решению проблемы состоит в том, чтобы решить, какой уровень MIP использовать самостоятельно, и вызвать
textureLod
его напрямую. Если планета всегда будет находиться достаточно близко к камере, вы можете просто жестко закодировать уровень мипа в 0 (или, если уж на то пошло, вообще не включать уровни мипа в текстуру). В противном случае это может быть основано на log2 расстояния точки от камеры, масштабируемого некоторыми подходящими факторами. Обратите внимание, что это эффективно отключит анизотропную фильтрацию.Более «правильный» подход заключается в расчете некоторых более качественных производных. Вместо использования
dFdx
иdFdy
на ультрафиолетовых лучах, которые имеют разрывы из-заatan2
, вы можете применитьdFdx
иdFdy
кfragVert
(который будет непрерывным на всем протяжении сферы), затем использовать некоторое исчисление (правило цепочки), чтобы найти формулу для получения производных УФ с позиции производных. Это будет более сложным и медленным, но имеет то преимущество, что анизотропная фильтрация должна работать.Наконец, поскольку вы новичок в OpenGL, я просто отмечу, что, хотя вычисление UV по сферическим координатам является совершенно правильным способом текстурирования сферы, это не «обычный» способ, который выбирает большинство людей. Чаще всего строят сферическую сетку, в которой для каждой вершины заданы значения UV и просто передаются из вершинного шейдера в пиксельный шейдер (линейно интерполируемый по каждому треугольнику). Вершины располагаются вдоль шва, таким образом , что есть две копии каждой вершины, в точно таких же положениях, но половина с u = 0 соединена с треугольниками на одной стороне, а другая половина с u = 1 соединена с треугольники на другой стороне. Это устраняет любой видимый шов и не требует никаких хитростей в пиксельном шейдере.
источник