帆立の貝殻

HOTATE's VIRTUALAB

View project on GitHub

659afc172f18b7f95b8b82d68341a168.png

概要

 色の表現方法にはRGBやHSVなどがあり、これらは人間が色を認識するL・M・S錐体がそれぞれ赤・緑・青に反応することに基づいて色を表現しています。  たしかにRGBやHSVは人間の目に映るあらゆる色を表現できるのですが、この空間で色を変化させても不規則に明るさが変化したりしてそんなにきれいには見えないと思います。  そこで今回は光の波長をRGBに変換する関数を紹介します。これを使ってきれいな虹色を表現してください! 92e6dbfe950f8c631cbfb4519fed6132.png

コード

波長とRGBの対応表はCIE1931色空間(http://cvrl.ucl.ac.uk/cmfs.htm) に基づいています。 このコードはShaderLabですが書き換えればGLSLでもHLSLでも使えるはず。。。

HLSL

//data on http://cvrl.ucl.ac.uk/cmfs.htm
static float MinVal = 390.0;
static int DataNum = 89;
static float Interval = 5.0;
static fixed4 CMF[89]={ //fixed4(wavelength,R,G,B)元のデータの構造由来
    fixed4(390,1.5000E-03,-4.0000E-04,6.2000E-03),
    fixed4(395,3.8000E-03,-1.0000E-03,1.6100E-02),
    fixed4(400,8.9000E-03,-2.5000E-03,4.0000E-02),
    fixed4(405,1.8800E-02,-5.9000E-03,9.0600E-02),
    fixed4(410,3.5000E-02,-1.1900E-02,1.8020E-01),
    fixed4(415,5.3100E-02,-2.0100E-02,3.0880E-01),
    fixed4(420,7.0200E-02,-2.8900E-02,4.6700E-01),
    fixed4(425,7.6300E-02,-3.3800E-02,6.1520E-01),
    fixed4(430,7.4500E-02,-3.4900E-02,7.6380E-01),
    fixed4(435,5.6100E-02,-2.7600E-02,8.7780E-01),
    fixed4(440,3.2300E-02,-1.6900E-02,9.7550E-01),
    fixed4(445,-4.4000E-03,2.4000E-03,1.0019E+00),
    fixed4(450,-4.7800E-02,2.8300E-02,9.9960E-01),
    fixed4(455,-9.7000E-02,6.3600E-02,9.1390E-01),
    fixed4(460,-1.5860E-01,1.0820E-01,8.2970E-01),
    fixed4(465,-2.2350E-01,1.6170E-01,7.4170E-01),
    fixed4(470,-2.8480E-01,2.2010E-01,6.1340E-01),
    fixed4(475,-3.3460E-01,2.7960E-01,4.7200E-01),
    fixed4(480,-3.7760E-01,3.4280E-01,3.4950E-01),
    fixed4(485,-4.1360E-01,4.0860E-01,2.5640E-01),
    fixed4(490,-4.3170E-01,4.7160E-01,1.8190E-01),
    fixed4(495,-4.4520E-01,5.4910E-01,1.3070E-01),
    fixed4(500,-4.3500E-01,6.2600E-01,9.1000E-02),
    fixed4(505,-4.1400E-01,7.0970E-01,5.8000E-02),
    fixed4(510,-3.6730E-01,7.9350E-01,3.5700E-02),
    fixed4(515,-2.8450E-01,8.7150E-01,2.0000E-02),
    fixed4(520,-1.8550E-01,9.4770E-01,9.5000E-03),
    fixed4(525,-4.3500E-02,9.9450E-01,7.0000E-04),
    fixed4(530,1.2700E-01,1.0203E+00,-4.3000E-03),
    fixed4(535,3.1290E-01,1.0375E+00,-6.4000E-03),
    fixed4(540,5.3620E-01,1.0517E+00,-8.2000E-03),
    fixed4(545,7.7220E-01,1.0390E+00,-9.4000E-03),
    fixed4(550,1.0059E+00,1.0029E+00,-9.7000E-03),
    fixed4(555,1.2710E+00,9.6980E-01,-9.7000E-03),
    fixed4(560,1.5574E+00,9.1620E-01,-9.3000E-03),
    fixed4(565,1.8465E+00,8.5710E-01,-8.7000E-03),
    fixed4(570,2.1511E+00,7.8230E-01,-8.0000E-03),
    fixed4(575,2.4250E+00,6.9530E-01,-7.3000E-03),
    fixed4(580,2.6574E+00,5.9660E-01,-6.3000E-03),
    fixed4(585,2.9151E+00,5.0630E-01,-5.3700E-03),
    fixed4(590,3.0779E+00,4.2030E-01,-4.4500E-03),
    fixed4(595,3.1613E+00,3.3600E-01,-3.5700E-03),
    fixed4(600,3.1673E+00,2.5910E-01,-2.7700E-03),
    fixed4(605,3.1048E+00,1.9170E-01,-2.0800E-03),
    fixed4(610,2.9462E+00,1.3670E-01,-1.5000E-03),
    fixed4(615,2.7194E+00,9.3800E-02,-1.0300E-03),
    fixed4(620,2.4526E+00,6.1100E-02,-6.8000E-04),
    fixed4(625,2.1700E+00,3.7100E-02,-4.4200E-04),
    fixed4(630,1.8358E+00,2.1500E-02,-2.7200E-04),
    fixed4(635,1.5179E+00,1.1200E-02,-1.4100E-04),
    fixed4(640,1.2428E+00,4.4000E-03,-5.4900E-05),
    fixed4(645,1.0070E+00,7.8000E-05,-2.2000E-06),
    fixed4(650,7.8270E-01,-1.3680E-03,2.3700E-05),
    fixed4(655,5.9340E-01,-1.9880E-03,2.8600E-05),
    fixed4(660,4.4420E-01,-2.1680E-03,2.6100E-05),
    fixed4(665,3.2830E-01,-2.0060E-03,2.2500E-05),
    fixed4(670,2.3940E-01,-1.6420E-03,1.8200E-05),
    fixed4(675,1.7220E-01,-1.2720E-03,1.3900E-05),
    fixed4(680,1.2210E-01,-9.4700E-04,1.0300E-05),
    fixed4(685,8.5300E-02,-6.8300E-04,7.3800E-06),
    fixed4(690,5.8600E-02,-4.7800E-04,5.2200E-06),
    fixed4(695,4.0800E-02,-3.3700E-04,3.6700E-06),
    fixed4(700,2.8400E-02,-2.3500E-04,2.5600E-06),
    fixed4(705,1.9700E-02,-1.6300E-04,1.7600E-06),
    fixed4(710,1.3500E-02,-1.1100E-04,1.2000E-06),
    fixed4(715,9.2400E-03,-7.4800E-05,8.1700E-07),
    fixed4(720,6.3800E-03,-5.0800E-05,5.5500E-07),
    fixed4(725,4.4100E-03,-3.4400E-05,3.7500E-07),
    fixed4(730,3.0700E-03,-2.3400E-05,2.5400E-07),
    fixed4(735,2.1400E-03,-1.5900E-05,1.7100E-07),
    fixed4(740,1.4900E-03,-1.0700E-05,1.1600E-07),
    fixed4(745,1.0500E-03,-7.2300E-06,7.8500E-08),
    fixed4(750,7.3900E-04,-4.8700E-06,5.3100E-08),
    fixed4(755,5.2300E-04,-3.2900E-06,3.6000E-08),
    fixed4(760,3.7200E-04,-2.2200E-06,2.4400E-08),
    fixed4(765,2.6500E-04,-1.5000E-06,1.6500E-08),
    fixed4(770,1.9000E-04,-1.0200E-06,1.1200E-08),
    fixed4(775,1.3600E-04,-6.8800E-07,7.5300E-09),
    fixed4(780,9.8400E-05,-4.6500E-07,5.0700E-09),
    fixed4(785,7.1300E-05,-3.1200E-07,3.4000E-09),
    fixed4(790,5.1800E-05,-2.0800E-07,2.2700E-09),
    fixed4(795,3.7700E-05,-1.3700E-07,1.5000E-09),
    fixed4(800,2.7600E-05,-8.8000E-08,9.8600E-10),
    fixed4(805,2.0300E-05,-5.5300E-08,6.3900E-10),
    fixed4(810,1.4900E-05,-3.3600E-08,4.0700E-10),
    fixed4(815,1.1000E-05,-1.9600E-08,2.5300E-10),
    fixed4(820,8.1800E-06,-1.0900E-08,1.5200E-10),
    fixed4(825,6.0900E-06,-5.7000E-09,8.6400E-11),
    fixed4(830,4.5500E-06,-2.7700E-09,4.4200E-11),
};

fixed4 Wave2RGB(float wavelength){ //波長→RGB
    wavelength = clamp( wavelength, MinVal, MinVal+Interval*DataNum);
    int index = clamp( (int)(wavelength-MinVal)/Interval, 0, DataNum);
    float weight = saturate((wavelength - MinVal - index * Interval)/(Interval));
    fixed4 output = lerp(CMF[index],CMF[index+1],weight);
    return fixed4(output.yzw,1.0);
}

fixed4 Val2RGB(float val){ //01→RGB
    return Wave2RGB(val*300+390);
}
Shader "HOTATE/Wave2Color" {
    Properties {
        _Wave ("wave(nm)",range(390,830)) = 500
    }
    SubShader {
        Tags { "Queue" = "Geometry" "RenderType" = "Opaque"}

        Pass {
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                #include "wave2rgb.cginc"

                float _Wave;

                struct appdata {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD;
                };

                struct v2f {
                    float4 vertex : SV_POSITION;
                    float2 uv : TEXCOORD;
                };

                v2f vert (appdata IN) {
                    v2f output;
                    output.vertex = UnityObjectToClipPos(IN.vertex);
                    output.uv = IN.uv;
                    return output;
                }

                fixed4 frag(v2f IN) : SV_Target {
                    return Wave2RGB(_Wave);
                    //return Val2RGB(IN.uv.x);
                }
            ENDCG
        }
    }
}
Shader "HOTATE/Rainbow" {
    Properties {
        _Ypow ("Y曲げ具合",range(0.0,5000.0)) = 1000.0
        _Xpow ("X曲げ具合",range(0.0,5000.0)) = 100.0
        _Height ("高さ",range(-5000,5000)) = 0.0
        _Brightnes ("明るさ",range(0,30)) = 1.0
    }
    SubShader {
        Tags { "Queue" = "Transparent"}
        Blend One One

        Pass {
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                #include "wave2rgb.cginc"

                float _Ypow, _Xpow, _Height, _Brightnes;

                struct appdata {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD;
                };

                struct v2f {
                    float4 vertex : SV_POSITION;
                    float2 uv : TEXCOORD;
                };

                v2f vert (appdata IN) {
                    v2f output;
                    output.vertex = UnityObjectToClipPos(IN.vertex);
                    output.uv = IN.uv;
                    return output;
                }

                fixed4 frag(v2f IN) : SV_Target {
                    return Wave2RGB(IN.uv.y*_Ypow + (IN.uv.x-0.5)*(IN.uv.x-0.5)*_Xpow + _Height) * _Brightnes;
                }
            ENDCG
        }
    }
}

GLSL

e1dc2f6d8c60262c9926dcaee8bdeea4.gif

解説

 多段階線形補完みたいな方法使っているので、これは他にも応用できそう・・・  波長方式だと単純にはループさせられないので、ここはひと工夫必要かと思います。

サンプル

虹サンプルのgithubリポジトリ

https://github.com/HhotateA/RainbowColor_Shaderlab 35dfee577643676b7d3d25c32807308e.png