Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Renderer.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * レンダラ実装
00022  * @author Junpee
00023  */
00024 
00025 #include "LampBasic.h"
00026 #include "Graphics/Renderer/Renderer.h"
00027 #include "Graphics/Renderer/DrawRequest.h"
00028 #include "Graphics/System/LampGraphics.h"
00029 #include "Graphics/Renderer/RenderingDevice.h"
00030 #include "Graphics/System/GraphicsDeviceCapacity.h"
00031 #include "Graphics/Camera/Camera.h"
00032 #include "Graphics/Light/LightManager.h"
00033 #include "Graphics/Mesh/Mesh.h"
00034 #include "Graphics/Material/Material.h"
00035 
00036 namespace Lamp{
00037 
00038 //------------------------------------------------------------------------------
00039 // 生成、破棄
00040 //------------------------------------------------------------------------------
00041 // コンストラクタ
00042 Renderer::Renderer() : meshList_(initialMeshListSize){
00043     // デバイスオブジェクトホルダ登録
00044     LampGraphics::addDeviceObjectHolder(this);
00045     buildRendererStateBlock();
00046     drawRequest_ = new DrawRequest();
00047 }
00048 //------------------------------------------------------------------------------
00049 // デストラクタ
00050 Renderer::~Renderer(){
00051     SafeDelete(drawRequest_);
00052     SafeRelease(rendererStateBlock_);
00053     // デバイスオブジェクトホルダ登録解除
00054     LampGraphics::removeDeviceObjectHolder(this);
00055 }
00056 //------------------------------------------------------------------------------
00057 // レンダリング
00058 //------------------------------------------------------------------------------
00059 // レンダリング準備を行う
00060 void Renderer::renderingSetup(Scene* scene){
00061     RenderingDevice* device = RenderingDevice::getInstance();
00062     scene_ = scene;
00063     // メッシュリストの構築
00064     buildMeshList();
00065     // 描画リクエストの初期化
00066     initializeDrawRequest();
00067 }
00068 //------------------------------------------------------------------------------
00069 // レンダリングを行う
00070 void Renderer::rendering(){
00071     RenderingDevice* device = RenderingDevice::getInstance();
00072     // デフォルトステートブロック適用
00073     device->applyDefaultStateBlock();
00074     // レンダラステートブロック適用
00075     device->applyStateBlock(rendererStateBlock_);
00076     // グローバル設定の初期化
00077     initializeGlobalSettings();
00078     // 描画
00079     if(device->beginScene()){
00080         int meshCount = meshList_.getCount();
00081         for(int i = 0; i < meshCount; i++){
00082             Mesh* mesh = meshList_.get(i);
00083             Material* material = mesh->getMaterial();
00084             drawRequest_->setMesh(mesh);
00085             // ブレンディングを有効にする
00086             if(drawRequest_->isBlendEnabled()){
00087                 device->setBlending(true);
00088                 device->setRenderState(
00089                     D3DRS_ALPHAREF, blendingAlphaTestBorder_);
00090             }
00091             // ローカルライトリストの構築
00092             if(material->useLight()){
00093                 drawRequest_->clearLocalLights();
00094                 scene_->getLocalLightList(mesh, drawRequest_);
00095             }
00096             // 描画
00097             material->draw(drawRequest_);
00098         }
00099         // 描画後始末
00100         device->endScene();
00101     }
00102     // デフォルトステートブロック適用
00103     device->applyDefaultStateBlock();
00104 }
00105 //------------------------------------------------------------------------------
00106 // メッシュリストの構築
00107 void Renderer::buildMeshList(){
00108     meshList_.clear();
00109     Camera* camera = scene_->getCurrentCamera();
00110     scene_->getMeshList(&meshList_, camera);
00111     int meshCount = meshList_.getCount();
00112     // カメラとの距離の二乗をテンポラリデータに設定
00113     Vector3 cameraPosition = camera->getPosition();
00114     for(int i = 0; i < meshCount; i++){
00115         Mesh* mesh = meshList_.get(i);
00116         mesh->setRenderingTemporaryData(
00117             (cameraPosition - mesh->getWorldCenter()).getSquaredLength());
00118     }
00119     // メッシュリストのソート
00120     meshList_.sort(sortMeshList);
00121 /* 正しいソートが行われているかprintfチェック
00122     for(int i = 0; i < meshCount; i++){
00123         Mesh* mesh = meshList_.get(i);
00124         Material* material = mesh->getMaterial();
00125         DebugOut("%3d %d %2d 0x%08x %6.1f %s\n",
00126             i, material->getBlendMode(), material->getPriority(),
00127             material,
00128             mesh->getRenderingTemporaryData(),
00129             material->getName().getBytes());
00130     }
00131     DebugOut("\n");// ここにブレークポイントを仕掛ける
00132 //*/
00133 }
00134 //------------------------------------------------------------------------------
00135 // メッシュリストのソート
00136 int Renderer::sortMeshList(Mesh* const* left, Mesh* const* right){
00137     const Mesh* leftMesh = (*left);
00138     const Mesh* rightMesh = (*right);
00139     const Material* leftMaterial = leftMesh->getMaterial();
00140     const Material* rightMaterial = rightMesh->getMaterial();
00141     if(!leftMaterial->isBlendEnabled()){
00142         // アルファソート
00143         if(rightMaterial->isBlendEnabled()){ return -1; }
00144         // アルファでないメッシュのソート
00145         // マテリアル優先度で比較
00146         int priority =
00147             rightMaterial->getPriority() - leftMaterial->getPriority();
00148         if(priority != 0){ return priority; }
00149         // マテリアルのアドレスでソート
00150         int leftAddress = (int)((*(u_int*)&leftMaterial) & 0x8fffffff);
00151         int rightAddress = (int)((*(u_int*)&rightMaterial) & 0x8fffffff);
00152         int address = leftAddress - rightAddress;
00153         if(address != 0){ return address; }
00154         // 手前から奥にZソート
00155         float cameraSquaredDistance = rightMesh->getRenderingTemporaryData() -
00156             leftMesh->getRenderingTemporaryData();
00157         if(cameraSquaredDistance > 0.f){ return -1; }
00158         else{ return 1; }
00159     }else{
00160         // アルファソート
00161         if(!rightMaterial->isBlendEnabled()){ return 1; }
00162         // アルファメッシュのソート
00163         // 奥から手前にZソート
00164         float cameraSquaredDistance = leftMesh->getRenderingTemporaryData() -
00165             rightMesh->getRenderingTemporaryData();
00166         if(cameraSquaredDistance > 0.f){ return -1; }
00167         else{ return 1; }
00168     }
00169     return 0;
00170 }
00171 //------------------------------------------------------------------------------
00172 // 描画リクエストの初期化
00173 void Renderer::initializeDrawRequest(){
00174     drawRequest_->clear();
00175     drawRequest_->setFog(scene_->getFog());
00176     drawRequest_->setCamera(scene_->getCurrentCamera());
00177     // グローバルライトの初期化
00178     LightManager* lightManager = scene_->getLightManager();
00179     int lightCount = lightManager->getCount();
00180     for(int i = 0; i < lightCount; i++){
00181         Light* light = lightManager->get(i);
00182         // 無効なライトを無視する
00183         if(!light->isGlobalEnabled()){ continue; }
00184         if(light->isAmbientLight()){
00185             drawRequest_->addAmbientLight(light->castAmbientLight());
00186         }else if(light->isDirectionalLight()){
00187             drawRequest_->addDirectionalLight(light->castDirectionalLight());
00188         }
00189     }
00190 }
00191 //------------------------------------------------------------------------------
00192 // グローバル設定の初期化
00193 void Renderer::initializeGlobalSettings(){
00194     // 一回のレンダリング中には変化しない設定を行う
00195     RenderingDevice* device = RenderingDevice::getInstance();
00196     // カメラ行列の設定
00197     Camera* camera = drawRequest_->getCamera();
00198     device->setProjectionMatrix(camera->getProjectionMatrix());
00199     device->setViewMatrix(camera->getViewMatrix());
00200     // フォグの設定
00201     device->setFog(drawRequest_->getFog());
00202 }
00203 //------------------------------------------------------------------------------
00204 // レンダラステートブロックの構築
00205 void Renderer::buildRendererStateBlock(){
00206     RenderingDevice* device = RenderingDevice::getInstance();
00207     GraphicsDeviceCapacity* capacity = GraphicsDeviceCapacity::getInstance();
00208     // デフォルトステートブロック適用
00209     device->applyDefaultStateBlock();
00210     // レンダラステートブロックの構築開始
00211     device->beginStateBlock();
00212 
00213     // カリングを逆順にする
00214     device->setRenderState(D3DRS_CULLMODE, D3DCULL_CW);
00215 
00216     // テクスチャサンプラにミップマップと線形補間を設定する
00217     int textureStageCount = capacity->getMaxTextureBlendStages();
00218     for(int i = 0; i < textureStageCount; i++){
00219         device->setSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00220         device->setSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00221         device->setSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
00222     }
00223 
00224     // 頂点カラーをエミッシブとして使用する
00225     device->setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
00226     device->setRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
00227     device->setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
00228 
00229     // アルファテストの設定
00230     // アルファブレンディングを行わなくてもアルファテストは行う
00231     device->setRenderState(D3DRS_ALPHATESTENABLE, true);
00232     device->setRenderState(D3DRS_ALPHAREF, alphaTestBorder_);
00233     device->setRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
00234 
00235     // レンダラステートブロックの構築完了
00236     rendererStateBlock_ = device->endStateBlock();
00237     // デフォルトステートブロック適用
00238     device->applyDefaultStateBlock();
00239 }
00240 //------------------------------------------------------------------------------
00241 } // End of namespace Lamp
00242 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:34 2005 for Lamp by doxygen 1.3.2