ArtColors は、次のように、2 つの RGB 入力と混合比率のみを使用して、最小限のコードで現実的な方法で 2 つの色を減算的に混合する単純な関数呼び出しを提供する必要があります。
Return Color=SubtractiveMix(Color a, Color b, percentage)
ArtColors は、(私が思うに) 他の方法のコードのほんの一部でかなり良い結果をもたらすアルゴリズムを使用し、反射率データや複雑な計算式を計算または保存する必要はありません。目標は、コードの 20% のみで 80% のリアリズムを実現することです。
基本的なアプローチは、塗料が実際にどのように混ざるかを考えることから着想を得ました。絵の具の混合のクローズアップを調べます。

注意深く見ると、一部の領域で 2 つの絵の具が完全に混ざり合っており、その結果が減法であることがわかります。黄色と青が、はるかに濃い緑を作っています。赤と青がとても濃い紫を作っています。しかし、ブレンドがそれほど完全ではない他の領域では、黄色と青の細い線が並んで存在します. これらの塗料は黄色と青色の光を反射しています。離れたところから見ると、はっきりとした渦巻きが小さすぎて見えない場合 、これらの色は目によって加算的にブレンドされます。
さらに、塗料の混合は化学的な意味での混合であると考えてください。化学変化は起こりません。赤と青の分子はまだ完全なブレンドの中にあり、分離していたときとまったく同じように、赤と青の光を反射します。光が媒質内で跳ね返るため、多くの地下物理的効果が起こっています。入射光はある分子に吸収されて反射され、次に別の分子に反射され、最終的にその結果が目に反射します。
これはどのように私たちの問題を解決するのに役立ちますか?
厳密な減算アプローチは、白から開始し、次に白からカラー A とカラー B の RGB 値を減算し、残ったものを返します。 多くの場合、このアプローチは暗すぎます。 なんで?各顔料の一部は、まだ小さなスケールでその独特の色を反映しています. 部分的に加算的で部分的に減算的なアプローチを取ると、より現実的な結果が得られます!
さらに、色 A = 色 B の場合、関数は同じ色を返す必要があります。同じ色と同じ色を混ぜると、同じ色になるはずです!厳密な減算アルゴリズムを使用すると、結果は元の色相のより暗いバージョンになります (入力カラー値が White から2 回減算されるため)。2 つの入力カラーが近いほど、ブレンドで見られる変化は少なくなります。
減法混色の ArtColor コードは次のとおりです。
Color ColorMixSub(Color a, Color b, float blend) {
Color out;
Color c,d,f;
c=ColorInv(a);
d=ColorInv(b);
f.r=max(0,255-c.r-d.r);
f.g=max(0,255-c.g-d.g);
f.b=max(0,255-c.b-d.b);
float cd=ColorDistance(a,b);
cd=4.0*blend*(1.0-blend)*cd;
out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);
out.a=255;
return out;
}
コードの説明:
Color a
とColor b
は入力色です。 blend
線形補間 (LERP) のように、ブレンドする各色の量を 0 から 1.0 で指定します。0.0 = すべてのカラー A、1.0 = すべてのカラー B。0.5 = A と B の 50%-50% の混合。
まず、色 a と b の RGB 反転を見つけ、それらを新しい色 c と d に割り当てます。
c=ColorInv(a);
d=ColorInv(b);
次に、純粋な RGB ホワイトから c と d の両方を減算し、結果をゼロにクランプして、結果を色 f に割り当てます。
f.r=max(0,255-c.r-d.r);
f.g=max(0,255-c.g-d.g);
f.b=max(0,255-c.b-d.b);
これまでのところ、f は純粋に減算的な結果であり、上記の問題に悩まされています。
次に、色 a と色 b の間の「色距離」を計算します。これは、RGB 空間でのそれらの間のベクトル距離であり、0.0 (同じ色) と 1.0 (白と黒のように完全に反対) の間で正規化されています。
float cd=ColorDistance(a,b);
この値は、2 つの類似した色相を混合しても結果があまり変わらないという問題を解決するのに役立ちます。次に、色距離係数cd
は、二次伝達関数によって変換されます。これにより、減法混合と加法混合の量が調整されます。
cd=4.0*blend*(1.0-blend)*cd;

エンドポイントにより、0% または 100% に近いブレンド パーセンテージが元の入力色に非常に近くなります。二次曲線は、次に来るミックスに適した色域を提供します。曲線のピークは、色の距離によって決まります。この関数の出力は、結果における加法的ブレンディングと減法的ブレンディングの量を決定します。より離れた色は、より減法的なダイナミクス (y=1.0 で完全に減法化) とブレンドされます。同様の色は、減法要素を持つより加法的なダイナミクス (より平坦な曲線) とブレンドされます。二次伝達関数の最大値は正規化された色距離であるため、色空間で正反対の色が完全に減算的にブレンドされます。
最後の行はすべての作業を行います:
out=ColorMixLin(ColorMixLin(a,b,blend),f,cd);`
まず、指定された比率で色 A と色 Bを加算的に混合します。これは によって達成されます。これは、上の画像の色の細かい渦巻きと表面下の相互作用の加算ブレンド効果を表しています。この要因がない場合、厳密に減法的なアプローチでは奇妙な結果が生じる可能性があります。この加算結果は、との間の色距離に基づく上記の伝達関数に従って、純粋な減算結果 とブレンドされます。blend
ColorMixLin(a,b,blend)
color f
Color a
Color b
出来上がり!広範囲の入力色でかなり良い結果が得られます。