ディフューズシェーディング
そして何の変哲も無いディフューズシェーディング。
/* レイと球の交差位置取得。 */ bool Test_Ray_Sphere( const Vector3& p0, const Vector3& v, const Sphere& s, float* out_t ) { Vector3 m = p0 - s.p; // tについての二次方程式(at^2 + 2bt + c = 0) float a = MathUtil::Dot( v, v ); float b = MathUtil::Dot( v, m ); float c = MathUtil::Dot( m, m ) - s.r * s.r; // 判別式を求める float D = b*b - a*c; if( D > 0 ) { // 交差しているなら解を求める。レイの発射点側だけ求めればよい。 *out_t = ( - b - sqrtf( D ) ) / a; return true; } else { // 交差してないか、接触なら無視。 return false; } } /* RGBA値をUInt32に変換します。 */ uint32_t FRGBAToARGB32( float r, float g, float b, float a ) { uint32_t ir = (uint32_t) min( 255.0f, max( 0.0f, r * 255.0f + 0.5f ) ); uint32_t ig = (uint32_t) min( 255.0f, max( 0.0f, g * 255.0f + 0.5f ) ); uint32_t ib = (uint32_t) min( 255.0f, max( 0.0f, b * 255.0f + 0.5f ) ); uint32_t ia = (uint32_t) min( 255.0f, max( 0.0f, a * 255.0f + 0.5f ) ); return (ia<<24) | (ir<<16) | (ig<<8) | ib; } /* 光線追跡 */ uint32_t TraceRay( const Vector3& p, const Vector3& d ) { // 球 Sphere s( Vector3( 0, 0, 1 ), 1.0f ); // 平行光源の定義 Vector3 lightDirection = MathUtil::Normal( Vector3( -1, -1, 1 ) ); // レイと衝突するか判定 float t; if( Test_Ray_Sphere( p, d, s, &t ) ) { Vector3 q = p + d * t; // 衝突位置 Vector3 n = MathUtil::Normal( q - s.p ); // 衝突位置の法線 float diffuse = max( 0, MathUtil::Dot( n, -lightDirection ) ); // ディフューズライティング return FRGBAToARGB32( diffuse, diffuse, diffuse, 1.0f ); } else { return 0x00000080; } }