影を追加する
シャドウバッファとかの元になってるやつ。流石にCPUの手抜き実装だとらくちんですね…
/* レイと球の交差位置取得。 */ 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 ) { // 交差しているなら解を求める。レイの発射点側だけ求めればよい。 float t = ( - b - sqrtf( D ) ) / a;; if( t > 0 ) { // レイの発射後の位置なら衝突している *out_t = t; return true; } else { // レイの発射前の位置で衝突している return false; } } else { // 交差してないか、接触なら無視。 return false; } } /* 光線追跡 */ uint32_t TraceRay( const Vector3& p, const Vector3& d, const Scene& scene ) { const float epsilon = 0.000001f; // レイと衝突するか判定 Contact contact; if( Test_Ray_Scene( p, d, scene, &contact ) ) { float sum = 0; for( std::vector<Vector3>::const_iterator it = scene.directionalLights.begin(); it != scene.directionalLights.end(); ++it ) { // ディフューズライティング float diffuse = max( 0, MathUtil::Dot( contact.n, -*it ) ); // 光源方向にレイをキャスト Contact contact2; if( Test_Ray_Scene( contact.p + contact.n * epsilon, -*it, scene, &contact2 ) ) { // もし光源方向にオブジェクトがあるなら影になる sum += 0.5f * diffuse; } else { // もし光源方向にオブジェクトがないなら直接ライティング sum += diffuse; } } return FRGBAToARGB32( sum, sum, sum, 1.0f ); } else { return 0x00000080; } }