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 //------------------------------------------------------------------------------