レイマーチングでソフトシャドウ

452023224091040c47c3bcaa40935c53?s=47 がむ
April 06, 2016

 レイマーチングでソフトシャドウ

先日の社内のシェーダ勉強会#2で「レイマーチングでソフトシャドウ」を実装する手法について発表しました。その資料を共有します。

後半ではソフトシャドウの現実らしい半影の特徴などにも触れています。半影については、3DCGに関する前提知識なしに直感的に理解できる内容だと思います。

半影の特徴は、現実世界の光の振る舞いにより生じるため、レイマーチングに限った話ではありません。レイマーチングに興味が無い方でも、3DCGに少しでもご興味があれば、目を通していただければ幸いです。

ソフトシャドウは、3DCGの基礎的なテーマですが、実際にはとても奥が深いと思います。

452023224091040c47c3bcaa40935c53?s=128

がむ

April 06, 2016
Tweet

Transcript

  1. 12.

    ϨΠϚʔνϯάͰϋʔυγϟυ΢ 12 float shadow = getShadow( p + nearest.normal *

    OFFSET, lightDir ); vec3 color = vec3( 0.9 ) * diffuse * shadow; HFU4IBEPX ͸EJ⒎VTFʹ৐ࢉͯ͠࢖͏  Ͱ׬શʹਅͬࠇͳӨ  ͸Ө͕ແ͍ চͷγΣʔσΟϯάॲཧ
  2. 13.

    ϨΠϚʔνϯάͰϋʔυγϟυ΢ িಥ͢ΔͳΒɺ͠ͳ͍ͳΒΛฦ͢ 13 float getShadow( vec3 ro, vec3 rd )

    { float dist; float depth = EPS; for ( int i = 0; i < 30; i++ ) { dist = sceneDist( ro + rd * depth ); if ( dist < EPS ) return 0.5; depth += dist; } return 1.0; }
  3. 22.

    ιϑτγϟυ΢ 22 float shadowIntensity = 0.7; float shadowSharpness = 6.0;

    float getSoft1Shadow( vec3 ro, vec3 rd ) { float dist, depth = EPS; float bright = 1.0; for ( int i = 0; i < 30; i++ ) { dist = sceneDist( ro + rd * depth ); if ( dist < EPS ) return 1.0 - shadowIntensity; bright = min( bright, shadowSharpness * dist ); depth += dist; } return 1.0 - ( 1.0 - bright ) * shadowIntensity; }
  4. 29.

    ιϑτγϟυ΢վ 29 float shadowIntensity = 0.7; float shadowSharpness = 6.0;

    float getSoft2Shadow( vec3 ro, vec3 rd ) { float dist, depth = EPS; float bright = 1.0; for ( int i = 0; i < 30; i++ ) { dist = sceneDist( ro + rd * depth ); if ( dist < EPS ) return 1.0 - shadowIntensity; bright = min( bright, shadowSharpness * dist / depth ); depth += dist; } return 1.0 - ( 1.0 - bright ) * shadowIntensity; }
  5. 30.

    iqͷιϑτγϟυ΢࣮૷ IUUQTXXXTIBEFSUPZDPNWJFX9ET[/ 30 float softshadow( in vec3 ro, in vec3

    rd, in float mint, in float tmax ) { ɹfloat res = 1.0; float t = mint; for( int i=0; i<16; i++ ) { ɹɹfloat h = map( ro + rd*t ).x; res = min( res, 8.0*h/t ); t += clamp( h, 0.02, 0.10 ); if( h<0.001 || t>tmax ) break; } return clamp( res, 0.0, 1.0 ); }
  6. 31.

    doxasͷιϑτγϟυ΢࣮૷ IUUQTXHMEPSHEHMTMHIUNM 31 float genShadow(vec3 ro, vec3 rd){ float h

    = 0.0; float c = 0.0; float r = 1.0; float shadowCoef = 0.5; for(float t = 0.0; t < 50.0; t++){ h = distFunc(ro + rd * c); if(h < 0.001){ return shadowCoef; } r = min(r, h * 16.0 / c); c += h; } return 1.0 - shadowCoef + r * shadowCoef; }