2015-07-10 17 views
8

Moim zadaniem jest renderowanie kwadratowej krzywej Beziera (ścieżki) za pomocą technologii Stage3d (Adobe Flash), która nie ma żadnych rozszerzeń dla tego rysunku po wyjęciu z pudełka (podczas gdy OpenGl go ma, jak wiem). Tak, jest grafika Starling-Extension-Graphics, ale wykorzystuje ona prostą metodę dzielenia segmentu krzywej na wiele linii prostych, które generują bardzo wiele trójkątów dla mojej długiej ścieżki krzywej.Narysuj krzywą kwadratową na GPU

Więc .. Jest idealny sposób na renderowanie kształtów o nierozpoznawalnych kształtach dla pętli i Blinna. Czytałem artykuł GPUGems3 (gpugems3_ch25.html) i przeniesiony ten fragment shader do AGAL2:

Quadratic Curve Pixel Shader

float4 QuadraticPS(float2 p : TEXCOORD0, 
    float4 color : COLOR0) : COLOR 
{ 
    // Gradients 
    float2 px = ddx(p); 
    float2 py = ddy(p); 
    // Chain rule 
    float fx = (2*p.x)*px.x - px.y; 
    float fy = (2*p.x)*py.x - py.y; 
    // Signed distance 
    float sd = (p.x*p.x - p.y)/sqrt(fx*fx + fy*fy); 
    // Linear alpha 
    float alpha = thickness - abs(sd); 
    if (alpha > 1)  // Inside 
    color.a = 1; 
    else if (alpha < 0) // Outside 
    clip(-1); 
    else     
    // Near boundary 
    color.a = alpha; 
    return color; 
} 

