2012-02-10 39 views
21

क्या जीएलएसएल (टुकड़ा शेडर) का उपयोग कर 2 डी ओपनजीएल बनावट के कुशलतापूर्वक बदलाव करने का कोई तरीका है?जीएलएसएल के साथ बनावट के रंग को कैसे बदला जाए?

क्या किसी के पास इसके लिए कुछ कोड है?

अद्यतन: यह user1118321 सुझाव से उत्पन्न कोड है:

uniform sampler2DRect texture; 
const mat3 rgb2yiq = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135); 
const mat3 yiq2rgb = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.1070, 1.7046); 
uniform float hue; 

void main() { 

vec3 yColor = rgb2yiq * texture2DRect(texture, gl_TexCoord[0].st).rgb; 

float originalHue = atan(yColor.b, yColor.g); 
float finalHue = originalHue + hue; 

float chroma = sqrt(yColor.b*yColor.b+yColor.g*yColor.g); 

vec3 yFinalColor = vec3(yColor.r, chroma * cos(finalHue), chroma * sin(finalHue)); 
gl_FragColor = vec4(yiq2rgb*yFinalColor, 1.0); 
} 

और यह एक संदर्भ के साथ तुलना में परिणाम है:

enter image description here

मैं साथ मैं स्विच करने की कोशिश की क्यू के अंदर क्यू लेकिन परिणाम 0 डिग्री

के आसपास भी गलत है कोई संकेत?

तो तुलना के लिए की जरूरत है, यह मूल असंशोधित छवि है: enter image description here

+5

यह आरजीबी चारों ओर (1,1,1) वेक्टर ट्रिपल की एक रोटेशन है - आपको लगता है कि व्यक्त कर सकते हैं शेडर – Flexo

+0

में एक आव्यूह गुणन के रूप में यदि आपका रंग पारी स्थिर है तो आप छोड़ सकते हैं अतान, वर्ग, पाप, और कॉस। आप जो कर रहे हैं वह उन्हें ध्रुवीय निर्देशांक में परिवर्तित कर रहा है, कोण को जोड़ रहा है, और वापस परिवर्तित कर रहा है। आप इस गणित को 2x2 रोटेशन मैट्रिक्स के साथ कर सकते हैं। यदि आपको यिक स्पेस में कोई अन्य गणित करने की आवश्यकता नहीं है तो आप पूरे ट्रांसफॉर्म को सटीक बना सकते हैं।2 डी रोटेशन (3x3 तक गद्देदार) के साथ अपने rgb2yiq को गुणा करें और फिर yiq2rgb के साथ एक बड़ी 3x3 मैट्रिक्स प्राप्त करने के लिए जो पूरी प्रक्रिया करता है। जो, जैसे @ फ्लेक्सो कहते हैं, (1,1,1) वेक्टर के आसपास बस एक घूर्णन है। –

उत्तर

23

जबकि क्या @awoodland कहते हैं सही है, कि विधि luminance में परिवर्तन के साथ समस्याओं का कारण बन सकता है, मेरा मानना ​​है कि।

एचएसवी और एचएलएस रंग प्रणाली कई कारणों से समस्याग्रस्त हैं। मैंने हाल ही में इस बारे में एक रंग वैज्ञानिक से बात की, और उसकी सिफारिश YIQ या YCbCr स्थान में कनवर्ट करना था और क्रोमो चैनल (I & क्यू, या सीबी & सीआर) को समायोजित करना था। (सीबी के लिए देख रहा है == 0), उन स्थानों में से एक में (आप कि here और here कैसे करना सीख सकते हैं।)

एक बार जब आप hue = atan(cr/cb) करके, कोण क्रोमा चैनलों द्वारा गठित से रंग प्राप्त कर सकते हैं। यह आपको रेडियंस में एक मूल्य देता है। बस घुमावदार रोटेशन राशि जोड़कर इसे घुमाएं। एक बार ऐसा करने के बाद, आप chroma = sqrt(cr*cr+cb*cb) के साथ क्रोमा की परिमाण की गणना कर सकते हैं। आरजीबी पर वापस जाने के लिए, Cr = chroma * sin (hue), Cb = chroma * cos (hue) का उपयोग करके नए सीबी और सीआर (या I & क्यू) की गणना करें। फिर उपरोक्त वेब पृष्ठों पर वर्णित आरजीबी में वापस कनवर्ट करें।

संपादित करें: यहां एक समाधान है जिसका मैंने परीक्षण किया है और मुझे आपके संदर्भ के समान परिणाम देने लगता है। आप शायद मैट्रिक्स पलता में डॉट उत्पादों में से कुछ संक्षिप्त कर सकते हैं:

uniform sampler2DRect inputTexture; 
uniform float hueAdjust; 
void main() 
{ 
    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); 

    // Sample the input pixel 
    vec4 color = texture2DRect (inputTexture, gl_TexCoord [ 0 ].xy); 

    // 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); 

    // Save the result 
    gl_FragColor = color; 
} 
+0

धन्यवाद, मैंने अभी इसे कार्यान्वित किया है लेकिन यह सही तरीके से काम नहीं कर रहा है .. यह वास्तव में एक रंग परिवर्तन देता है लेकिन यह फ़ोटोशॉप रंग समायोजन (उदाहरण के लिए) से बिल्कुल अलग है। मैंने इसे वाईआईक्यू में बदलने का फैसला किया है क्योंकि वाईसीबीसीआर के साथ मुझे भी सबसे खराब परिणाम मिल रहे थे। इसलिए मैंने गणना की है 'ह्यू = एटान 2 (क्यू, आई)', 'क्रोमा = एसकर्ट (आई * आई + क्यू * क्यू)' और फिर 'आई = क्रोमा * पाप (ह्यू)', 'क्यू = क्रोमा * कॉस (ह्यू) '। क्या यह सही है? क्या मैं कुछ भूल रहा हूँ? – Andrea3000

+0

यह मेरे लिए सही लगता है। आपको क्या परिणाम मिल रहे हैं? (क्या सिर्फ गलत गड़बड़ है, या चमक और संतृप्ति गड़बड़ हो रही है?) क्या परिणाम आपको उम्मीद है कि अगर आप I और Q को 'atan2() 'कॉल में उलटते हैं तो आप क्या उम्मीद करते हैं? हो सकता है कि अगर आपने कुछ कोड पोस्ट किया है, तो हम इसे आपके लिए दोबारा जांच सकते हैं। – user1118321

+0

आपके ध्यान के लिए धन्यवाद, मैंने कोड के साथ प्रश्न और परिणाम के स्नैपशॉट को अपडेट किया है। – Andrea3000

3

Andrea3000, नेट पर YIQ उदाहरण की तुलना में, मैं अपनी पोस्टिंग भर में आया है, लेकिन मुझे लगता है कि की 'अद्यतन' संस्करण के साथ कुछ समस्या है आपका कोड .... मुझे यकीन है कि आपकी 'mat3' परिभाषा कॉलम/पंक्ति ऑर्डरिंग पर फ्लिप/फ्लॉप हो गई है ... (शायद यही कारण है कि आपको अभी भी परेशानी हो रही है) ...

FYI: ओपनजीएल मैट्रिक्स ऑर्डरिंग : "अधिक मूल्यों के लिए, कॉलम-प्रमुख क्रम में matrices भर जाते हैं। यही है, पहले एक्स मान पहले कॉलम हैं, दूसरे एक्स मान अगले कॉलम हैं, और बहुत आगे।" देखें: http://www.opengl.org/wiki/GLSL_Types

mat2(
float, float, //first column 
float, float); //second column 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^