0001: #include "stdafx.h"
0002: #include "common\my_include.h"
0003: #include "prim.h"
0004: #include "render.h"
0005: 
0006: //void ToneMapping( CColor *pDest, CColor *pSrc, u32 nPixels );
0007: 
0008: namespace Render {
0009: 
0010: D3DXVECTOR3 BG_COLOR = D3DXVECTOR3(0.25f, 0.4f, 0.5f);
0011: 
0012: extern OBJ_DATA sphere_data[];
0013: extern OBJ_DATA room_data[];
0014: extern OBJ_DATA Short_block[];
0015: extern OBJ_DATA Tall_block[];
0016: 
0017: OBJ_DATA *pLightPolygone[2];
0018: 
0019: typedef struct
0020: {
0021:     OBJ_DATA    *pObjData; // 頂点データ
0022:     D3DXVECTOR3  normal;   // 法線
0023:     float        area;     // 面積
0024: }LIGHT_DATA;
0025: 
0026: class CCamera
0027: {
0028: private:
0029:     D3DXVECTOR3 m_vFrom;
0030:     D3DXVECTOR3 m_vLookat;
0031:     D3DXVECTOR3 m_vUp;
0032: 
0033:     float   m_fFilmSize[2];  // フィルムの実寸0.036*0.024[m*m]0.025*0.025(Cornell Box)
0034:     float   m_fFocalLength;  // 焦点距離 0.035(Cornell Box )
0035:     float   m_fFNumber;      // F値
0036:     float   m_fFocusDistance;// ピントが合う位置までの距離
0037: 
0038:     float   m_fLensRadius;   // レンズの半径(f/2F)
0039:     float   m_fFilmDistance; // フィルムまでの距離 Lf/(L-f)
0040: 
0041:     D3DXVECTOR3 u, v, w;
0042: 
0043: public:
0044: 
0045:     void Update();
0046:     void SetFrom  (const D3DXVECTOR3 *p){m_vFrom  =*p;}
0047:     void SetLookAt(const D3DXVECTOR3 *p){m_vLookat=*p;}
0048:     void SetUp    (const D3DXVECTOR3 *p){m_vUp    =*p;}
0049:     void SetFilmSize      (float w, float h){m_fFilmSize[0] = w; m_fFilmSize[1] = h;}
0050:     void SetFocalLength   (float v){m_fFocalLength   = v;}
0051:     void SetFNumber       (float v){m_fFNumber       = v;}
0052:     void SetFocusDistance (float v){m_fFocusDistance = v;}
0053:     
0054:     void GetRay( D3DXVECTOR3 *o, D3DXVECTOR3 *v, float x, float y);
0055: };
0056: 
0057: // ---------------------------------------------------------------------------
0058: // オブジェクト
0059: // ---------------------------------------------------------------------------
0060: char   s_data [4*RENDER_WIDTH*RENDER_HEIGHT];// 仮想フレームバッファ
0061: float  s_total[4*RENDER_WIDTH*RENDER_HEIGHT];// 累積フレームバッファ
0062: CColor s_tmp  [  RENDER_WIDTH*RENDER_HEIGHT];// 一時フレームバッファ
0063: 
0064: CCamera camera;
0065: 
0066: CRand   *g_pRand = NULL;
0067: #define frand() ((float)g_pRand->GetF32())
0068: 
0069: CMesh *pRoom       = NULL;
0070: CMesh *pBlockSmall = NULL;
0071: CMesh *pBlockTall  = NULL;
0072: CMesh *pShpereS    = NULL;
0073: CMesh *pShpereT    = NULL;
0074: #define LIGHT_DATA_MAX 2
0075: LIGHT_DATA g_LightData[LIGHT_DATA_MAX];
0076: float      g_fTotalArea;
0077: 
0078: static int s_x = 0;         // レンダリングピクセルのx座標
0079: static int s_y = 0;         // レンダリングピクセルのy座標
0080: static float render_cnt = 0;// 描画回数
0081: enum{
0082:     STATE_IDLE=0,           // 処理待ち
0083:     STATE_RENDER_BEGIN,     // 初期化
0084:     STATE_RENDER,           // 描画
0085:     STATE_RENDER_END,       // 後片付け
0086: };
0087: 
0088: // ---------------------------------------------------------------------------
0089: // 関数宣言
0090: // ---------------------------------------------------------------------------
0091: D3DXVECTOR3 *GetColor(D3DXVECTOR3 *dest, float x, float y);
0092: 
0093: // ---------------------------------------------------------------------------
0094: // 光源管理
0095: // ---------------------------------------------------------------------------
0096: // 光源の1点を選択する
0097: LIGHT_DATA *choiceEmmisivePoint( D3DXVECTOR4 *pos, D3DXVECTOR3 *dir )
0098: {
0099:     LIGHT_DATA *pData;
0100:     float a = g_fTotalArea * g_pRand->GetF32();
0101: 
0102:     pData = &g_LightData[0];
0103:     for( int i = 0; i < LIGHT_DATA_MAX; i++ )
0104:     {
0105:         if( a < pData->area )
0106:         {
0107:             // 3角形の内部の1点を選択する
0108:             float s = g_pRand->GetF32();
0109:             float t = g_pRand->GetF32();
0110:             if(1 < s + t) {s=1-s;t=1-t;}
0111: 
0112:             float *x0 = pData->pObjData->triangle.x0;
0113:             float *x1 = pData->pObjData->triangle.x1;
0114:             float *x2 = pData->pObjData->triangle.x2;
0115:             pos->x = (1.0f-s-t)*x0[0] + s * x1[0] + t * x2[0];
0116:             pos->y = (1.0f-s-t)*x0[1] + s * x1[1] + t * x2[1];
0117:             pos->z = (1.0f-s-t)*x0[2] + s * x1[2] + t * x2[2];
0118:             pos->w = 1.0f;
0119: 
0120:             *dir = pData->normal;
0121:             return pData;
0122:         }
0123:         a -= pData->area;
0124:         pData++;
0125:     }
0126:     return NULL;
0127: }
0128: 
0129: // ---------------------------------------------------------------------------
0130: // カメラクラス
0131: // ---------------------------------------------------------------------------
0132: void CCamera::Update()
0133: {
0134:     // 正規直行基底の計算
0135:     D3DXVec3Subtract( &w, &m_vLookat, &m_vFrom );
0136:     D3DXVec3Cross( &v, &w, &m_vUp );
0137:     D3DXVec3Cross( &u, &v, &w );
0138:     D3DXVec3Normalize( &u, &u );
0139:     D3DXVec3Normalize( &v, &v );
0140:     D3DXVec3Normalize( &w, &w );
0141: 
0142:     // レンズの半径(f/2F)
0143:     m_fLensRadius = 0.5f * m_fFocalLength / m_fFNumber;
0144:     // フィルムまでの距離 Lf/(L-f)
0145:     m_fFilmDistance = m_fFocusDistance*m_fFocalLength/(m_fFocusDistance-m_fFocalLength);
0146: }
0147: // ---------------------------------------------------------------------------
0148: void CCamera::GetRay( D3DXVECTOR3 *o, D3DXVECTOR3 *dir, float x, float y)
0149: {
0150:     D3DXVECTOR3 ds, e;
0151:     D3DXVECTOR3 tmp, tmp1;
0152:     float z1 = frand();
0153:     float z2 = frand();
0154: 
0155:     float r = m_fLensRadius * sqrtf(z1);
0156:     float theta = 2.0f * D3DX_PI * z2;
0157:     
0158:     // レイを飛ばす位置
0159:     D3DXVec3Scale( &tmp, &v, cosf(theta) );
0160:     D3DXVec3Scale( &ds,  &u, cosf(theta) );
0161:     D3DXVec3Add( &ds, &ds, &tmp );
0162:     D3DXVec3Scale( &ds, &ds, r );
0163:     D3DXVec3Add( o, &ds, &m_vFrom );
0164: 
0165:     // レンズの中心からピントの当たる位置へのベクトル
0166:     D3DXVec3Scale( &e,    &w,   m_fFilmDistance );
0167:     D3DXVec3Scale( &tmp,  &v,   m_fFilmSize[0] * (x-0.5f) );
0168:     D3DXVec3Scale( &tmp1, &u, - m_fFilmSize[1] * (y-0.5f) );
0169:     D3DXVec3Add( &e, &e, &tmp );
0170:     D3DXVec3Add( &e, &e, &tmp1 );
0171:     D3DXVec3Normalize( &e, &e );
0172: 
0173:     D3DXVec3Scale( dir, &e, m_fFocusDistance / D3DXVec3Dot( &e, &w ) );
0174:     D3DXVec3Subtract( dir, dir, &ds );
0175:     D3DXVec3Normalize( dir, dir );
0176: }
0177: 
0178: 
0179: // ---------------------------------------------------------------------------
0180: // スレッド処理
0181: // ---------------------------------------------------------------------------
0182: 
0183: MySystem::CThreadMgr *g_pThreadMgr = NULL;
0184: 
0185: unsigned int WINAPI workthread ( LPVOID pParam )
0186: {
0187:     MySystem::CThreadMgr  *pSender = (MySystem::CThreadMgr *)pParam;
0188:     MySystem::CThreadData *ptr;
0189:     
0190:     while( pSender->IsEnable() )
0191:     {
0192:         while( NULL != (ptr = pSender->GetWork()) )
0193:         {
0194:             // --- ここからスレッドデータごとの処理
0195: 
0196:             rect *pRect = (rect *)ptr->GetData();
0197: 
0198:             for( s32 y = pRect->top; y < pRect->bottom; y++ )
0199:             {
0200:                 for( s32 x = pRect->left; x < pRect->right; x++ )
0201:                 {
0202:                     D3DXVECTOR3 col;
0203: 
0204:                     GetColor(&col, ((float)x+0.5f)/(float)RENDER_WIDTH
0205:                                  , ((float)y+0.5f)/(float)RENDER_HEIGHT);
0206:                     int no = 4*(y*RENDER_WIDTH+x);
0207:                     s_total[no+0]+=col.x;// R
0208:                     s_total[no+1]+=col.y;// G
0209:                     s_total[no+2]+=col.z;// B
0210:                 }
0211:             }
0212: 
0213:             // --- ここまでスレッドデータごとの処理
0214: 
0215:             // 終わったら、そのスレッドデータを殺す
0216:             ptr->Finish( );
0217:         }
0218:         Sleep(10);
0219:     }
0220: 
0221:     return 0;
0222: }
0223: 
0224: 
0225: // ---------------------------------------------------------------------------
0226: char *GetDataPointer()
0227: {
0228:     return s_data;
0229: }
0230: // ---------------------------------------------------------------------------
0231: int GetRenderCount()
0232: {
0233:     return (int)(render_cnt+0.5f);
0234: }
0235: // ---------------------------------------------------------------------------
0236: void Init()
0237: {
0238:     int i, j;
0239: 
0240:     camera.SetFrom  (&D3DXVECTOR3(278,273,-800));
0241:     camera.SetLookAt(&D3DXVECTOR3(278,273,0));
0242:     camera.SetUp    (&D3DXVECTOR3(0,1,0));
0243:     camera.SetFilmSize      ( ASPECT*25, 25 );
0244:     camera.SetFocalLength   ( 35 );
0245:     camera.SetFNumber       ( 0.3f  );
0246:     camera.SetFocusDistance ( 1100.0 );
0247:     camera.Update();
0248:     
0249:     g_pRand = new CRand();
0250: 
0251:     pRoom = new CMesh();
0252:     pRoom->Init( room_data, 14 );
0253:     
0254:     pBlockSmall = new CMesh();
0255:     pBlockSmall->Init( Short_block, 10);
0256: 
0257:     pBlockTall = new CMesh();
0258:     pBlockTall->Init( Tall_block, 10);
0259:     
0260:     pShpereS = new CMesh();
0261:     pShpereS->Init( sphere_data, 1);
0262:     
0263:     pShpereT = new CMesh();
0264:     pShpereT->Init( sphere_data+1,1);
0265: 
0266:     // ライト情報
0267:     g_LightData[0].pObjData = &room_data[0];
0268:     g_LightData[1].pObjData = &room_data[1];
0269:     g_fTotalArea = 0.0f;
0270:     for( i = 0; i < LIGHT_DATA_MAX; i++ )
0271:     {
0272:         float *x0, *x1, *x2;
0273:         g_LightData[i].normal   = D3DXVECTOR3(0,-1,0);// 下向きライト限定
0274:         x0 = g_LightData[i].pObjData->triangle.x0;
0275:         x1 = g_LightData[i].pObjData->triangle.x1;
0276:         x2 = g_LightData[i].pObjData->triangle.x2;
0277:         g_LightData[i].area = 0.5f * fabs((x1[0]-x0[0])*(x2[2]-x0[2])-(x2[0]-x0[0])*(x1[2]-x0[2]));
0278:         g_fTotalArea += g_LightData[i].area;
0279:     }
0280: 
0281:     // フレームバッファの初期化
0282:     render_cnt = 0; // レンダリング回数
0283:     for(j=0; j<RENDER_HEIGHT; j++){
0284:     for(i=0; i<RENDER_WIDTH ; i++){
0285:         s_data [4*(j*RENDER_WIDTH+i)+0]=(char)255;// R
0286:         s_data [4*(j*RENDER_WIDTH+i)+1]=(char)(i*256/RENDER_WIDTH );// G
0287:         s_data [4*(j*RENDER_WIDTH+i)+2]=(char)(j*256/RENDER_HEIGHT);// B
0288:         s_total[4*(j*RENDER_WIDTH+i)+0]=0;// R
0289:         s_total[4*(j*RENDER_WIDTH+i)+1]=0;// G
0290:         s_total[4*(j*RENDER_WIDTH+i)+2]=0;// B
0291:     }
0292:     }
0293: 
0294:     // スレッドを動かす
0295:     g_pThreadMgr = new MySystem::CThreadMgr( workthread
0296:                                             , 2  // 最大スレッド数(CPUの数と同じ程度)
0297:                                             , 16 // スレッドに流し込める仕事の数
0298:                                             );
0299: }
0300: 
0301: // ---------------------------------------------------------------------------
0302: void Delete()
0303: {
0304:     // スレッドを終了する
0305:     if(g_pThreadMgr) delete g_pThreadMgr;g_pThreadMgr=NULL;
0306: 
0307:     if(pShpereT){delete pShpereT;pShpereT=NULL;}
0308:     if(pShpereS){delete pShpereS;pShpereS=NULL;}
0309:     if(pBlockTall){delete pBlockTall;pBlockTall=NULL;}
0310:     if(pBlockSmall){delete pBlockSmall;pBlockSmall=NULL;}
0311:     if(pRoom){delete pRoom; pRoom=NULL;}
0312:     if(g_pRand){delete g_pRand; g_pRand=NULL;}
0313: }
0314: // ---------------------------------------------------------------------------
0315: 
0316: #define BLOCK_X 2
0317: #define BLOCK_Y 2
0318: #define RENDERING_COUNT 1
0319: 
0320: 
0321: // ---------------------------------------------------------------------------
0322: int Render()
0323: {
0324:     int k,no;
0325:     static unsigned int save_bit = 0;
0326: 
0327:     render_cnt+=RENDERING_COUNT;
0328: 
0329: #if 0
0330:     for(int i=0;i<RENDERING_COUNT;i++)
0331:     {
0332:         for( s32 y = 0; y < RENDER_HEIGHT; y++ )
0333:         {
0334:             for( s32 x = 0; x < RENDER_WIDTH; x++ )
0335:             {
0336:                 auto D3DXVECTOR3 col;
0337: 
0338:                 GetColor(&col, ((float)x+0.5f)/(float)RENDER_WIDTH
0339:                              , ((float)y+0.5f)/(float)RENDER_HEIGHT);
0340:                 int no = 4*(y*RENDER_WIDTH+x);
0341:                 s_total[no+0]+=col.x;// R
0342:                 s_total[no+1]+=col.y;// G
0343:                 s_total[no+2]+=col.z;// B
0344:             }
0345:         }
0346:     }
0347: #else
0348:     static rect r[BLOCK_Y][BLOCK_X];
0349:     
0350:     for( s32 i = 0; i < BLOCK_Y; i++ )
0351:     {
0352:         for( s32 j = 0; j < BLOCK_X; j++ )
0353:         {
0354:             r[i][j].left   = (j+0)*RENDER_WIDTH /BLOCK_X;
0355:             r[i][j].right  = (j+1)*RENDER_WIDTH /BLOCK_X;
0356:             r[i][j].top    = (i+0)*RENDER_HEIGHT/BLOCK_Y;
0357:             r[i][j].bottom = (i+1)*RENDER_HEIGHT/BLOCK_Y;
0358:         }
0359:     }
0360:     
0361:     // 描画をする
0362:     for( int n = 0; n < RENDERING_COUNT; n++)
0363:     {
0364:         for( s32 i = 0; i < BLOCK_Y; i++ )
0365:         {
0366:             for( s32 j = 0; j < BLOCK_X; j++ )
0367:             {
0368:                 g_pThreadMgr->Req( &r[i][j] );
0369:             }
0370:         }
0371:         while( 0 != g_pThreadMgr->GetLeftWork() )Sleep(10);
0372:     }
0373:     
0374: #endif
0375: 
0376:     
0377:     // トーンマッピング
0378:     no = 0;
0379:     for(s32 j=0; j<RENDER_HEIGHT; j++){
0380:     for(s32 i=0; i<RENDER_WIDTH ; i++){
0381:         s_tmp[no].r = max(0,s_total[4*no+0]/render_cnt);
0382:         s_tmp[no].g = max(0,s_total[4*no+1]/render_cnt);
0383:         s_tmp[no].b = max(0,s_total[4*no+2]/render_cnt);
0384:         no++;
0385:     }
0386:     }
0387: 
0388: //  ToneMapping( s_tmp, s_tmp, RENDER_WIDTH*RENDER_HEIGHT );
0389: 
0390:     // 画面の反映
0391:     no = 0;
0392:     for(s32 j=0; j<RENDER_HEIGHT; j++){
0393:     for(s32 i=0; i<RENDER_WIDTH ; i++){
0394:         auto CColor &c = s_tmp[no>>2];
0395:         s_data [no+0]=(unsigned char)(255.9*max(0,min(1,c.r)));// R
0396:         s_data [no+1]=(unsigned char)(255.9*max(0,min(1,c.g)));// G
0397:         s_data [no+2]=(unsigned char)(255.9*max(0,min(1,c.b)));// B
0398:         no += 4;
0399:     }
0400:     }
0401: 
0402:     // 適当なときに画像を保存する
0403:     if( (1<<save_bit) <= GetRenderCount() )
0404:     {
0405:         // ファイル名を決める
0406:         _TCHAR buf[256];
0407:         _stprintf( buf, _T("%d.bmp"), GetRenderCount());
0408:         
0409:         // ビットマップイメージを作る
0410:         BYTE *pImage = new BYTE[3 * RENDER_WIDTH * RENDER_HEIGHT];
0411:         k = 0;
0412:         for(s32 j=0; j<RENDER_HEIGHT; j++)
0413:         {
0414:             no = 4*RENDER_WIDTH*(RENDER_HEIGHT-j-1);
0415:             for(s32 i=0; i<RENDER_WIDTH ; i++)
0416:             {
0417:                 pImage[k+0] = s_data [no+2];
0418:                 pImage[k+1] = s_data [no+1];
0419:                 pImage[k+2] = s_data [no+0];
0420:                 no += 4;
0421:                 k += 3;
0422:             }
0423:         }
0424: 
0425:         // ビットマップに必要な情報を格納する
0426:         SAVE_BITMAP tBitmap_Info;
0427:         tBitmap_Info.pFileName = buf;
0428:         tBitmap_Info.iWidth  = RENDER_WIDTH;
0429:         tBitmap_Info.iHeight = RENDER_HEIGHT;
0430:         tBitmap_Info.iBitCount = 24;
0431:         tBitmap_Info.pData = (BYTE*)pImage;
0432: 
0433:         SaveBitMap( tBitmap_Info );
0434: 
0435:         delete[] pImage;
0436: 
0437:         save_bit++;
0438:     }
0439: 
0440:     return 0;
0441: }
0442: 
0443: // ---------------------------------------------------------------------------
0444: #define GETCOLOR_FLAG_DISABLE_EMMISIVE (1<<0)
0445: 
0446: bool GetColor( D3DXVECTOR3 *dest, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v, int depth, u32 flag )
0447: {
0448:     D3DXVECTOR3 diffuse_color=D3DXVECTOR3(0,0,0);
0449: 
0450:     // -----------------------------------------------------------------------
0451:     // 初期化:光が屈折、反射しかしないで延々と跳ね返ったときは、光が届かない黒色
0452:     // -----------------------------------------------------------------------
0453:     if(0==depth) *dest = D3DXVECTOR3(0,0,0);
0454: 
0455:     // -----------------------------------------------------------------------
0456:     // 再帰しすぎた場合は光が届いていないものと考える
0457:     // -----------------------------------------------------------------------
0458:     const int DEPTH_MAX = 3;
0459:     if(DEPTH_MAX <= depth) { *dest=D3DXVECTOR3(0,0,0); return FALSE;}
0460: 
0461:     // -----------------------------------------------------------------------
0462:     // 視線から交点を求める
0463:     // -----------------------------------------------------------------------
0464:     float t = CPrimitive::INFINTY_DIST;
0465:     CPrimitive *pObj = NULL;
0466:     D3DXVECTOR4 p, n;// 交点の位置と法線
0467: 
0468:     t = pShpereS   ->IsAcross(t, &n, &p, &pObj, x, v);
0469:     t = pShpereT   ->IsAcross(t, &n, &p, &pObj, x, v);
0470:     t = pRoom      ->IsAcross(t, &n, &p, &pObj, x, v);
0471: //  t = pBlockSmall->IsAcross(t, &n, &p, &pObj, x, v);
0472:     t = pBlockTall ->IsAcross(t, &n, &p, &pObj, x, v);
0473: 
0474:     if( NULL == pObj ){
0475:         // 視線はオブジェクトから外れた!
0476:         *dest = BG_COLOR;
0477:         return TRUE;
0478:     }
0479: 
0480:     // -----------------------------------------------------------------------
0481:     // 反射方向をロシアンルーレットで決める
0482:     // -----------------------------------------------------------------------
0483:     float cd = pObj->m_material.diffuse;    // 拡散率
0484:     float cr = pObj->m_material.reflection; // 反射率
0485:     float cn = pObj->m_material.refraction; // 屈折率
0486:     float ce = pObj->m_material.emmisive;   // 放射率
0487:     float total = cd+cr+cn+ce;
0488:     float prob = total * (float)frand();
0489: 
0490:     int type = 0;// 拡散
0491:     if(prob < cr      ) type = 1; else// 反射
0492:     if(prob < cr+cn   ) type = 2; else// 屈折
0493:     if(prob < cr+cn+ce) type = 3;     // 放射
0494: 
0495:     // -----------------------------------------------------------------------
0496:     // 交点が、影に隠れているかどうか調べて、拡散光を算出する
0497:     // -----------------------------------------------------------------------
0498:     if(0==type)
0499:     {
0500:         if(++depth<DEPTH_MAX)
0501:         {
0502:             D3DXVECTOR4 dir, pos;
0503: 
0504:             // --- 光源の影響を考慮に入れる
0505:             D3DXVECTOR4 lp;
0506:             D3DXVECTOR3 ln;
0507:             // 光源から1点を選ぶ
0508:             LIGHT_DATA *pData = choiceEmmisivePoint( &lp, &ln );
0509:             D3DXVECTOR4 vr = lp-p; vr.w = 0;
0510:             float d2 = D3DXVec3Dot((D3DXVECTOR3 *)&vr,(D3DXVECTOR3 *)&vr); // 反射点から光源までの距離の2乗
0511:             D3DXVec4Normalize(&vr, &vr);     // 反射点から光源を見る方向
0512: 
0513:             // その点が見えるかどうか調べる
0514:             CPrimitive *pTObj = NULL;
0515:             D3DXVECTOR4 tp, tn;// 交点の位置と法線
0516:             float tt = CPrimitive::INFINTY_DIST;
0517:             pos = p + 0.01f*(vr);
0518:             tt = pShpereS   ->IsAcross( tt, &tn, &tp, &pTObj, &pos, &vr );
0519:             tt = pShpereT   ->IsAcross( tt, &tn, &tp, &pTObj, &pos, &vr );
0520:             tt = pRoom      ->IsAcross( tt, &tn, &tp, &pTObj, &pos, &vr );
0521: //          tt = pBlockSmall->IsAcross( tt, &tn, &tp, &pTObj, &pos, &vr );
0522:             tt = pBlockTall ->IsAcross( tt, &tn, &tp, &pTObj, &pos, &vr );
0523:             
0524:             if( pTObj && 1.0f == pTObj->m_material.emmisive )
0525:             {
0526:                 // 直接光と間接光の強さの割合を見える面積で求める
0527:                 float prob;
0528:                 prob = -g_fTotalArea * D3DXVec3Dot((D3DXVECTOR3 *)&vr, (D3DXVECTOR3 *)&ln)/d2;
0529:                 prob /= 2.0f*D3DX_PI;// 光源が半球を囲んだときの立体角は2πsr
0530:                 if(prob<0)prob=0;
0531:                 if(1<prob)prob=1;
0532: 
0533:                 float rn = D3DXVec3Dot((D3DXVECTOR3 *)&vr, (D3DXVECTOR3 *)&n);
0534:                 rn = max( 0, rn );
0535:                 diffuse_color.x = prob * pTObj->m_material.COLOR_DIF[0] * rn;
0536:                 diffuse_color.y = prob * pTObj->m_material.COLOR_DIF[1] * rn;
0537:                 diffuse_color.z = prob * pTObj->m_material.COLOR_DIF[2] * rn;
0538:             }
0539:             
0540:             // --- ロシアンルーレットで別のレイも飛ばす
0541:             
0542:             // 等方的にレイを飛ばす
0543:             float theta =      D3DX_PI * (float)frand();
0544:             float phi   = 2.0f*D3DX_PI * (float)frand();
0545:             dir.x = sinf(theta) * cosf(phi);
0546:             dir.y = sinf(theta) * sinf(phi);
0547:             dir.z = cosf(theta);
0548:             float dn = D3DXVec3Dot((D3DXVECTOR3 *)&dir, (D3DXVECTOR3 *)&n);
0549:             if(dn<0){
0550:                 // 法線と反対向きに飛ぶつもりなら、方向を反対にする
0551:                 dn = -dn;
0552:                 dir.x *= -1;
0553:                 dir.y *= -1;
0554:                 dir.z *= -1;
0555:             }
0556: 
0557:             D3DXVECTOR3 c;
0558:             pos = p + 0.01f*(dir);
0559:             GetColor( &c, &pos, &dir, depth, GETCOLOR_FLAG_DISABLE_EMMISIVE );
0560:             // プリミティブの色や拡散光の余弦側を適用
0561:             diffuse_color.x += c.x * dn;
0562:             diffuse_color.y += c.y * dn;
0563:             diffuse_color.z += c.z * dn;
0564: 
0565:             diffuse_color.x *= pObj->m_material.COLOR_DIF[0] * 0.5f*D3DX_PI;
0566:             diffuse_color.y *= pObj->m_material.COLOR_DIF[1] * 0.5f*D3DX_PI;
0567:             diffuse_color.z *= pObj->m_material.COLOR_DIF[2] * 0.5f*D3DX_PI;
0568:         }
0569:     }
0570: 
0571:     // -----------------------------------------------------------------------
0572:     // 再帰的に光線を飛ばして、より高次の反射を考慮に入れる
0573:     // -----------------------------------------------------------------------
0574:     // 反射
0575:     D3DXVECTOR3 reflect_color=D3DXVECTOR3(0,0,0);
0576:     if(1==type){
0577:         // 反射ベクトル
0578:         D3DXVECTOR4 r = *v - 2.0f*D3DXVec3Dot((D3DXVECTOR3 *)&n, (D3DXVECTOR3 *)v) * n;
0579:         D3DXVECTOR4 pos = p + 0.01f*n;// ちょっと浮かす
0580:         if(!GetColor( &reflect_color, &pos, &r, depth,0)){
0581:             cr = 0;// 結局、光が届かなかった
0582:         }
0583:     }
0584: 
0585:     // -----------------------------------------------------------------------
0586:     // 屈折
0587:     // -----------------------------------------------------------------------
0588:     D3DXVECTOR3 refract_color=D3DXVECTOR3(0,0,0);
0589:     if(2==type){
0590:         // 屈折ベクトル
0591:         D3DXVECTOR4 t, pos;
0592:         float VN = D3DXVec3Dot((D3DXVECTOR3 *)v, (D3DXVECTOR3 *)&n);
0593:         float eta = 1.5f;
0594:         if(VN<0){
0595:             // 入射
0596:             float D = 1-(1+VN)*(1+VN)/(eta*eta);
0597:             if(D<0){cn=0;goto no_refract;}// 全反射
0598:             t = (-VN/eta-sqrtf(D))*n+(1/eta)*(*v);
0599:             pos = p - 0.01f*n;// ちょっと浮かす
0600:         }else{
0601:             // 出て行く
0602:             float D = 1-(1-VN)*(1-VN)*(eta*eta);
0603:             if(D<0){cn=0;goto no_refract;}// 全反射
0604:             t = -(VN*eta-sqrtf(D))*n+eta*(*v);
0605:             pos = p + 0.01f*n;// ちょっと浮かす
0606:         }
0607:         D3DXVec3Normalize( (D3DXVECTOR3 *)&t, (D3DXVECTOR3 *)&t );
0608:         if(!GetColor( &refract_color, &pos, &t, depth,0)){
0609:             cn = 0;// 結局、光が届かなかった
0610:         }
0611:     }
0612: no_refract:
0613: 
0614:     // -----------------------------------------------------------------------
0615:     // 放射
0616:     // -----------------------------------------------------------------------
0617:     D3DXVECTOR3 emmisive_color;
0618:     if(flag & GETCOLOR_FLAG_DISABLE_EMMISIVE)
0619:     {
0620:         emmisive_color = D3DXVECTOR3(0,0,0);
0621:     }else{
0622:         emmisive_color = *(D3DXVECTOR3*)&pObj->m_material.COLOR_DIF;
0623:     }
0624: 
0625:     // -----------------------------------------------------------------------
0626:     // 色を出力する
0627:     // -----------------------------------------------------------------------
0628:     switch(type){
0629:     case 0:// 拡散
0630:         *dest = (cd+cr+cn) * diffuse_color;
0631:         break;
0632:     case 1:// 反射
0633:         *dest = (cd+cr+cn) * reflect_color;     
0634:         break;
0635:     case 2:// 屈折
0636:         *dest = (cd+cr+cn) * refract_color;
0637:         break;
0638:     case 3:// 放射
0639:         *dest = ce * emmisive_color;
0640:         break;
0641:     }
0642: 
0643:     return TRUE;
0644: }
0645: // ---------------------------------------------------------------------------
0646: D3DXVECTOR3 *GetColor(D3DXVECTOR3 *dest, float x, float y)
0647: {
0648:     D3DXVECTOR4 ray_start;
0649:     D3DXVECTOR4 ray_dir;
0650:     
0651:     ray_start.w = 1.0f;
0652:     ray_dir.w   = 0.0f;
0653: 
0654:     camera.GetRay( (D3DXVECTOR3*)&ray_start, (D3DXVECTOR3*)&ray_dir, x, y);
0655:     
0656:     GetColor(dest, &ray_start, &ray_dir, 0,0);
0657: 
0658:     return dest;
0659: }
0660: 
0661: };// namespace Render
0662: