Пересчет нормали с кривой (синусоида)

Я пытаюсь создать шейдер геометрии воды, который машет синусоидой.

Для каждой вершины я вычисляю синус для x и y, а затем смещаю вершину к результату * normal.

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

Я понимаю, что каким-то образом я должен использовать эту синусоидальную функцию и получить из нее 3D-нормаль, но я озадачен.

Может ли кто-нибудь объяснить, как вы получаете нормаль вычисления греха в трехмерном пространстве?


person user1091566    schedule 11.06.2014    source источник


Ответы (2)


Вы не указываете точную функцию, которую используете, но похоже, что это что-то вроде:

z = a * sin(b * x) * sin(b * y)

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

Здесь у нас есть параметрическая поверхность, где 3 координаты точки плоскости вычисляются из двух параметров. В данном случае это параметры x и y, а вектор, описывающий каждую точку:

          [ x                           ]
v(x, y) = [ y                           ]
          [ a * sin(b * x) * sin(b * y) ]

Описанный здесь процесс работает для любой параметрической поверхности, включая обычные геометрические формы. Например, для тора двумя параметрами будут два угла. Математические инструменты, необходимые для расчета, включают базовый анализ (производные) и некоторую векторную геометрию (перекрестное произведение).

В качестве первого шага мы вычисляем вектор градиента для каждого из двух параметров. Эти векторы градиента состоят из частных производных каждой компоненты вектора с соответствующим параметром. В примере результаты следующие:

              [ 1                               ]
dv(x, y)/dx = [ 0                               ]
              [ a * b * cos(b * x) * sin(b * y) ]


              [ 0                               ]
dv(x, y)/dy = [ 1                               ]
              [ a * b * sin(b * x) * cos(b * y) ]

Вектор нормали рассчитывается как перекрестное произведение этих двух векторов градиента:

     [ - a * b * cos(b * x) * sin(b * y) ]
vn = [ - a * b * sin(b * x) * cos(b * y) ]
     [ 1                                 ]

Затем вы нормализуете этот вектор, и vn / |vn| будет вашим вектором нормали.

person Reto Koradi    schedule 12.06.2014
comment
Спасибо за обширный ответ, я понимаю, что должно произойти, и попробовал, но я не могу прийти к правильному результату. Моя версия волновой функции выглядит так: AmpX * sin(SpeedX * Time * ScaleX * pos.x); Я использую эту формулу для расчета плавающей «анимации» и добавляю к ней ту же формулу, но с Z. Затем я использую это смещение, чтобы переместить свою вершину на это количество, умноженное на его норму. Затем мне нужно пересчитать нормальные и мои производные функциональные инструменты следующим образом: AmpX * (sin(SpeedX * Time + ScaleX * pos.x) + ScaleX * pos.x * cos(SpeedX * time + ScaleX * pos.x)) Тогда я беру на себя крест их. - person user1091566; 12.06.2014
comment
Я получил производную функцию от wolframalpha.com/input/?i=derivative+ x+a+*+sin%28b+*+c+%2B+d++*+x%29 и результат выглядит несколько правильным (поскольку кажется, что нормаль движется), но мне также нужно пересчитать тангенс, я делаю это взяв нормализованное пересечение нормали и одного из производных векторов. - person user1091566; 12.06.2014

Вам нужно получить производную по x и y, чтобы вы могли построить 2 вектора 1,0,x' и 0,1,y', затем вы берете перекрестное произведение и нормализуете. Это будет нормально.

person ratchet freak    schedule 11.06.2014
comment
вы имеете в виду: normalize(cross(float3(1, 0, dx), float3(0, 1, dy))) потому что это не работает для меня - person user1091566; 11.06.2014
comment
@user1091566 user1091566 Я предположил, что исходная плоскость была горизонтальной (с Z вверху) - person ratchet freak; 11.06.2014