2012-11-03 13 views
8

मैं वर्तमान में सी में एक छोटे से परियोजना पर काम कर रहा हूँ ++ और ओपन और एक रंग चयन उपकरण है कि में फ़ोटोशॉप के समान लागू करने के लिए कोशिश कर रहा हूँ, जैसा कि नीचे।ओपन रंग प्रक्षेप

enter image description here

हालांकि मैं बड़े वर्ग के प्रक्षेप साथ परेशानी हो रही हूँ। एक 8800 GTS के साथ अपने डेस्कटॉप कंप्यूटर पर काम करते हुए परिणाम समान था लेकिन सम्मिश्रण के रूप में चिकनी नहीं था।

इस कोड मैं का उपयोग कर रहा है:

GLfloat swatch[] = { 0,0,0, 1,1,1, mR,mG,mB, 0,0,0 }; 
GLint swatchVert[] = { 400,700, 400,500, 600,500, 600,700 }; 

glVertexPointer(2, GL_INT, 0, swatchVert); 
glColorPointer(3, GL_FLOAT, 0, swatch); 
glDrawArrays(GL_QUADS, 0, 4); 

के साथ इंटेल ग्राफिक्स HD 3000 अपने लैपटॉप पर चल कर, इस परिणाम कोड में कोई परिवर्तन नहीं और भी बदतर था।

http://i.imgur.com/wSJI2.png

मैंने सोचा कि यह ओपन दो त्रिकोण में ट्रैक्टर बंटवारे था, इसलिए मैं त्रिकोण के उपयोग से रेंडर और अपने आप को वर्ग के बीच में रंग interpolating की कोशिश की लेकिन यह अभी भी काफी परिणाम मैं के लिए उम्मीद से मेल नहीं करता है । enter image description here

एक ट्रैक्टर पर यह लागू करना अब पैदावार:

#ifdef GL_ES 
precision highp float; 
#endif 

uniform vec2 resolution; 

void main(void) 
{ 
    vec2 p = gl_FragCoord.xy/resolution.xy; 
    float gray = 1.0 - p.x; 
    float red = p.y; 
    gl_FragColor = vec4(red, gray*red, gray*red, 1.0); 
} 

यहाँ परिणाम है:

enter image description here

उत्तर

11

मैं जल्दी से एक शीर्ष/टुकड़ा शेडर कि सफलतापूर्वक रंग interpolates कर दिया है सही परिणाम क्योंकि प्रक्षेप सही मायने में पूरी सतह x और y निर्देशांक का उपयोग करने पर किया जाता है। यह क्यों काम करता है के रूप में @ डेटनवॉल्फ के विस्तृत स्पष्टीकरण देखें।

संपादित करें 1 आदेश में एक कार्यात्मक रंग पिकर में रंग की पूरी रेंज प्राप्त करने के लिए, यह (https://stackoverflow.com/a/9234854/570738 देखें) सहभागी रंग को संशोधित करने के लिए संभव है।

लाइव ऑनलाइन डेमो: http://goo.gl/Ivirl

#ifdef GL_ES 
precision highp float; 
#endif 

uniform float time; 
uniform vec2 resolution; 

const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0); 
const vec4 kRGBToI  = vec4 (0.596, -0.275, -0.321, 0.0); 
const vec4 kRGBToQ  = vec4 (0.212, -0.523, 0.311, 0.0); 

const vec4 kYIQToR = vec4 (1.0, 0.956, 0.621, 0.0); 
const vec4 kYIQToG = vec4 (1.0, -0.272, -0.647, 0.0); 
const vec4 kYIQToB = vec4 (1.0, -1.107, 1.704, 0.0); 

const float PI = 3.14159265358979323846264; 

