'Fog'에 해당되는 글 1건

  1. 2010.03.27 기초 튜토리얼3
2010.03.27 17:22

입문자 튜토리얼 3: Terrain, Sky, Fog, and the Root object

튜토리얼 진행중 문제가 발생한다면 Help 포럼 문의하세요.

Contents

*                                  1 미리 알아두어야

*                                  2 소개

*                                  3 시작하기

*                                  4 Root 객체와 SceneManager 생성

*                                          4.1 Root

*                                          4.2 SceneManager 생성

*                                  5 지형

*                                          5.1 장면에 지형 추가하기

*                                          5.2 terrain.cfg 파일

*                                          5.3 형조명

*                                  6 하늘

*                                          6.1 SkyBoxes

*                                          6.2 SkyDomes

*                                          6.3 SkyPlanes

*                                          6.4 어느것을 써야 하나?

*                                  7 안개

*                                          7.1 안개 소개

*                                          7.2 안개 종류

*                                          7.3 안개와 하늘

*                                          7.4 안개를 어둠처럼 사용하기

 

미리 알아두어야  

튜토리얼은 독자가 C++ 프로그래밍이 가능하고 오우거 어플리케이션 설정 컴파일이 가능하다는 가정하에 진행됩니다. 튜토리얼은 이전 튜토리얼을 기초로 작성되었으며 독자는 이전 튜토리얼들을 거쳐왔다고 가정합니다.

 

소개

튜토리얼에서는 어떻게 지형, 하늘 그리고 안개를 조작하는지 안내 것입니다. 튜토리얼 이후에 여러분은 Skyboxes, Skyplanes 그리고 Skydomes 차이점을 알고 있게 것입니다. 종류에 따른 안개들의 차이점도 알게 것이며 어떻게 쓰는지도 알게 것입니다.

튜토리얼을 진행함에 있어서 여러분은 천천히 코드를 따라가며 입력하고 결과를 지켜볼 필요성이 있습니다. 튜토리얼의 최종 코드는 여기(http://www.ogre3d.org/wiki/index.php/BasicTutorial3Source) 얻을 있습니다. 만약 작성한 코드에 문제가 발생한다면 코드와 비교해 보세요.

 

시작하기

지난번 튜토리얼처럼 미리 작성된 코드를 기초로 시작할 입니다. 프로젝트를 생성하고 아래의 코드를 입력하세요 :

#include "ExampleApplication.h"

 

class TutorialApplication : public ExampleApplication

{

protected:

public:

    TutorialApplication()

    {

    }

 

    ~TutorialApplication()

    {

    }

protected:

    void chooseSceneManager(void)

    {

    }

 

    void createScene(void)

    {

    }

};

 

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32

#define WIN32_LEAN_AND_MEAN

#include "windows.h"

 

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)

#else

int main(int argc, char **argv)

#endif

{

    // Create application object

    TutorialApplication app;

 

    try {

        app.go();

    } catch(Exception& e) {

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32

        MessageBox(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);

#else

        fprintf(stderr, "An exception has occurred: %s\n",

                e.getFullDescription().c_str());

#endif

    }

 

    return 0;

}

만약 오우거SDK Windows 에서 사용한다면 "[OgreSDK_DIRECTORY]\samples\include" 디렉토리 (ExampleApplication.h 파일이 있는곳) include 가능하도록 프로젝트에 추가해 주세요. 만약 오우거엔진 소스를 직접 사용하신다면 [OgreSource_DIRECTORY]\Samples\Common\include" 추가해 주세요. 다음 진행을 위해서 컴파일이 에러없이 되도록 해두세요. 그러나 실행은 하지마세요! 나중에 코드에 추가할 계획입니다. 만약 컴파일에 문제가 생긴다면 Wiki 페이지에서 컴파일러별 설정 정보를 찾아보시고 문제가 지속된다면 Help 포럼에 문의하세요.

프로그램이 동작되면 WASD 키로 움직이고 마우스로 주변을 둘러보는 기능을 합니다. ESC 키는 종료키 입니다.  


Trackback 0 : Comment 0

기초 튜토리얼 3-2

Ogre3D 삽질란/Basic Tutorial 3 2008/11/14 13:28

