Opengl вычисляет производные треугольника

У меня есть треугольник в 2D-пространстве. У меня есть координаты экранного пространства каждой вершины, и у меня есть значения атрибутов каждой вершины.

Как я могу рассчитать dFdx/dFdy для этих атрибутов? Другими словами, как изменится атрибут с пикселя экрана на пиксель.

//fragment shader
varrying vec2 myAttr;

void main(void)
{
  vec2 px = dFdx(myAttr);
  vec2 py = dFdy(myAttr);
}

Я хочу получить px, py. Мне нужно знать дельту (рост) myAttr от следующего пикселя для осей x и y. Мне нужна формула/алгоритм, как их вычислить вручную (например, для случаев, когда железо не поддерживает производные).

P.S. Значение атрибута линейно интерполировано между 3 вершинами (согласно документу OpenGL).


person tower120    schedule 04.09.2014    source источник
comment
Я не понимаю, о чем вы спрашиваете. В вашем коде уже есть встроенные функции GLSL dFdx, dFdy. Что вы еще хотите? Объяснение того, как рассчитать его вручную?   -  person datenwolf    schedule 04.09.2014
comment
Это в GLSL :) Мне нужна формула, чтобы вычислить их вручную/на процессоре.   -  person tower120    schedule 04.09.2014
comment
В этой теме на форумах opengl задается очень похожий вопрос: opengl.org/discussion_boards/showthread.php/.   -  person user3256930    schedule 04.09.2014
comment
производная означает скорость изменения на единицу. Ваша единица здесь — расстояние между пикселями. Изменение – это разница значений функции в соседних точках. Таким образом, это должно быть простое приблизительное деление с одной из формул более высокого порядка, такой как шаблон с 5 точками, но вместо этого с тремя точками.   -  person huseyin tugrul buyukisik    schedule 04.09.2014
comment
@huseyin tugrul buyukisik - Ну да. И я понимаю, как сделать линейную интерполяцию между 2 точками. Но я не могу понять, как интерполировать между 3.   -  person tower120    schedule 04.09.2014
comment
Это было нечто, полученное из ряда Тейлора или некоторых уравнений Эйлера. Позвольте мне поискать больше, если кто-то еще не ищет. Здесь: mathfaculty.fullerton.edu/mathews/n2003/numericaldiffmod.html   -  person huseyin tugrul buyukisik    schedule 04.09.2014
comment
@huseyintugrulbuyukisik Это было что-то полученное из ряда Тейлора или некоторых уравнений Эйлера. - Вы имеете в виду интерполяцию между 3 точками или деривацию?   -  person tower120    schedule 04.09.2014
comment
Я имел в виду деривацию. У интерполяции есть линейная и экспоненциальная версии, не так ли?   -  person huseyin tugrul buyukisik    schedule 04.09.2014
comment
@huseyintugrulbuyukisik Я знаю только этот current = (max-min)*pos, где pos = 0..1 :) И я знаю, что это линейная интерполяция. Как интерполировать между 3 значениями я понятия не имею. И было бы хорошо, если бы кто-нибудь показал, как рассчитывается интерполяция, в частности, в OpenGL/DirectX/любом оборудовании (GL_LINEAR).   -  person tower120    schedule 04.09.2014


Ответы (1)


предполагая, что ваша вершина структурирована следующим образом:

struct vertex
{
  double x; // screenspace x coordinate
  double y; // screenspace y coordinate
  double a; // your attribute
};

Вывод, который вы ищете, рассчитывается следующим образом:

      d    = (v0.x - v2.x) * (v1.y - v2.y) -
             (v1.x - v2.x) * (v0.y - v2.y);

      dfdx = ((v0.a - v2.a) * (v1.y - v2.y) -
              (v1.a - v2.a) * (v0.y - v2.y)) / d;

      dfdy = ((v0.a - v2.a) * (v1.x - v2.x) -
              (v1.a - v2.a) * (v0.x - v2.x)) / d;

Обратите внимание, что это уравнение становится неустойчивым, когда d приближается к нулю. Это также вызовет деление на ноль, если d равно нулю. На практике это не проблема, потому что в этом случае треугольник также имеет нулевую площадь и ничего не нужно рендерить.

person Nils Pipenbrinck    schedule 04.09.2014
comment
Ух ты. Именно то, что мне нужно. Вы сами нашли эти уравнения, или это какой-то известный способ их получить? Я имею в виду, если это что-то известное, могу ли я где-нибудь об этом прочитать? - person tower120; 04.09.2014
comment
И кажется, что атрибут может быть вектором в ваших уравнениях. Я прав? Или лучше рассчитать по компонентам? - person tower120; 04.09.2014
comment
@ Tower120 d - это просто общий фактор, который я вытащил из уравнения, чтобы упростить его. Если я правильно помню, это в два раза больше площади треугольника. Да, вы можете заменить скаляр вектором атрибутов. Это будет работать так же хорошо. Не знаю, откуда я взял уравнения, но я их придумал не сам. Насколько я помню, они получаются, начиная с барицентрических координат, затем вычисляя одно интерполированное значение и упрощая уравнения. - person Nils Pipenbrinck; 04.09.2014
comment
Я вырезал и вставил уравнения более или менее прямо из старого кода растеризатора треугольников, который я написал еще в 90-х. :-) - person Nils Pipenbrinck; 04.09.2014
comment
в dfdx вы работаете с компонентом y. Это правильно? - person tower120; 04.09.2014
comment
Ага. Верно. Поскольку мы делим все уравнение на d, компонент y сокращается, а компонент x остается в уравнении. - person Nils Pipenbrinck; 04.09.2014
comment
Мой dFdy кажется всегда перевернутым знаком s000.tinyupload.com/index.php?file_id=90985762636944752928 (файл mathematica) или простой txt s000.tinyupload.com/index. php?file_id=57702494364821549967 - person tower120; 05.09.2014
comment
Должно быть, мы используем другой порядок индексов. Что было в вашем растеризаторе? Против часовой стрелки? - person tower120; 05.09.2014