Ogre SkyBox构建、渲染
来源:互联网 发布:测脸型的软件 编辑:程序博客网 时间:2024/05/16 08:39
1. SkyBox的构建过程
OgreSceneManager.cpp
/** Enables / disables a 'sky box' i.e. a 6-sided box at constant distance from the camera representing the sky. @remarks You could create a sky box yourself using the standard mesh and entity methods, but this creates a plane which the camera can never get closer or further away from - it moves with the camera. (NB you could create this effect by creating a world box which was attached to the same SceneNode as the Camera too, but this would only apply to a single camera whereas this skybox applies to any camera using this scene manager). @par The material you use for the skybox can either contain layers which are single textures, or they can be cubic textures, i.e. made up of 6 images, one for each plane of the cube. See the TextureUnitState class for more information. @param enable True to enable the skybox, false to disable it @param materialName The name of the material the box will use @param distance Distance in world coorinates from the camera to each plane of the box. The default is normally OK. @param drawFirst If true, the box is drawn before all other geometry in the scene, without updating the depth buffer. This is the safest rendering method since all other objects will always appear in front of the sky. However this is not the most efficient way if most of the sky is often occluded by other objects. If this is the case, you can set this parameter to false meaning it draws <em>after</em> all other geometry which can be an optimisation - however you must ensure that the distance value is large enough that no objects will 'poke through' the sky box when it is rendered. @param orientation Optional parameter to specify the orientation of the box. By default the 'top' of the box is deemed to be in the +y direction, and the 'front' at the -z direction. You can use this parameter to rotate the sky if you want. @param groupName The name of the resource group to which to assign the plane mesh. */void SceneManager::setSkyBox( bool enable, const String& materialName, Real distance, bool drawFirst, const Quaternion& orientation, const String& groupName){_setSkyBox(enable, materialName, distance, static_cast<uint8>(drawFirst?RENDER_QUEUE_SKIES_EARLY: RENDER_QUEUE_SKIES_LATE), orientation, groupName);}
SkyBox实际实现代码:
//-----------------------------------------------------------------------void SceneManager::_setSkyBox( bool enable, const String& materialName, Real distance, uint8 renderQueue, const Quaternion& orientation, const String& groupName){ // 是否启用SkyBox if (enable) { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName, groupName); if (m.isNull()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Sky box material '" + materialName + "' not found.", "SceneManager::setSkyBox"); } // Ensure loaded m->load(); if (!m->getBestTechnique() || !m->getBestTechnique()->getNumPasses()) { // 材质没有Technique或是获取Pass个数为零,使用默认设置的材质 LogManager::getSingleton().logMessage( "Warning, skybox material " + materialName + " is not supported, defaulting."); m = MaterialManager::getSingleton().getDefaultSettings(); } // 确定纹理单元的类型是普通纹理还是3D纹理 bool t3d = false; Pass* pass = m->getBestTechnique()->getPass(0); if (pass->getNumTextureUnitStates() > 0 && pass->getTextureUnitState(0)->is3D()) t3d = true; // 设置SkyBox的渲染顺序 mSkyBoxRenderQueue = renderQueue; // Create node if (!mSkyBoxNode) { // 创建SkyBox挂载的SceneNode节点 // SkyBoxNode不挂载在场景树的任何节点上,而是在SceneManager::_queueSkiesForRendering(Camera *cam), // 设置SkyBoxNode的坐标为Camera的坐标,保证Camera与SkyBoxNode的坐标一致 mSkyBoxNode = createSceneNode("SkyBoxNode"); } // Create object if (!mSkyBoxObj) { // 创建SkyBox对象,设置不投影,将对象挂载到SkyBox上 mSkyBoxObj = OGRE_NEW ManualObject("SkyBox"); mSkyBoxObj->setCastShadows(false); mSkyBoxNode->attachObject(mSkyBoxObj); } else { // 若已存在SkyBox对象,清除原对象的内容 if (!mSkyBoxObj->isAttached()) { mSkyBoxNode->attachObject(mSkyBoxObj); } mSkyBoxObj->clear(); } // 设置SkyBox的渲染队列组 mSkyBoxObj->setRenderQueueGroup(mSkyBoxRenderQueue); if (t3d) { // 纹理单元是否为3D图片? mSkyBoxObj->begin(materialName); } MaterialManager& matMgr = MaterialManager::getSingleton(); // Set up the box (6 planes) for (uint16 i = 0; i < 6; ++i) { Plane plane; String meshName; Vector3 middle; Vector3 up, right; switch(i) { case BP_FRONT: middle = Vector3(0, 0, -distance); up = Vector3::UNIT_Y * distance; right = Vector3::UNIT_X * distance; break; case BP_BACK: middle = Vector3(0, 0, distance); up = Vector3::UNIT_Y * distance; right = Vector3::NEGATIVE_UNIT_X * distance; break; case BP_LEFT: middle = Vector3(-distance, 0, 0); up = Vector3::UNIT_Y * distance; right = Vector3::NEGATIVE_UNIT_Z * distance; break; case BP_RIGHT: middle = Vector3(distance, 0, 0); up = Vector3::UNIT_Y * distance; right = Vector3::UNIT_Z * distance; break; case BP_UP: middle = Vector3(0, distance, 0); up = Vector3::UNIT_Z * distance; right = Vector3::UNIT_X * distance; break; case BP_DOWN: middle = Vector3(0, -distance, 0); up = Vector3::NEGATIVE_UNIT_Z * distance; right = Vector3::UNIT_X * distance; break; } // Modify by orientation middle = orientation * middle; up = orientation * up; right = orientation * right; if (t3d) { // 3D cubic texture // Note UVs mirrored front/back // I could save a few vertices here by sharing the corners // since 3D coords will function correctly but it's really not worth // making the code more complicated for the sake of 16 verts // top left Vector3 pos; pos = middle + up - right; mSkyBoxObj->position(pos); mSkyBoxObj->textureCoord(pos.normalisedCopy() * Vector3(1,1,-1)); // bottom left pos = middle - up - right; mSkyBoxObj->position(pos); mSkyBoxObj->textureCoord(pos.normalisedCopy() * Vector3(1,1,-1)); // bottom right pos = middle - up + right; mSkyBoxObj->position(pos); mSkyBoxObj->textureCoord(pos.normalisedCopy() * Vector3(1,1,-1)); // top right pos = middle + up + right; mSkyBoxObj->position(pos); mSkyBoxObj->textureCoord(pos.normalisedCopy() * Vector3(1,1,-1)); uint16 base = i * 4; // 根据六个面上的点构建每个面,并获取纹理UV坐标,构建各个面 mSkyBoxObj->quad(base, base+1, base+2, base+3); } else // !t3d { // If we're using 6 separate images, have to create 6 materials, one for each frame // Used to use combined material but now we're using queue we can't split to change frame // This doesn't use much memory because textures aren't duplicated String matName = mName + "SkyBoxPlane" + StringConverter::toString(i); MaterialPtr boxMat = matMgr.getByName(matName, groupName); if (boxMat.isNull()) { // Create new by clone boxMat = m->clone(matName); boxMat->load(); } else { // Copy over existing m->copyDetailsTo(boxMat); boxMat->load(); } // Make sure the material doesn't update the depth buffer // 天空总是处于其它物体的背后,不需要重写、检查深度值,SkyBox的颜色总是被覆盖的 boxMat->setDepthWriteEnabled(false); // Set active frame Material::TechniqueIterator ti = boxMat->getSupportedTechniqueIterator(); while (ti.hasMoreElements()) { Technique* tech = ti.getNext(); if (tech->getPass(0)->getNumTextureUnitStates() > 0) { TextureUnitState* t = tech->getPass(0)->getTextureUnitState(0); // Also clamp texture, don't wrap (otherwise edges can get filtered) t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); /** Changes the active frame in an animated or multi-image texture. @remarks An animated texture (or a cubic texture where the images are not combined for 3D use) is made up of a number of frames. This method sets the active frame. @note Applies to both fixed-function and programmable pipeline. */ t->setCurrentFrame(i); } } // section per material mSkyBoxObj->begin(matName, RenderOperation::OT_TRIANGLE_LIST, groupName); // top left mSkyBoxObj->position(middle + up - right); mSkyBoxObj->textureCoord(0,0); // bottom left mSkyBoxObj->position(middle - up - right); mSkyBoxObj->textureCoord(0,1); // bottom right mSkyBoxObj->position(middle - up + right); mSkyBoxObj->textureCoord(1,1); // top right mSkyBoxObj->position(middle + up + right); mSkyBoxObj->textureCoord(1,0); mSkyBoxObj->quad(0, 1, 2, 3); mSkyBoxObj->end(); } } // for each plane if (t3d) { mSkyBoxObj->end(); } } mSkyBoxEnabled = enable; mSkyBoxGenParameters.skyBoxDistance = distance;}
SkyBox渲染:
也是在OgreSceneManager::_renderScene()中的_renderVisibleObjects()中进行
OgreSceneManager::_renderScene -----> OgreSceneManager::_renderVisibleObjects() -----> OgreSceneManager::renderVisibleObjectsDefaultSequence() ----->
OgreSceneManager::_renderQueueGroupObjects() -----> OgreSceneManager::renderBasicQueueGroupObjects() /* No shadows, ordinary pass */ -----> OgreSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), 0m, true, true); -----> OgreQueuedRenderableCollection::acceptVisitor() -----> OgreQueuedRenderableCollection::acceptVisitorGrouped() -----> OgreSceneManager::SceneMgrQueuedRenderableVisitor::visit(Ogre::Renderable *r) ----->
OgreSceneManager::renderSingleObject() -----> D3D9RenderSystem::_render(const RenderOperation &op);
- Ogre SkyBox构建、渲染
- ogre的天空----SkyBox,SkyDome和SkyPlane
- SkyBox
- SkyBox
- 使用 Fantasy Skybox FREE 构建游戏场景
- 【Ogre引擎架构】 第十讲 唯美场景-天空盒SkyBox
- OGRE 渲染状态管理
- Ogre渲染目标
- OGRE 渲染 到 MFC
- Ogre的渲染系统
- OGRE 渲染流程
- Ogre主要渲染流程
- ogre渲染流程
- OGRE渲染对象
- Ogre渲染到纹理
- OGRE渲染对象
- OGRE - RenderProcess (渲染流程)
- OGRE 渲染 到 MFC
- FCF中文指南-第二章--FusionCharts Free安装
- 【串和序列处理 2】Trie Tree 串集合查找
- 三种方法 在Linux里设置环境变量的方法(export PATH)
- DataGridView排序後,如何抓取綁定資料的正確索引值
- 老男孩歌词--永恒的记忆
- Ogre SkyBox构建、渲染
- .net使用免费开源类库操作Excel
- 有道词典的API使用 C#
- Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask等
- 标题收缩展开效果
- mysql日志复制方式,删除方式
- 在GridView中使用模板列LinkButton,如何知道当前的LinkButton点击在哪行记录上? .
- 什么是CDN?
- [转]SSL原理