Root 객체와 SceneManager 생성  

Root

데모에서는 오우거에서 지형을 출력할 것입니다. 이걸 하기위해서 ExampleApplication 에서 기본으로 수행되는 SceneManager 설정을 TerrainSceneManager 클래스로 설정해야 합니다. chooseSceneManager 함수를 찾아서 다음 코드를 추가합니다 :

        mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE);

Root 객체 (mRoot Root 인스턴스입니다) 오우거의 "핵심" 객체 입니다. 여기(http://www.ogre3d.org/docs/manual/manual_4.html) 에서 오우거 객체들간의 관계를 나타내는 UML 다이어그램을 있습니다. 이것들이 RenderSystem 제외한 실제로 쓰이는 거의 모든 객체들 입니다. 코드는 Root 노드에게 ST_EXTERIOR_CLOSE 타입의 SceneManager 요구하는 코드입니다. Root 객체가 요청된 SceneManager 찾기위해 SceneManagerEnumerator 쿼리를 실행하고 해당되는 객체의 포인터를 리턴합니다.

여러분의 어플리케이션이 생성된 오우거의 Root 객체를 건드릴 일이 거의 없었을 것이며 SceneManagerEnumerator 직접적인 상호작업을 적도 없었을 겁니다.

 

SceneManager 생성

필자는 여러분의 추후에 있을 혼란을 방지하고자 SceneManager 생성과 저장에 대해서 설명해 드리려 합니다. SceneManager Singleton 아닙니다. 원하는 갯수만큼 생성할 있으며 SceneNodes/Lights/기타 와는 다르게 "new SceneManager()" 방식으로 바로 생성할 있습니다( 방식을 정말 원하신다면요). 여러개의 개별적인 도형들과 Entity 들을 가진 여러개의 SceneManager 동시에 다룰 있습니다. Viewport 다시 생성하거나(중급 튜토리얼 4에서 다룹니다) 여러개의 SceneManager 다수의 Viewport 이용해서 동시에 출력하는것으로 시간에 구애받지 않고 SceneManager 서로 교체하는게 가능합니다.

SceneManager 수동으로 생성하는 대신 createSceneManager 함수를 사용할까요? 오우거의 플러그인 시스템은 1개의 SceneManager 동작될때 가장좋은 유연성을 발휘합니다. SceneType 열거형 변수에는 몇몇 종류의 장면타입만이 설정되어 있습니다. 지금까지는 ExampleApplication 클래스에서 SceneManager ST_GENERIC 으로 설정했습니다. plugins.cfg 파일을 다뤄보지 않은 이상 어쩌면 이게 SceneManager 기본타입이라고 생각할지도 모르겠습니다만 실제로 알고보면 전혀다른 이름의 객체가 대신 쓰이고 있습니다! OctreeSceneManager 플러그인을 사용하면 기본값으로 OctreeSceneManager ST_GENERIC 등록하고 있습니다. OctreeSceneManager 보이지 않는 객체는 아예 그리지 않음으로써 평균적으로 일반 SceneManager 비해서 빠릅니다. 만약 OctreeSceneManager plugins.cfg 에서 제거시킨다면 ST_GENERIC 요구하면 기본 SceneManager 선택되거나 플러그인들에 기준하여 뭔가 나은뭔가가 대신에 선택될 입니다. 정말 멋진 시스템입니다.

이렇게 많은 분량을 진행 했음에도 SceneManager 생성할때 사용되는 Root 객체의 최소한의 기본내용들만 다뤘습니다. 사실 SceneManager 요청할때 SceneType 열거형 변수대신 문자열로 대체 가능합니다. 오우거는 유연한 SceneManager 생성시스템을 사용하며 오우거에서 몇개의 SceneManager 설정하던지, 몇개를 생성하고 파괴하던지 제한이 없습니다. 예를 들어보자면, "FooSceneManager" 라는 이름으로 생성할 있는 SceneManager 설치했다고  가정합시다. 한개의 SceneManager 다음과 같이 생성할 있을 입니다 :

       // do not add this to the project

       mSceneMgr = mRoot->createSceneManager("FooSceneManager");

방식은 기본 이름으로 한개를 생성할 입니다. 튜토리얼에서는 이렇게 기본 이름으로 생성시키지만 실제로 사용하실때에는 2번째 매개변수로 SceneManager 이름을 항상 지정해 줘야 합니다. 예를 들면 2개의 SceneManager 2개의 이름들로 만들고 싶다면 다음과 같이 있습니다 :

       // do not add this to the project

       mSceneMgr1 = mRoot->createSceneManager("FooSceneManager", "foo");

       mSceneMgr2 = mRoot->createSceneManager("FooSceneManager", "bar");

SceneManagers 이름을 짓는것으로 그것들의 포인터를 관리할 필요가 없어집니다. Root 객체가 대신 해주기 때문이죠. 나중에 "foo", "bar" 이름의 SceneManager 들이 필요하다면 다음과 같이 하면 됩니다 :  

       // do not add this to the project

       SceneManager *foo = mRoot->getSceneManager("foo");

       SceneManager *bar = mRoot->getSceneManager("bar");

SceneManager 쓰고나면 Root destroySceneManager 함수를 써서 제거하고 메모리를 절약하세요.

여기서는 다루지 않지만, SceneManagerFactory 클래스를 상속시켜서 유저만의 SceneManager 생성기를 정의 있습니다. 상속시켜서 만든 유저만의 SceneManager 기본적인 SceneManager에서 몇몇 기능들을 수정된 방식으로 쓰고 싶을 경우(카메라 조명 생성, 기하학 정보 로딩, 기타등등..) 유용하게 사용됩니다.

 

지형(Terrain)

 

장면에 지형 추가하기

이제 지형을 생성하기위해 준비가 끝났습니다. 기본 SceneManager 범용적인 장면 생성을 위해서 세분화된setWorldGeometry 함수를 정의합니다. 함수는 TerrainSceneManager 클래스와 함께 읽혀질 지형설정 파일이름을 필요로 합니다. TutorialApplication::createScene 함수를 찾아서 다음 코드를 추가합니다 :

        mSceneMgr->setWorldGeometry("terrain.cfg");

컴파일 실행시켜 봅시다. 쉽군요. 지형을 바라보는데 있어서 부적절한 카메라 위치때문에 카메라 시작위치를 수정해야 할지도 모르겠군요.

 

terrain.cfg 파일

terrain.cfg 파일에는 수많은 선택사항들이 있으며 지형생성을 위해서 이미지를 설정하는 최소한의 기본사항을 설명드릴 입니다. 지형설정파일에 대한 자세한 내용을 원하신다면 여기(http://www.ogre3d.org/wiki/index.php/Terrain_Scene_Manager) 참조하세요. TerrainSceneManager 대한 중요한 한가지는 페이징 기능을 염두하고 디자인되었으나 아직 구현되지 않았습니다. 지형에서의 페이징 기법은 지형덩어리를 여러개의 조각으로 나눈 다음에 보이는 부분만을 뽑아내어 출력하는 시스템 입니다. 이러한 기능은 대규모의 지형을 프레임 하락없이 보여줄 있게끔 줍니다. Paging Scene Manager 오우거 플러그인이 이러한 기능을 담당합니다.

TerrainSceneManager 지형생성시 Heightmap 방식을 사용합니다. "Heightmap.image" 속성을 조절하여 어떤 방식의 Heightmap 사용할지를 설정할 있습니다. WorldTexture 속성에서 어떤 덱스쳐가 지형에 쓰일지를 설정합니다. 지형 장면 매니저에서는 "DetailTexture" 속성으로 WorldTexture 얼마나 실제같이 보이게 것인지도 설정가능합니다. terrain.cfg 에서 설정된 각각의 이미지들을 찾아보시면 도움이 것입니다(Media 폴더안에 있을것 입니다).

어떻게 heightmap 생성하는지는 포럼에서 토론되어졌던 주제입니다. heightmap 관련된 궁금한 내용을 직접 찾아보세요.

 

지형조명

이전 튜토리얼에서는 조명과 그림자에 대해 전체지면을 할애하였지만 불행히도 TerrainSceneManager 적용하기는 쉽지 않습니다. 지금은 이것만 알아두세요. 차라리 텍스쳐의 세부적인 부분에 조명효과를 추가하는것이 일반적인 조명을 적용하는 보다 쉽습니다. 추후 안개 섹션에서 "가짜 어둠" 구현하는 방법을 다룰 입니다. 만약 지형에 조명을 적용하고 싶다면 Paging Scene Manager 사용법(http://www.ogre3d.org/wiki/index.php/Paging_Scene_Manager) 참조하세요. 그러한 구현에는 그게 향상된지원을 해줍니다.

 

하늘

오우거에서는 3가지 종류의 하늘을 제공합니다 : SkyBoxes, SkyDomes, SkyPlanes. 이제부터 하나하나 살펴보도록 하겠습니다. Example/* 텍스쳐를 쓰기위해 chooseSceneManager 함수에 다음 라인을 추가하세요 :

        ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

 

SkyBoxes

SkyBox 장면속의 모든 객체들을 둘러싼 거대한 큐브라 보시면 됩니다.

백문이 불여일견, 이것에 대해 설명하는 보다는 한번 보시는게 이해가 빠를 입니다. 다음 라인을 createScene 추가하세요 :

        mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox");

컴파일 실행시켜 봅시다. 깔끔한가요? (SkyBox 매우 크기때문에 텍스쳐의 실제해상도는 매우 낮아집니다; 고해상도의 SkyBox 나아보입니다.) SkyBox 설정을 위해서 setSkyBox 호출시 몇몇 유용한 기능들을 제어할 있는 매개변수들이 있습니다. 첫번째 옵션은 SkyBox 활성화할지의 여부입니다. 단순히 'mSceneMgr->setSkyBox(false, "");' 이런 호출만으로 비활성화가 됩니다. 두번째 매개변수는 SkyBox 재질설정 스크립트입니다.

세번째와 네번째 매개변수는 setSkyBox 있어서 이해하는데 중요합니다. 세번재는 SkyBox 카메라로부터 얼마나 멀리 떨어지느냐며, 네번째는 SkyBox 장면을 그린 이후에 그려질 것인지 아닌지를 설정합니다. 이런 이유로 어떤일이 벌어질지 관찰하기위해 세번째 매개변수값을 기본값인 5000에서 아주 가까운 값으로 바꿉니다 :  

        mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 10);

컴파일하고 실행시켜봐도 아무것도 바뀐게 없군요! 이유는 네번째 매개변수로 SkyBox 가장 먼저 그려질지 아닐지인 여부가 디폴트로 true값으로 설정되어 있습니다. 만약 SkyBox 먼저 그려진다면 위에 다른 모든것(지형같이..) 이후에 겹쳐서 그려지기때문에 SkyBox 항상 배경화면처럼 보입니다. (거리값을 근접클리핑 거리보다 높게 설정하지 않으면 SkyBox 보이지 않을겁니다!) 먼저 그리는 것은 그다지 좋아보이진 않습니다. 왜냐하면 모든게 그려지기 때문이죠. 마지막에 그린다면 보이는 부분만 그려지는데 약간의 속도 향상을 가져다 줍니다. 그렇기 때문에 SkyBox 마지막에 그려지도록 설정합시다 :

        mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 5000, false);

다시보면 전에 했던것과 비슷해 보이지만 SkyBox 보이지 않는 부분은 그려지지 않을것 입니다. 기법을 쓸때 조심해야 점이 한가지 있습니다. 만약 SkyBox 너무 가깝게 설정된다면 장면의 일부분을 잘라버릴지도 모릅니다. 예제로 다음을 시도해 보세요 :  

        mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 100, false);

보시는것과 같이 SkyBox 지형을 절단시켜 버렸군요. 절대로 우리가 원하는게 아닙니다. 만약 SkyBox 어플리케이션에서 활용할 계획이라면 어떻게 써야할지 결정해야 합니다. 빠른 렌더링 속도를 바란다면 지형 이후에 그리는게 바람직 것이며 지형지물에 방해되지 않도록 신중하게 해야 것입니다. 일반적인 경우 2번째 매개변수 이후로는 기본값을 사용하는게 안전합니다.

 

SkyDomes

SkyDome SkyBox 매우 비슷하며 setSkyDome 함수를 호출하여 렌더링 공간과 카메라가 있는 주면에 커닿란 큐브를 만듬으로 사용하게 됩니다. 그러나 차이점은  SkyBox 내부의 원형표면상의 "미리 설계된" 텍스쳐가 사용된다는 것입니다. 여전히 큐브를 바라보는 상태이지만 구면체를 둘러싼 텍스쳐 처럼 보입니다. 단점으로는 큐브의 바닥면은 텍스쳐가 없으므로 바닥을 메꿀만한 뭔가의 지형이 항상 필요하다는 입니다.

오우거에서 기본으로 제공하는 텍스쳐로 예제를 깔끔하게 보여줄 입니다. createScene 함수에서 setSkyBox 지우고 대신에 코드를 추가하세요 :

        mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);

실행시켰을 카메라를 지형의 중앙에 위치시키고 지형과 가까운 상태에서 카메라를 움직이세요 (이게 가장 나아보입니다). 보시고 나면 R 키를 눌러서 메쉬 모드로 바꿔보세요. 보시는것과 같이 여전히 큐브를 바라보고 있지만(바닥없이), 구름이 꼭대기 부근에서 원형으로 둘러 쌓인것 처럼 보입니다. (구름의 움직임은 "Examples/CloudySky" 재질속성이며 SkyDome 기본 제공기능이 아닙니다)

처음 2개의 setSkyDome 매개변수는 setSkyBox 같으며 'mSceneMgr->setSkyDome(false, "");' 호출로 SkyDome 있습니다. 세번째 매개변수는 SkyDome 곡률입니다. API 레퍼런스에서는 값으로 2~65 사이값을 추천합니다; 낮은값은 거리감이 좋아지며, 높은값은 화질손실이 낮아지며 부드러운 효과를 있습니다. 세번째 매개변수값을 2~65 값을 적용시켜보고 차이점을 관찰하세요. API 레퍼런스가 가르키는 거리효과는 아래 스크린 샷에서 확인할 있습니다. 셋팅은 곡률값 2 셋팅입니다 :

사용자 삽입 이미지

곡률값 64 셋팅입니다 :
사용자 삽입 이미지

4번째 매개변수는 텍스쳐의 쪼개지는 횟수 입니다. 값은 텍스쳐 크기에 따라 조절할 필요가 있습니다. 그리고 값은 정수가 아닌 실수값을 가집니다. 어플리케이션에서 필요하다면 텍스쳐를 1.234 쪼갤수 있습니다. 4번째와 6번째 값은 거리값과 drawFirst 입니다. 값들은 SkyBox 섹션에서 이미 설명한 내용들입니다.

 

SkyPlanes

SkyPlane SkyBox SkyDome 과는 매우 다릅니다. 거대한 큐브를 써서 하늘을 그리는 대신 단순한 평면 1개를 이용합니다. (앞으로 소개될 SkyPlane 설정에 있어서 시점이 지면의 중심을 향해야 하고 지면과 가까워야 합니다.) createScene 모든 내용을 지우세요. 가장 먼저 해야할 일은 평면을 생성하고 아랫방향으로 바라보게끔 하는 입니다. setSkyPlane 함수는 SkyBox SkyDome 같이 거리에 관련된 매개변수를 가지고 있지 않습니다. 대신 평면의 d 값으로 설정됩니다 :

        Plane plane;

        plane.d = 1000;

        plane.normal = Vector3::NEGATIVE_UNIT_Y;

이제 평면이 정의되었고 SkyPlane 생성할 있습니다. 4번째 매개변수는 SkyPlane 크기(여기서는 1500x1500 단위크기) 이며 5번째 매개변수는 얼마나 많은 수의 텍스쳐가 타일형식으로 나열될 것인지 입니다 :

        mSceneMgr->setSkyPlane(true, plane, "Examples/SpaceSkyPlane", 1500, 75);

컴파일 실행시켜 보세요. SkyPlane 2개의 문제점이 있군요.

첫번재는, 사용된 텍스쳐의 해상도가 너무 낮다는것과 예쁘게 보이지도 않습니다. 이것은 텍스쳐를 고화질에 고해상도로 생성하면 간단히 해결되는 문제입니다. 그러나 가장 중요한 문제는 수평으로 바라볼때 SkyPlane 끝이 보인다는 입니다. 이것은 아무리 좋은 텍스쳐를 쓴다고 해도 수평선을 바라보는 상황에서는 해결되지 않습니다. SkyPlane 기본적으로 유용하게 쓰일 경우는 높은 (또는 언덕) 시선주위에 존재 할때 입니다. SkyPlane 사용할 때에는 full SkyBox/SkyDome 생성하는 보다 낮은 그래픽 처리량을 기대할 있습니다.

다행히도 이것들이 SkyPlane 으로 있는 전부는 아닙니다. 6번째 매개변수는 SkyBox SkyDome 섹션에서 다뤘던 "renderFirst" 입니다. 7번째 매개변수는 SkyPlane 곡률을 설정할 있으므로 평면대신 볼록한 표면을 있습니다. 이제부터 SkyPlane 생성할때 x, y 조각들로 설정해야 합니다(초기 SkyPlane 나누어 지지 않은 하나의 사각형이지만 곡면이 필요할때 작은 사각형들로 구성되어야 합니다). 8, 9번째 매개변수는 x, y 조각 갯수입니다 :

        mSceneMgr->setSkyPlane(true, plane, "Examples/SpaceSkyPlane", 1500, 50, true, 1.5f, 150, 150);

실행시켜 보세요. 약간 부자연 스럽긴 하지만 훨씬 나은 SkyPlane 보입니다. 여기서 사용된 구름재질 대신에 이것을 사용해도 됩니다 :  

        mSceneMgr->setSkyPlane(true, plane, "Examples/CloudySky", 1500, 40, true, 1.5f, 150, 150);

컴파일후 실행시켜 보세요. 구름이 흘러가는 모습이 SkyDome 보다는 약간 부자연스럽게 보일 입니다. 특히 끝에 서서 수평선을 바라볼때 말이죠.

한가지 덧붙인다면 'mSceneMgr->setSkyPlane(false, Plane(), "");' 호출로 SkyPlane 지울 있습니다.

 

어느것을 써야 하나?

어떤 하늘을 사용할 것인지는 전적으로 유저에게 달렸습니다. -y 방향까지 포함하는 사방을 봐야 한다면 SkyBox밖에 없을 것입니다. 만약 지면 또는 -y 방향을 가로막는 뭔가가 있다면 SkyDome 리얼한 결과를 보여줄 것입니다. 수평선을 없는 상황(산으로 둘러쌓인 계곡이나 성벽으로 둘러쌓인 내부)에서는 SkyPlane GPU 자원을 적게 소비하여 아주 좋은 결과값을 보여줄 것입니다. SkyPlane 쓰는 중요한 이유는 다음 섹션, 멋진 안개효과에서 알게 것입니다.

이것들은 단지 제안에 불과합니다. 유저의 어플리케이션에서 어떤게 가장 나아 보이는지 직접 실험해 보세요.


Trackback 0 : Comment 0

기초 튜토리얼 3-3 (마지막)

Ogre3D 삽질란/Basic Tutorial 3 2008/11/14 13:25

안개

 

안개 소개

오우거에서의 안개는 사용하는데 어렵지 않습니다. 안개를 프로그램에 적용시키는데에는 한가지 절차만 알면 됩니다. TerrainSceneManager 쓸때 setFog 함수는 setWorldGeometry 함수 전에 호출되어야 합니다. (다른 SceneManager 에서는 상관없습니다.) 어느게 먼저 호출되느냐에따라 다른 vertex 프로그램이 안개와 지형을 만드는데 선택됩니다. (오우거 1.0.0 에서는 잘못된 호출 순서로 인한 급격한 안개량 증가로 아무것도 안보이게 만드는 버그거리였습니다; 오우거 1.0.1. 에서 고쳐졌습니다.)

시작하기전에 createScene 함수에서 setWorldGeometry 부분만 제외하고 지우세요.

안개를 설정함에 있어서 가장 중요한 것은 공간에 안개 Entity 흔히들 상상하는것 처럼 만들지 않는다는 입니다. 대신에 안개는 단지 현재 바라보고 있는 객체에 적용되는 필터일 뿐입니다. 이것은 흥미로운 점을 내포합니다. 아무것도 없는 공간을 쳐다볼 ( 어떤 객체도 보고 있지 않을때), 안개는 보이지 않습니다. 사실은 뷰포트의 배경색만 보이는 입니다. 그래서 안개가 제대로 보이게 하기 위해서는 배경색을 안개와 동일하게 맞춰줘야 합니다.

2가지 종류의 기본 안개타입이 있습니다 : linear exponential 방식입니다. Linear 안개는 선형적으로 안개가 짙어지고 exponential 안개는 급격하게 짙어집니다 ( 거리마다 바로 전에 짙어진 만큼보다 짙어 집니다). 설명하는 보다 보여주는게 이해가 쉬울것입니다. 다음 예제를 봅시다.

 

안개 종류

가장 이해하기 쉬운 linear 방식 안개를 먼저 보도록 합시다. 첫번째로 해야 일은 setWorldGeometry 호출 이후에 뷰포트의 배경색을 설정해야 합니다. createViewport 함수를 재정의 하여 구현할 있지만 (지난번 튜토리얼에서 했던 처럼) 가끔씩은 매번 뷰포트를 다시 생성하지 않고도 설정할 있어야 합니다. 이렇게 하면 됩니다 :

        ColourValue fadeColour(0.9, 0.9, 0.9);

        mWindow->getViewport(0)->setBackgroundColour(fadeColour);

getNumViewports 멤버함수를 사용하여 뷰포트 갯수를 절정할 있고 1 이상의 뷰포트를 다룰때 함수를 통해서 하나하나 선택할 있지만 그런경우는 없습니다(그리고 여기서는 1개의 뷰포트만 씁니다). 뷰포트는 한번에 획득될 있습니다. 배경색을 설정한 지금 안개를 만들 있습니다. 코드는 setWorldGeometry 이전에 호출되어야 함을 명심하세요 :

        mSceneMgr->setFog(FOG_LINEAR, fadeColour, 0.0, 50, 500);

첫번째 setFog 매개변수는 안개 종류( 경우는 linear)입니다. 두번째 매개변수는 안개에 쓰일 색상( 경우는 매우 옅은 회색 또는 C# "WhiteSmoke")입니다. 세번째 매개변수는 linear 안개방식에서는 쓰이지 않습니다. 네번째와 다섯번째 매개변수는 안개가 두터워질 범주를 설정합니다. 경우는 안개가 50에서 시작하여 500에서 끝납니다. 말은 카메라로부터 0 50사이에는 안개가 없으며 50부터 500까지는 선형적으로 두꺼워 집니다. 500 이상 떨어진 경우 안개때문에 아무것도 보이지 않습니다. 컴파일 하고 실행시켜보세요.

다른 타입은 exponential 안개입니다. 안개의 시작과 경계를 설정하는것 대신에 안개의 농도를 설정합니다(4, 5번째 매개변수는 안씁니다). 아까 setFog 함수내용을 내용으로 바꾸세요 :

        mSceneMgr->setFog(FOG_EXP, fadeColour, 0.005);

컴파일 실행시켜 보세요. DirectX Renderer 사용하신다면 안개때문에 아무것도 안보일 있습니다. 이때는 setFog 함수를 setWorldGeometry 다음에 호출하시면 해결됩니다. OpenGL Renderer 설명드렸던 처럼 동작합니다. 이건 안개가 생성되는것 마다 다르게 보입니다. 좀더 세밀한 exponential 안개함수도 있습니다(앞서 소개드린 함수보다 진하게 생성됩니다). FOG_EXP2 쓸때 진한 안개가 연출됩니다. 예전의 setFog 코드를 코드로 바꿔보세요 :

        mSceneMgr->setFog(FOG_EXP2, fadeColour, 0.003);

다시 컴파일하고 실행시켜 보세요. 오우거에서 제공하는 세가지 안개들은 손쉽게 교체가 가능합니다. 당신의 어플리케이션에서 세가지 안개함수들을 시험해 보시고 뭐가 가장 나아 보이는지 확인하세요.

 

안개와 하늘

SkyBox SkyDome 안개와 같이 출력할때 재미있는 문제점들에 봉착할 있습니다. SkyDome SkyBox 큐브형태이기 때문에 안개가 나타날때 원형표면에 대해 문제가 발생합니다. createScene 함수 내용을 삭제하세요. 만약 그럴싸하게 SkyDome 안개 매개변수를 선택한다면 문제점을 바로 확인할 있습니다.

        ColourValue fadeColour(0.9, 0.9, 0.9);

        mSceneMgr->setFog(FOG_LINEAR, fadeColour, 0.0, 50, 515);

        mWindow->getViewport(0)->setBackgroundColour(fadeColour);

        mSceneMgr->setWorldGeometry("terrain.cfg");

        mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8, 500);

컴파일하고 실행시켜보세요. 만약 카메라를 움직이면 바라보고 있는 SkyDome 부분이 안개에 의해 잘려나간 것을 있을것 입니다(중앙이 아닌 측면의 blue 색상으로 나타납니다) :



우리가 원하던 결과값이 아닙니다. 다른 방법은 SkyPlane 대신 사용하는 입니다. createScene 함수내용을 다음으로 바꿔주세요 :

        ColourValue fadeColour(0.9, 0.9, 0.9);

        mSceneMgr->setFog(FOG_LINEAR, fadeColour, 0.0, 0, 130);

        mWindow->getViewport(0)->setBackgroundColour(fadeColour);

 

        Plane plane;

        plane.d = 100;

        plane.normal = Vector3::NEGATIVE_UNIT_Y;

 

        mSceneMgr->setWorldGeometry("terrain.cfg");

 

        mSceneMgr->setSkyPlane(true, plane, "Examples/CloudySky", 500, 20, true, 0.5, 150, 150);

제대로 보이는군요. 위로 보면 정상적인 하늘이 보입니다(안개가 제대로 표시된다면 실제세계와 비슷한 화면입니다). 곡률을 적용해도 괜찮습니다. 방법은 수평선을 바라볼때 문제되는 SkyPlane 단점을 해결해 줍니다.

하늘의 일부분에만 안개를 적용하는 방법도 있습니다. 그러나 그렇게 하기 위해서는 하늘 텍스쳐를 위해 재질 스크립트 수정을 필요로 합니다.

이런 내용은 튜토리얼의 범주를 벗어납니다. 추후 특정재질을 위해 안개를 비활성화 시키시려면 여기 (http://www.ogre3d.org/docs/manual/manual_16.html#SEC64) 참조하세요.

 

안개를 어둠처럼 사용하기

안개를 설정하고 항상 하늘을 사용하지 않아도 됩니다. 왜냐하면 안개가 너무 짙으면 어쨋든 하늘은 안보이기 때문입니다. 지금까지 설명한 안개의 설명에 의하면 한정된 경우 멋진 그래픽트릭을 있게끔 해줍니다. 안개를 밝은 색상 대신에 매우 어두운 색상으로 만들면 어떻게 되는지 봅시다 (지금 작성한 코드의 SkyPlane 카메라와 겨우 10단위거리 밖에 떨어져 있지 않습니다.) :

        ColourValue fadeColour(0.1, 0.1, 0.1);

        mWindow->getViewport(0)->setBackgroundColour(fadeColour);

        mSceneMgr->setFog(FOG_LINEAR, fadeColour, 0.0, 10, 150);

 

        mSceneMgr->setWorldGeometry("terrain.cfg");

 

        Plane plane;

        plane.d = 10;

        plane.normal = Vector3::NEGATIVE_UNIT_Y;

 

        mSceneMgr->setSkyPlane(true, plane, "Examples/SpaceSkyPlane", 100, 45, true, 0.5, 150, 150);

컴파일하고 실행시켜 보세요. 이게 결과입니다 :


나쁘진 않군요. 물론 가능하다면 적절한 조명으로도 이런 효과를 있습니다. 그러나 방법은 안개의 유연한 기능을 보여주고 오우거엔진으로 있는 재미있는 기능이기도 합니다. 검은 안개는 FPS 게임에서 "시력약화" "암흑" 같은 마법 효과를 있는 흥미로운 기법이 수도 있습니다.

출처 : http://begin.pe.kr/category/Ogre3D%20삽질란/Basic%20Tutorial%203

신고
Posted by 우엉 여왕님!! ghostkyow

티스토리 툴바