void adjustHue(inout vec4 color, float hueAdjust) { 
    // Convert to YIQ 
    float YPrime = dot (color, kRGBToYPrime); 
    float I  = dot (color, kRGBToI); 
    float Q  = dot (color, kRGBToQ); 

    // Calculate the hue and chroma 
    float hue  = atan (Q, I); 
    float chroma = sqrt (I * I + Q * Q); 

    // Make the user's adjustments 
    hue += hueAdjust; 

    // Convert back to YIQ 
    Q = chroma * sin (hue); 
    I = chroma * cos (hue); 

    // Convert back to RGB 
    vec4 yIQ = vec4 (YPrime, I, Q, 0.0); 
    color.r = dot (yIQ, kYIQToR); 
    color.g = dot (yIQ, kYIQToG); 
    color.b = dot (yIQ, kYIQToB); 
} 

void main(void) 
{ 
    vec2 p = gl_FragCoord.xy/resolution.xy; 
    float gray = 1.0 - p.x; 
    float red = p.y; 
    vec4 color = vec4(red, gray*red, gray*red, 1.0); 
    adjustHue(color, mod(time, 2.0*PI)); 
    gl_FragColor = color; 
} 

संपादित 2: यदि आवश्यक हो, बनावट निर्देशांक के साथ प्रयोग के लिए शेडर (बनावट के साथ 0 से 1 तक निर्देशांक quads पर लागू करने के लिए) कुछ इस तरह दिखना चाहिए। अनचाहे।

टुकड़ा शेडर:

void main(void) 
{ 
    vec2 p = gl_TexCoord[0].st; 
    float gray = 1.0 - p.x; 
    float red = p.y; 
    gl_FragColor = vec4(red, gray*red, gray*red, 1.0); 
} 

एक पासथ्रू शिखर शेडर:

void main() 
{ 
    gl_TexCoord[0]=gl_MultiTexCoord0; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 
+0

आपके उत्तर के लिए धन्यवाद, मैं के साथ बहुत कम अनुभव है जीएलएसएल हालांकि मुझे लगता है कि अगर आप एक शेडर का उपयोग करना चाहते हैं तो आपको पढ़ना याद रखना प्रतीत होता है क्योंकि आपको ओपनजीएल पाइपलाइन को पूरी तरह से बदलना है? क्या आपके द्वारा प्रदान किए गए शेडर का उपयोग करने का एक आसान तरीका है और केवल इसे glDrawArrays() के एक कॉल पर लागू कर रहा है? –

+0

@ विल-ऑफ-फॉर्च्यून: जब तक आप OpenGL-2.1 के साथ चिपके रहते हैं और नीचे आप चुनिंदा शेडर्स का चयन कर सकते हैं। अर्थात। ज्यादातर चीजों के लिए निश्चित फ़ंक्शन पाइपलाइन का उपयोग करें, लेकिन केवल कुछ पर एक शेडर। केवल ओपनजीएल -3 कोर के साथ और बाद में * * शेडर्स का उपयोग करना चाहिए। लेकिन ईमानदारी से: शेडर्स का उपयोग जीवन को इतना आसान बनाता है, इसलिए मैं दृढ़ता से उनको हर जगह उपयोग करने का सुझाव देता हूं। – datenwolf

+0

@ विल-ऑफ-फॉर्च्यून मैं आमतौर पर फ्रेमवर्क या ग्राफिक्स इंजन का उपयोग करता हूं जो शेडर्स को प्रबंधित करना आसान बनाता है। हालांकि, मैं आपको इसका उल्लेख करता हूं: http://nehe.gamedev.net/article/glsl_an_introduction/25007/ "जीएलएसएल एपीआई" अपने ओपनजीएल एप्लिकेशन में जीएलएसएल का उपयोग कैसे करें "अनुभाग पर जाएं। यह अनुभाग आपको दिखाएगा कि ग्लोस्ल शेडर्स को इन टिप्पणियों में से बेहतर तरीके से कैसे शामिल किया जाए। – num3ric

9

ओपन मूल्यों एक शीर्ष शेडर से एक टुकड़ा शेडर की प्रति-टुकड़ा इनपुट मानों को उत्सर्जित पर barycentric प्रक्षेप का उपयोग करता है । आप जो देखते हैं वहां क्वाड को त्रिकोण में विभाजित करने का प्रभाव होता है जैसा कि आपने पहले ही अनुमान लगाया है।

अब इसे देखें: इसमें शीर्ष दाएं त्रिकोण है जिसमें लाल रंग है, और इसलिए इसमें लाल राशि के साथ अच्छी तरह से नीचे बहती है। और फिर इसमें केवल भूरे रंग के साथ नीचे बाएं त्रिकोण है।बेशक शीर्ष दाएं त्रिकोण का लाल निचले बाएं के भूरे रंग में योगदान नहीं देगा।

समस्या यह है कि आरजीबी स्पेस में इंटरपोलेशन होता है, लेकिन आपके वांछित परिणाम के लिए एचएसवी या एचएसएल स्पेस में रखा जाना चाहिए, जहां एच (ह्यू) स्थिर रखा जाएगा।

हालांकि यह केवल इंटरपोलेशन का मामला नहीं है। आपके रास्ते में क्या हो रहा है, कि रंग रैखिक रूप से अंतर नहीं करते हैं; अधिकांश डिस्प्ले में एक nonlinear फ़ंक्शन लागू होता है, जिसे "गामा" भी कहा जाता है (वास्तव में गामा इनपुट मानों पर लागू शक्ति का एक्सपोनेंट होता है)।

आपका ओपनजीएल संदर्भ रंग सुधारित रंग स्थान में हो सकता है या नहीं। आपको इसके लिए परीक्षण करने की ज़रूरत है। फिर फ्रेमबफर में कौन सा रंग स्थान रहता है, यह जानने के लिए, आपको एक टुकड़ा शेडर का उपयोग करके प्रति खंड मूल्यों में बैरिएंट्रिक निर्देशांक (एक कशेरुक शेडर का उपयोग करके मूल्यांकन) के प्रति खंड परिवर्तन को लागू करना होगा।

3

मैं शीर्ष मतदान जवाब पसंद नहीं आया, क्योंकि यह तो शाब्दिक है और केवल बहुत आसान जवाब में लाल पर केंद्रित है तो मैं शीर्ष रंग के आधार पर एक सरल विकल्प के साथ में आना चाहा:

#version 330 core 

smooth in vec4 color; 
smooth in vec2 uv; 

out vec4 colorResult; 

void main(){ 
    float uvX = 1.0 - uv.st.x; 
    float uvY = uv.st.y; 

    vec4 white = vec4(1, 1, 1, 1); 
    vec4 black = vec4(0, 0, 0, 1); 

    colorResult = mix(mix(color, white, uvX), black, uvY); 
} 

यह समझाने और तर्क के लिए सरल है। मिश्रण एक रैखिक इंटरपोलेशन, या glsl में lerp है। तो मैं उलटा एक्स अक्ष के साथ कशेरुक रंग और सफेद के बीच मिश्रण करता हूं, यह मुझे ऊपर बाईं ओर सफेद बाएं और शुद्ध रंग में सफेद रंग देता है। इसके परिणामस्वरूप मैं वाई अक्ष के साथ काले रंग में मिलाकर मुझे नीचे काले रंग देता हूं।

उम्मीद है कि यह मदद करता है, मैं इस जवाब में आया और पाया कि यह हार्ड-बेक्ड लाल, हरे, या नीले रंग के पैलेट के अलावा कुछ भी प्राप्त करने में बहुत उपयोगी नहीं था, और समायोजन हू बिट बस इतना नहीं था जो मैं चाहता था।

मूल रूप से यह आप अपने वांछित रंग के शीर्ष रंग के सभी सेट करना चाहते हैं काम करने के लिए मिलता है, और सुनिश्चित करें कि आपके यूवी निर्देशांक सेट कर रहे हैं:

TL: UV(0, 0), COLOR(YOUR DESIRED COLOR) 
BL: UV(0, 1), COLOR(YOUR DESIRED COLOR) 
BR: UV(1, 1), COLOR(YOUR DESIRED COLOR) 
TR: UV(1, 0), COLOR(YOUR DESIRED COLOR) 
संबंधित मुद्दे