2012-04-24 38 views
8

कुछ दिन पहले मैंने बेजियर वक्र को कुशलतापूर्वक चित्रित करना शुरू कर दिया था, और मैं चार्ल्स लूप और जिम ब्लिंन द्वारा विकसित इस विधि में आया जो बहुत दिलचस्प लग रहा था। कितनी बार, उनके एल्गोरिदम के साथ प्रयोग करने के बाद, मैं बस क्यूबिक घटता प्रस्तुत करने में सक्षम होने के लिए प्रतीत नहीं कर सकता। Quadratics ठीक है, कोई समस्या नहीं है।बेज़ीयर वक्र, लूप और ब्लिंन शैली

केवल संसाधनों मैं पाया है अब तक इस प्रकार हैं:

GPU Gems 3 Chapter 25

Curvy Blues

Resolution Independent Curve Rendering using Programmable Graphics Hardware

परीक्षण को और जल्दी से चलाने के लिए, मैं इस कर रहा हूँ XNA। असल में मैं जीपीयू में अपने शिखर के साथ बनावट निर्देशांक पास कर रहा हूं, एक परिप्रेक्ष्य परिवर्तन लागू करता हूं और अंतिम परिणाम प्रस्तुत करने के लिए पिक्सेल शेडर में सभी लेखों में वर्णित सूत्र का उपयोग करता हूं। कितनी बार, समस्या (मुझे लगता है) यह बताता है कि मैं बनावट निर्देशांक की गणना कैसे करता हूं। इस कोड की जाँच करें:

public void Update() 
{ 
    float a1 = Vector3.Dot(p1, Vector3.Cross(p4, p3)); 
    float a2 = Vector3.Dot(p2, Vector3.Cross(p1, p4)); 
    float a3 = Vector3.Dot(p3, Vector3.Cross(p2, p2)); 

    float d1 = a1 - 2 * a2 + 3 * a3; 
    float d2 = -a2 + 3 * a3; 
    float d3 = 3 * a3; 

    float discr = d1 * d1 * (3 * d2 * d2 - 4 * d1 * d3); 

    if (discr > 0) 
    { 
     Type = CurveTypes.Serpentine; 

     float ls = 3 * d2 - (float)Math.Sqrt(9 * d2 * d2 - 12 * d1 * d3); 
     float lt = 6 * d1; 
     float ms = 3 * d2 + (float)Math.Sqrt(9 * d2 * d2 - 12 * d1 * d3); 
     float mt = 6 * d1; 

     TexCoord1 = new Vector3(ls * ms, (float)Math.Pow(ls, 3), (float)Math.Pow(ms, 3)); 
     TexCoord2 = new Vector3((3 * ls * ms - ls * mt - lt * ms)/3, ls * ls * (ls - lt), ms * ms * (ms - mt)); 
     TexCoord3 = new Vector3((lt * (mt - 2 * ms) + ls * (3 * ms - 2 * mt))/3, (float)Math.Pow(lt - ls, 2) * ls, (float)Math.Pow(mt - ms, 2) * ms); 
     TexCoord4 = new Vector3((lt - ls) * (mt - ms), -(float)Math.Pow(lt - ls, 3), -(float)Math.Pow(mt - ms, 3)); 
    } 
    else if (discr == 0) 
    { 
     Type = CurveTypes.Cusp; 
    } 
    else if (discr < 0) 
    { 
     Type = CurveTypes.Loop; 
    } 
} 

कीजिए गड़बड़ है, यह सिर्फ कुछ परीक्षण कोड है। पी 1 ... पी 4 विश्व अंतरिक्ष में नियंत्रण बिंदु हैं, और TexCoord1 ... TexCoord4 इसी बनावट निर्देशांक हैं। यह जीपीयू जेम्स लेख में जो कहा गया है उसका एक प्रतिकृति है।

वहाँ कुछ समस्याओं यहाँ हैं, पहले जब a3 की गणना, हम दोनों मानकों, जो निश्चित रूप से हमेशा एक (0,0,0) वेक्टर में जो परिणाम के लिए p2 का उपयोग करें और इस बात का डॉट उत्पाद लेने और p3 हमेशा होगा हमें 0 दें। यह बहुत बेकार नहीं है, तो वे लेख में क्यों उल्लेख करेंगे?

यह निश्चित रूप से डिस्क को गलत बना देगा, और हम यह निर्धारित करने में भी सक्षम नहीं होंगे कि यह किस प्रकार का वक्र है।

