UV-отображение OpenGL для сферы (со швом)

У меня возникает следующая проблема при попытке сопоставить UV-координаты со сферой введите здесь описание изображения

Вот код, который я использую для получения своих UV-координат

glm::vec2 calcUV( glm::vec3 p)
{
    p = glm::normalize(p);

    const float PI = 3.1415926f;

    float u = ((glm::atan(p.x, p.z) / PI) + 1.0f) * 0.5f;
    float v = (asin(p.y) / PI) + 0.5f;

    return glm::vec2(u, v);
}

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


person tvoloshyn    schedule 22.11.2013    source источник
comment
Аааа, старая забавная проблема с наложением текстуры на сферу. Одно из самых универсальных решений, которое я видел, подробно описано здесь (это фантастический ресурс для материалов, связанных с графикой). Ссылка: iquilezles.org/www/articles/patchedsphere/patchedsphere.htm   -  person enhzflep    schedule 23.11.2013


Ответы (2)


Ваша проблема заключается в том, что на стыке ваши координаты текстуры «откатываются» к 0, поэтому вы получаете всю текстуру, отображаемую, зеркально отраженную на стыке. Чтобы этого не произошло, следует использовать режим повтора GL_WRAP и на стыке заканчивать вершинами с текстурными координатами >= 1 (не откатываясь к 0). Помните, что вершина состоит из целого набора всех ее атрибутов, а вершины с разными значениями атрибутов в целом различны, поэтому нет смысла пытаться «поделиться» вершинами.

person datenwolf    schedule 23.11.2013

Другой способ сделать это — просто передать координаты объекта сферы в пиксельный шейдер и вычислить UV в «идеальном» сферическом пространстве.

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

В противном случае да. Вам нужно продублировать вершины вдоль того же ребра, что и u=0, а также повторить вершины на полюсах. Таким образом, топология вашего объекта станет прямоугольником: точно так же, как ваша текстура.

person bjorke    schedule 23.11.2013
comment
У меня проблема в том, что я не могу вычислить uv внутри фрагментного шейдера, так как у меня есть другие объекты, которые не являются сферами. Я знаю, что могу настроить некоторые переменные типа объекта, но я действительно не хочу слишком усложнять свой шейдер. Я до сих пор не понимаю, что на самом деле подразумевается под дублированием вершин... Значит ли это, что мне нужно вручную добавить эти вершины и установить их координаты UV равными 1.0? - person tvoloshyn; 23.11.2013
comment
Рассмотрим случай круга. Допустим, вы упростили его до пятиугольника. Было бы пять вершин, да? Но если вы хотите правильно нанести UV-карту (или, в этом упрощенном случае, просто U-карту), вам понадобится ШЕСТЬ вершин: [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] -- если у вас не было повторяющейся вершины в конце, то отображение для последнего диапазона, от 0,8 до 1, вместо этого будет идти от 0,8 до 0,0, в обратном направлении. - person bjorke; 23.11.2013
comment
Теперь возможно, что у вас уже есть правильное количество вершин, но вы просто неправильно вычисляете значение для дублированной вершины в конечной позиции, потому что ваш триггер calcUV() говорит 0 градусов, когда вы действительно хотите 360 градусов. Конкретное правильное решение для этого я оставляю вам, поскольку лучшим решением будет то, которое понимает топологию вашей модели, и вы уже заявили, что реальные модели, которые вы используете, не те, которые вы показываем. - person bjorke; 23.11.2013