to działa. Ale istnieją dwa podstawowe problemy:.

  1. I nie rozumieją, że algorytm :(Czytałem o podpisane pole odległości, pochodnych i innych ... Myślałem wiele godzin i ponownie przeczytać - ale nie ! wynik Moje pytanie brzmi: czy ktoś może mi pomóc i wyjaśnić, co się dzieje w tym shaderów (linia po linii(), jeśli to możliwe!)

  2. Drugim problemem jest to, że krzywa jest obcięty u? narożnik trójkąta o zmiennej grubości. Proszę spojrzeć na zdjęcie: https://monosnap.com/file/84EBOuQ1czNM5lprQ5VlnRUKP2mKmW Jeśli więc narysować ścieżkę wygląda to tak: https://monosnap.com/file/54Zs5Xui6s3BL6lNdZRCx9ibcV2bCF

lubię tę metodę za pomocą jednego trójkąta na segment krzywej, ponieważ nie każdy geometria potrzebne. I nie muszę mieć bardzo grubych łuków (1-2 px jest doskonałe), ale zmienna grubość jest problemem. Czy ktoś może mi pomóc?

(Przepraszam za mój angielski. To nie jest mój język ojczysty.)

[Edit1 przez Spektre] prostu przeniósł się z komentarzem i nieprawidłowej odpowiedzi

Planuję użyć jednego trójkąta na jedną Segment krzywa, coś jak na zdjęciu

  • the path
  • ścieżka składa się z MA ny trójkąty
  • jeden na jeden segment ścieżki (kwadratowa krzywej)
  • jak radzić sobie sprawę z tego podejścia, jeśli wszystkie punkty kontrolne są współliniowe (leżą na tej samej prostej) lub kolinearne?
+0

dodać szczegóły jak które kwadratowa krzywej czy używasz (równań) ile punktów konturu na krzywej itp., to wygląda na to, że używasz prymitywu trójkąta (przyczyna artefaktów grubości) może być QUAD_STRIP byłoby lepsze (gdzie punkty kontrolne znajdują się wewnątrz łaty quadowej sposób, taki jak quad, to ciągłe powiększanie punktów kontrolnych czworokąta lub co, ale to jest trudne do generycznych krzywych) lub ol punkty oddzielnie jako inny układ atrybutów – Spektre

+0

Dziękuję, Spectre! Chcę narysować dowolne krzywe kwadratowe Beziera, opisane przez 3 punkty kontrolne. Teraz myślę, że najlepszym sposobem na to jest: 1. Użyj kwadratu o stałym powiększeniu (o 2 trójkąty) jako "płótna", gdzie mogę rysować wszystko proceduralnie. 2. Znajdź konkretne kwadratowe równanie qurve (http: //math.stackexchange .com/questions/1360891/find-quadratic-bezier-curve-equation-based-on-its-control-points) i przekazuje go do modułu cieniującego zamiast do domyślnego równania Loop/Blinn (u^2 - v = 0) . 3. Narysuj to nowe równanie algorytmem Loopa/Blinna. – Ilya

Odpowiedz

6

dla 3 Control Point krzywych Beziera będę:

  1. stosowanie trójkątów pierwotnych
  2. powiększyć punkty kontrolne obejmują obszar wokół krzywej uniknąć artefakty

    triangle enlargement

Ta metoda jest szybka i nie ma problemu z wyliczeniem A',B',C' z A,B,C i na odwrót. Jeśli skala jest stała (na przykład scale=1.25), wówczas maksymalna użyteczna krzywa thickness<=2.0*min(|control_point-M|)*(scale-1.0).

Dla większego zwiększenia można obliczyć wymaganą skalę (na przykład w module cieniującym geometrii) i przekazać ją do wierzchołka i fragmentu ... Wszystko powyżej może być wykonane za pomocą modułu cieniującego Geometria. Powinieneś użyć przezroczystość, aby poprawnie połączyć krzywe razem. Średni punkt środkowy powinien pozostać taki sam M=A+B+C=A'+B'+C'

czy przezroczystość nie jest opcją

Następnie trzeba zmienić podejście więc przechodzić punktów kontrolnych i położenia wewnątrz tekstur.

  1. utworzyć jeden 2D float tekstury z punktów kontrolnych

    • coś jak float pnt[9][N]
    • pnt[0,1,2][] jest punkt kontrolny A(x,y,z)
    • pnt[3,4,5][] jest punkt kontrolny B(x,y,z)
    • pnt[6,7,8][] jest punkt kontrolny C(x,y,z)
  2. także stworzyć 1D tekstury kolor

    • coś rgba col[N]
    • Uchwała x oś obu faktur = N jest liczba krzywych Beziera
  3. teraz wyciągnąć pojedynczą Quad zasłanianie całego ekranu

    I wewnątrz modułu cieniującego fragmentu sprawdź, czy piksel znajduje się wewnątrz dowolnej krzywej. Jeśli tak, wypisz jego kolor ...

To może stać się bardzo powoli na wysokim krzywej Beziera liczyć N

[Edit1] prawie współliniowych punktów kontrolnych

dla tych użyłbym quady

quad enlarge

  • D,E są dublowane punkty A,B wokół C
  • D=C+C-A
  • E=C+C-B
  • C jest środkowego punktu M = (A+B+D+E)/4 = C = (A'+B'+C'+D')/4
  • i A',B',C',D' są powiększone A,B,D,E punkty kontrolne
  • A'=C+(A -C)*scale
  • B'=C+(B -C)*scale
  • A =C+(A'-C)/scale
  • B =C+(B'-C)/scale

ten może być stosowany dla każdego Beziera nie tylko prawie współliniowo ale używa większych wielokątów tak będzie wolniejszy na wydajności (więcej fragmentów wtedy naprawdę potrzebne)

+0

Dziękuję bardzo, Spectre! To jest fantastyczne!!! Tak myślałem, ale nie mogłem pisać! Prawdopodobnie zadziała bardzo szybko! – Ilya

+0

Hm ... Nie ukrywam, dlaczego potrzebuję przejrzystości ... Co masz na myśli? Drugie podejście nie jest teraz całkiem jasne ... ( – Ilya

+0

@Jeśli masz tylko pojedyncze kolorowe krzywe Beziera, to nie potrzebujesz przezroczystości, ale musisz wyrzucić fragmenty, które nie są używane przez krzywą, w przeciwnym razie pusty obszar trójkąta (nałożony/powiększony obszar) usunie już narysowane krzywe Beziera ... – Spektre