LoginSignup
12
5

More than 3 years have passed since last update.

波長ベース色空間【光の波長をRGBに変換】

Last updated at Posted at 2019-07-18

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

Wave2RGB.cginc
//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);
}
wave2color.shader
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
        }
    }
}
Rainbow.shader
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

wave2rgb

e1dc2f6d8c60262c9926dcaee8bdeea4.gif

解説

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

サンプル

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

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

12
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
5