थोड़ी देर के लिए उस कोड के साथ झुकाव के बाद, मैंने इसे ठीक करने की कोशिश करने का फैसला किया कि उन्होंने लूप और ब्लिंन पेपर में क्यों किया। उस से मुझे कुछ ऐसा मिलता है:

public void Update() 
{ 
    Matrix m1 = new Matrix(
     p4.X, p4.Y, 1, 0, 
     p3.X, p3.Y, 1, 0, 
     p2.X, p2.Y, 1, 0, 
     0, 0, 0, 1); 
    Matrix m2 = new Matrix(
     p4.X, p4.Y, 1, 0, 
     p3.X, p3.Y, 1, 0, 
     p1.X, p1.Y, 1, 0, 
     0, 0, 0, 1); 
    Matrix m3 = new Matrix(
     p4.X, p4.Y, 1, 0, 
     p2.X, p2.Y, 1, 0, 
     p1.X, p1.Y, 1, 0, 
     0, 0, 0, 1); 
    Matrix m4 = new Matrix(
     p3.X, p3.Y, 1, 0, 
     p2.X, p2.Y, 1, 0, 
     p1.X, p1.Y, 1, 0, 
     0, 0, 0, 1); 

    float det1 = m1.Determinant(); 
    float det2 = -m2.Determinant(); 
    float det3 = m3.Determinant(); 
    float det4 = -m4.Determinant(); 

    float tet1 = det1 * det3 - det2 * det2; 
    float tet2 = det2 * det3 - det1 * det4; 
    float tet3 = det2 * det4 - det3 * det3; 

    float discr = 4 * tet1 * tet3 - tet2 * tet2; 

    if (discr > 0) 
    { 
     Type = CurveTypes.Serpentine; 

     float ls = 2 * det2; 
     float lt = det3 + (float)((1/Math.Sqrt(3)) * Math.Sqrt(3 * det3 * det3 - 4 * det2 * det4)); 
     float ms = 2 * det2; 
     float mt = det3 - (float)((1/Math.Sqrt(3)) * Math.Sqrt(3 * det3 * det3 - 4 * det2 * det4)); 

     TexCoord1 = new Vector3(lt * mt, (float)Math.Pow(lt, 3), (float)Math.Pow(mt, 3)); 
     TexCoord2 = new Vector3(-ms * lt - ls * mt, -3 * ls * lt * lt, -3 * ms * mt * mt); 
     TexCoord3 = new Vector3(ls * ms, 3 * ls * ls * lt, 3 * ms * ms * mt); 
     TexCoord4 = new Vector3(0, -ls * ls * ls, -ms * ms * ms); 
    } 
    else if (discr == 0) 
    { 
     Type = CurveTypes.Cusp; 
    } 
    else if (discr < 0) 
    { 
     Type = CurveTypes.Loop; 
    } 
} 

मान लीजिए कि यह काम नहीं करता है। कितनी बार, डिस्कर कम से कम थोड़ा और सही प्रतीत होता है। कम से कम इसका सही संकेत है, और यह शून्य है जब नियंत्रण बिंदु को एक कुंड बनाने के लिए व्यवस्थित किया जाता है। हालांकि मुझे वही दृश्य परिणाम मिलता है, हालांकि वक्र को थोड़ी देर के लिए यादृच्छिक रूप से गायब हो जाता है (पिक्सेल शेडर फॉर्मूला हमेशा शून्य से अधिक होता है) और नियंत्रण बिंदु को वापस एक वर्ग आकार में ले जाने के बाद लौटाता है। यहां पिक्सेल शेडर कोड है:

PixelToFrame PixelShader(VertexToPixel PSIn) 
{ 
    PixelToFrame Output = (PixelToFrame)0; 

    if(pow(PSIn.TexCoords.x, 3) - PSIn.TexCoords.y * PSIn.TexCoords.z > 0) 
    { 
    Output.Color = float4(0,0,0,0.1); 
    } 
    else 
    { 
    Output.Color = float4(0,1,0,1); 
    } 

    return Output; 
} 

यह सभी उपयोगी जानकारी है जो मैं अभी सोच सकता हूं। क्या किसी को पता है कि क्या हो रहा है? क्योंकि मैं उनमें से बाहर चला रहा हूँ।

+0

मैं अपने आप को इस पद्धति को लागू करने शुरू कर दिया और जब मैं कुछ काम कर रहे है वापस पोस्ट करेंगे। बस आप को पता है कि इस सवाल का नहीं छोड़ा है चाहता था :) – Ani

