Ogre SkyBox构建、渲染

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);


内容概要:本文详细探讨了基于MATLAB/SIMULINK的多载波无线通信系统仿真及性能分析,重点研究了以OFDM为代表的多载波技术。文章首先介绍了OFDM的基本原理和系统组成,随后通过仿真平台分析了不同调制方式的抗干扰性能、信道估计算法对系统性能的影响以及同步技术的实现与分析。文中提供了详细的MATLAB代码实现,涵盖OFDM系统的基本仿真、信道估计算法比较、同步算法实现和不同调制方式的性能比较。此外,还讨论了信道特征、OFDM关键技术、信道估计、同步技术和系统级仿真架构,并提出了未来的改进方向,如深度学习增强、混合波形设计和硬件加速方案。; 适合人群:具备无线通信基础知识,尤其是对OFDM技术有一定了解的研究人员和技术人员;从事无线通信系统设计与开发的工程师;高校通信工程专业的高年级本科生和研究生。; 使用场景及目标:①理解OFDM系统的工作原理及其在多径信道环境下的性能表现;②掌握MATLAB/SIMULINK在无线通信系统仿真中的应用;③评估不同调制方式、信道估计算法和同步算法的优劣;④为实际OFDM系统的设计和优化提供理论依据和技术支持。; 其他说明:本文不仅提供了详细的理论分析,还附带了大量的MATLAB代码示例,便于读者动手实践。建议读者在学习过程中结合代码进行调试和实验,以加深对OFDM技术的理解。此外,文中还涉及了一些最新的研究方向和技术趋势,如AI增强和毫米波通信,为读者提供了更广阔的视野。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值