2012-03-05 33 views
2

OpenGLは、1つの側から他の側への色の勾配で矩形に色を付けることができます。私はOpenGLのRGBではなくHSVのグラデーション

glBegin(GL_QUADS); 
{ 
    glColor3d(simulationSettings->hotColour.redF(), simulationSettings->hotColour.greenF(), simulationSettings->hotColour.blueF()); 
    glVertex2d(keyPosX - keyWidth/2, keyPosY + keyHight/2); 
    glColor3d(simulationSettings->coldColour.redF(), simulationSettings->coldColour.greenF(), simulationSettings->coldColour.blueF()); 
    glVertex2d(keyPosX - keyWidth/2, keyPosY - keyHight/2); 
    glColor3d(simulationSettings->coldColour.redF(), simulationSettings->coldColour.greenF(), simulationSettings->coldColour.blueF()); 
    glVertex2d(keyPosX + keyWidth/2, keyPosY - keyHight/2); 
    glColor3d(simulationSettings->hotColour.redF(), simulationSettings->hotColour.greenF(), simulationSettings->hotColour.blueF()); 
    glVertex2d(keyPosX + keyWidth/2, keyPosY + keyHight/2); 
} 

私はHSVとRGBの間の変換を行うために、いくつかのQtライブラリを使用しているC++でそのために以下のコードを使用しています。コードからわかるように、私はhotColourとcoldColourという名前のカラーグラデーションを使って四角形を描画しています。

なぜ私はこれをやっていますか?私が作ったプログラムでは、空間内の3Dベクトルを描画し、その長さを色で示します。ユーザーはホット(高値)と低温(低値)の色を選択できるようになり、HSVスケーリングを使用してグラデーションが自動的に実行されます。

なぜHSVスケーリングですか? HSVは私が使用しているカラーマップに沿って単一値であるため、直線的にグラデーションを作成するのは非常に簡単な作業です。色を選択するユーザーのために、私はこのカラーマップでは彼にQColourDialogカラーマップ

http://qt-project.org/doc/qt-4.8/qcolordialog.html

を提供し、あなたはそれが不可能な線形を持つようになって、赤が右と左に利用可能であることがわかりますRGBを使用したこのカラーマップのスケール。しかし、HSVでは、リニアスケールは非常に簡単に達成可能です。ここでは、Hue値に0〜360のリニアスケールを使用するだけです。

このパラダイムでは、暑い色と寒い色が勾配の方向を定義していることがわかります。たとえば、色相を冷気で0、高温で359と選択すると、HSVは0と359であり、勾配内の色の全スペクトルを含む。一方、OpenGLでは、基本的には赤から赤に変わりますが、これはグラデーションではありません!!!!!!

OpenGLに強制的にRGBではなくHSVグラジエントを使用させることができますか?私に起こる唯一のアイデアは、私が色付けしたい矩形をスライスし、小さな矩形に多くの勾配をつけることですが、これを行うには最も効率的な方法ではないと思います。

アイデア?

答えて

7

OpenGLに強制的にRGBではなくHSVグラジエントを使用させることができますか?

私は「強制」ではなく「教える」と言っています。頂点属性ベクトルを補間するためのOpenGLのデフォルトの方法は、フラグメントのNDC座標に基づく単一のベクトル要素の重心補間によるものです。

これらの重心補間されたHSV値をRGBに変換する方法をOpenGLに教えてください。

これについては、カラー頂点属性がRGBではなくHSVであることを前提とするフラグメントシェーダを導入します。

#version 120 
varying vec3 vertex_hsv; /* set this in appropriate vertex shader to the vertex attribute data*/ 

vec3 hsv2rgb(vec3 hsv) 
{ 
    float h = hsv.x * 6.; /* H in 0°=0 ... 1=360° */ 
    float s = hsv.y; 
    float v = hsv.z; 
    float c = v * s; 

    vec2 cx = vec2(v*s, c * (1 - abs(mod(h, 2.)-1.))); 

    vec3 rgb = vec3(0., 0., 0.); 
    if(h < 1.) { 
     rgb.rg = cx; 
    } else if(h < 2.) { 
     rgb.gr = cx; 
    } else if(h < 3.) { 
     rgb.gb = cx; 
    } else if(h < 4.) { 
     rgb.bg = cx; 
    } else if(h < 5.) { 
     rgb.br = cx; 
    } else { 
     rgb.rb = cx; 
    } 
    return rgb + vec3(v-cx.y); 
} 

void main() 
{ 
    gl_FragColor = hsv2rgb(vertex_hsv); 
} 
+0

「6」は、最初の計算では「float h = hsv.x * 6.;」となりますが、それはどういう意味ですか? – tobsen

+0

また、vec2 cx = vec2(v * s、c *(1 - abs(mod(h、2))));); ')の行に定義されている" c " – tobsen

+0

@tobsen: 'c'編集で代用するのを忘れました。ファクタ6について:HSLの色相は角度として与えられ、上のコードは、0°〜360°または0°のHに対応する0 ... 1の値域hのカラーサイクルの完全な回転を仮定しています〜2pi。したがって、カラーサイクルで6つのセクタがあり、h値の範囲を6倍に拡大し、2を法とする(cx計算で)と、一連のif文がH円の原色間の補間を行います怒り – datenwolf

3

フラグメントシェーダでこれを行うことができます。あなたはクワッドを描いて、あなたが望むカラーリングをクワッドに適用するフラグメントシェイダーを適用します。これを行う方法は、コーナーの色を必要なHSV値に設定し、フラグメントシェーダーで補間されたカラー値をHSVからRGBに変換し直すことです。フラグメントシェーダの詳細については、docsを参照してください。

関連する問題