+0

@ananthonline भयानक! कृपया कीजिए! – Roliga

+0

मुझे इसके साथ भी समस्याएं हैं। क्या आप इसे काम करने के लिए मिला? क्या तुम मेरे सवाल का जवाब दे सकते हो? http://stackoverflow.com/questions/15519142/resolution-independent-cubic-bezier-drawing-on-gpu-blinn-loop – scippie

उत्तर

7

मैं पेपर और आपका कोड देख रहा था, और यह सीम है कि आप एम 3 मैट्रिक्स में गुणा खो रहे हैं।

आपका P1, P2, P3 और P4 निर्देशांक इसे प्रयोग निर्धारकों की गणना करने के पहले एक मैट्रिक्स में रखा जाना चाहिए और गुणा एम 3 मैट्रिक्स द्वारा,। उदाहरण के लिए।

Matrix M3 = Matrix(
    1, 0, 0, 0, 
    -3, 3, 0, 0, 
    3, -6, 3, 0, 
    -1, 3, -3, 1); 
Matrix B = Matrix(
    p1.X, p1.Y, 0, 1, 
    p2.X, p2.Y, 0, 1, 
    p3.X, p3.Y, 0, 1, 
    p4.X, p4.Y, 0, 1); 
Matrix C = M3*B; 

तो फिर तुम सी मैट्रिक्स की प्रत्येक पंक्ति के निर्देशांकों के रूप में एम 1 के लिए अपने कोड में मैट्रिक्स एम 4 का उपयोग करें। जहां पंक्ति के पहले और दूसरे मान x, y निर्देशांक हैं और अंतिम w समन्वय है।

अंत में बनावट निर्देशांक के मैट्रिक्स को एम 3 उदाहरण के विपरीत से विचलित करने की आवश्यकता है।

Matrix invM3 = Matrix(
    1, 0, 0, 0, 
    1, 0.3333333, 0, 0, 
    1, 0.6666667, 0.333333, 0, 
    1, 1, 1, 1); 
Matrix F = Matrix(
    TexCoord1, 
    TexCoord2, 
    TexCoord3, 
    TexCoord4); 
Matrix result = invM3*F; 

परिणामी मैट्रिक्स की प्रत्येक पंक्ति शेडर के लिए आवश्यक बनावट निर्देशांक से मेल खाती है।

मैं इसे अपने आप अभी तक लागू नहीं किया है, इसलिए गारंटी नहीं दे सकते कि है कि यह आपकी समस्या का समाधान होगा। पेपर पढ़ने के बाद मैंने आपके कार्यान्वयन से जो कुछ भी खोया है, वह वही है।

मुझे आशा है कि इस मदद करता है, अगर मैं गलत कृपया मुझे बताओ क्योंकि मैं इस जल्दी ही बाहर की कोशिश कर रहा हो जाएगा हूँ।

+0

बहुत बढ़िया आदमी! विश्वास नहीं कर सकता कि मैं इसे में गड़बड़ है कि बुरा था: डी समस्या हालांकि, det1 हमेशा 0 है, जो निश्चित रूप से सही नहीं है हो रहा है है। मैं कल कुछ और परीक्षण करने जा रहा हूं और देख सकता हूं कि मुझे समस्या मिल सकती है या नहीं। मुझे बताओ कि क्या आपके पास कोई विचार है। – Roliga

+1

पहले पैराग्राफ में इंटीग्रल क्यूबिक्स सेक्शन (4.4) में पेपर में, यह कहता है कि अभिन्न क्यूबिक्स के लिए इसका पहला निर्धारक बराबर शून्य होगा। जो sh^3-lm – rdsgalvao

+0

ओह दाएं कोडर कोड समीकरण को कम करता है। कारण मैंने सोचा कि कुछ गलत था क्योंकि मैंने केवल उन घटकों को सोचा था जो वास्तव में लूप को लूप समीकरण का उपयोग करना चाहते थे, लेकिन यह मामला प्रतीत नहीं होता था, इसलिए लूप समीकरण को लागू करने के बाद यह सब काम करता था। अब इस चीज को संरचित करने के लिए इसे वास्तव में इस्तेमाल किया जा सकता है: यदि मैं किसी और समस्या में भाग लेता हूं तो मैं एक और टिप्पणी छोड़ दूंगा। – Roliga