'Ogre3D 삽질란'에 해당되는 글 50건

  1. 2011.02.08 OGRE 3D 1.7 Beginner’s Guide
  2. 2010.03.02 OGRE 1.7.0 Final Release 그리고 .. 2
  3. 2009.12.15 Ogre3D iPhone 3
  4. 2009.02.05 Ogre3D Tutorial 소스코드 모음입니다. 5
  5. 2009.01.15 중급 튜토리얼 7-1
  6. 2009.01.15 중급 튜토리얼 7-2
  7. 2009.01.15 중급 튜토리얼 7-3 (마지막)
  8. 2009.01.07 중급 튜토리얼 6-1
  9. 2009.01.07 중급 튜토리얼 6-2
  10. 2009.01.07 중급 튜토리얼 6-3 (마지막)

OGRE 3D 1.7 Beginner’s Guide

Ogre3D 삽질란 2011. 2. 8. 10:31




몰랐는데 1월에 새로운 Ogre3D 서적이 출간되었군요!

예전 책은 너무 버젼이 오래되서 읽기가 좀 꺼렸는데 이 책은 관심이 많이 가는군요.

튜토리얼로 부족한 기초지식을 채워줄 수 있지 않을까 하는 기대가 큽니다.

이 책으로 배울 수 있는 점들을 다음과 같이 소개하고 있습니다.

  • Learn the basics of OGRE 3D - (Ogre3D의 기초)
  • Understand the scene graph - (장면 그래프의 이해)
  • Develop 3D scenes with OGRE 3D - (Ogre3D를 통해 입체영상 연출하기)
  • Create complex scenes - (복잡한 장면 연출)
  • Write your own shaders and add them to scenes - (쉐이더 기법 활용)
  • Add lights and shadows - (조명과 그림자)
  • Add compositors to 3D scene for post-processing effects - (이펙트 기법)
  • Learn more about user control and animation - (좀 더 자세한 사용자 입력컨트롤 및 애니메이션 효과)
  • Extend OGRE 3D with plugins - (플러그인을 통한 Ogre3D 엔진 확장)
예제를 통해 단계적인 접근법을 사용한다고 합니다.
연습문제를 통해 실력향상을 유도한다고 하는군요.

좋은 읽을거리 소스가 생겨서 기분이 좋군요.

번역해서 출간한다면 과연 얼마나 팔릴까요..?

:

OGRE 1.7.0 Final Release 그리고 ..

Ogre3D 삽질란 2010. 3. 2. 21:24

사용자 삽입 이미지


OGRE 1.7.0 Final 버젼이 2월 28일자로 정식등록 되었습니다.
아직 인스톨버젼으로는 등록되지 않았지만 별로 문제될 사항은 아닌듯 합니다.

이렇게 계속 새로운 빌드가 나오는데 정작 개인적으로 해본건 없네요.
( 뭐가 바뀐건지 알아도 개인적으로는 큰 해당사항이 없다는게 참 힘빠지게 합니다. ㅠ )

하지만 이런 포스팅을 한 이유는


이번 공식홈피에서 흥미로운 사항을 언급했는데 다음과 같습니다.


Source releases and Windows SDKs are up now. SDKs for OS X, iPhone and MinGW, plus an Ubuntu PPA will follow soon, but in the meantime you can use the source releases if you want to get started.


네.

아이폰SDK 입니다.
( 솔직히 엄청 기대하는 중 입니다! 아마 고품질의 3D 어플 홍수가 일어날듯 합니다! )

OS X 용 SDK 는 3월 1일! 즉 어제날짜로 등록이 되었습니다!
맥이 한대 있긴 하지만 OS X 플랫폼은 그다지 매력적이지 않아서..
그런데 다시 생각해보니 OS X 플랫폼으로 미리 대비를 해놔야 할 것 같군요!


지금은 좀 바쁘지만 시간만 된다면...

아이폰 관련 내용이 나오는데로 정리(번역)해서 올려볼 생각입니다.


UDK 도 봐야 하는데 이거 원...
( 먹고살기 바쁩니다. ㅠㅠ )

:

Ogre3D iPhone

Ogre3D 삽질란 2009. 12. 15. 17:02

사용자 삽입 이미지
아이폰으로 Ogre3D 어플을 포팅할 날이 머지 않았군요.
자세한건 아래 링크로 따라가 보심 됩니다. ㅎㅎㅎ





http://www.3d-test.com/interviews/ogre3d_iphone_1.htm

:

Ogre3D Tutorial 소스코드 모음입니다.

Ogre3D 삽질란 2009. 2. 5. 09:20

Ogre3D Tutorial Source-Code 최종형태 묶음 project file 입니다.

Visual Studio 2008로 작성되었습니다.
다른 버젼을 사용하시는 분은 디렉토리별 소스코드를 개별적으로 참조해 주세요.

A1~A7 까지는 Advenced Tutorial 편이며
B1~B8 까지는 Basic Tutorial 편 입니다.

몇 개 튜토리얼은 결과물을 보기좋게 볼 수 있도록 ViewPoint나 특정 수치값이 조금 바뀐경우도 있습니다.


그리고 Decal_filter.png와 Decal.png는 Advenced Tutorial 6를 위한 파일입니다.
$(OGRE_HOME)\media\materials\textures 폴더로 붙여넣어 주세요.

 

:

중급 튜토리얼 7-1

Ogre3D 삽질란/Intermediate Tutorial 7 2009. 1. 15. 23:09

중급 튜토리얼 7 (번역 : n_Sys)

중급 튜토리얼 7: 텍스쳐에 렌더링하기

튜토리얼 진행에 있어서 문제가 생긴다면 Help Forum 문의하세요.

목차

                               1 소개

                                       1.1 초기코드

                               2 텍스쳐에 렌더링하기

                                       2.1 render texture 하기

                                       2.2 텍스쳐를 파일로 저장하기

                               3 미니스크린 구현하기

                                       3.1 소개

                                       3.2 하기

                                       3.3 부터 하기

                               4 RenderTargetListener

                                       4.1 소개

                                       4.2 RenderTargetListener 하기

                               5 RTTs and shaders

                                       5.1 RTT 이더 내기

                               6

 

소개

이번 튜토리얼에서는 텍스쳐에 렌더링 하는 기본기를 가르쳐 드릴 계획입니다. 기법은 셰이더를 써서 구현되는 모션블러와 같은 다양한 특수효과와 함께 사용됩니다.

텍스쳐로 렌더링("RTT")하는 기법은 단순한 원리입니다. 출력되는 렌더링 데이터를 렌더윈도우가 아닌 텍스쳐로 바로 보냅니다. 텍스쳐는 하드디스크상의 일반 텍스쳐로도 사용될 있습니다.

 

사용자 삽입 이미지

 

튜토리얼에 대한 코드는 여기 찾을 있습니다.

 

초기코드

프로젝트에 cpp파일을 하나 생성하고 다음 코드를 추가하세요 :

#include "ExampleApplication.h"

 

class RTTListener : public ExampleFrameListener

{

public:

   RTTListener(RenderWindow *win, Camera *cam, SceneNode *sn)

        : ExampleFrameListener(win, cam), mPlaneNode(sn)

   {

   }

 

   bool frameStarted(const FrameEvent& evt)

   {

        mPlaneNode->yaw(Radian(evt.timeSinceLastFrame));

              

        return ExampleFrameListener::frameStarted(evt);

   }

 

protected:

   SceneNode      *mPlaneNode;

};

 

class RTTApplication : public ExampleApplication

{

protected:

   MovablePlane   *mPlane;

   Entity         *mPlaneEnt;

   SceneNode      *mPlaneNode;

 

   void createScene()

   {

       // Set ambient light

       mSceneMgr->setAmbientLight(ColourValue(0.2f, 0.2f, 0.2f));

 

       // Create a light

       Light* l = mSceneMgr->createLight("MainLight");

       l->setPosition(20, 80, 50);

 

       // Position the camera

       mCamera->setPosition(60, 200, 70);

       mCamera->lookAt(0, 0, 0);

 

        // Create a material for the plane (just a simple texture, here grass.jpg)

       MaterialPtr mat = MaterialManager::getSingleton().create("PlaneMat", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

       TextureUnitState* t = mat->getTechnique(0)->getPass(0)->createTextureUnitState("grass_1024.jpg");

              

        // Create a simple plane

       mPlane = new MovablePlane("Plane");

       mPlane->d = 0;

       mPlane->normal = Vector3::UNIT_Y;

       MeshManager::getSingleton().createPlane("PlaneMesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,

           *mPlane, 120, 120, 1, 1, true, 1, 1, 1, Vector3::UNIT_Z);

       mPlaneEnt = mSceneMgr->createEntity("PlaneEntity", "PlaneMesh");

       mPlaneEnt->setMaterialName("PlaneMat");

 

       // Attach the plane to a scene node

       mPlaneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();

       mPlaneNode->attachObject(mPlaneEnt);

   }

 

   // Create a new frame listener

   void createFrameListener()

   {

       mFrameListener = new RTTListener(mWindow, mCamera, mPlaneNode);

       mRoot->addFrameListener(mFrameListener);

   }

};

 

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

#define WIN32_LEAN_AND_MEAN

#include "windows.h"

#endif

 

#ifdef __cplusplus

extern "C" {

#endif

 

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

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

#else

   int main(int argc, char **argv)

#endif

   {

       // Create application object

       RTTApplication app;

 

       try {

           app.go();

       } catch(Exception& e) {

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

           MessageBoxA(NULL, e.getFullDescription().c_str(),

               "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);

#else

           std::cerr << "An exception has occurred: " << e.getFullDescription();

#endif

       }

 

       return 0;

   }

 

#ifdef __cplusplus

}

#endif

컴파일 실행시켜보세요. Y축을 따라서 회전하는 단순한 평판이 보일 입니다.

 

사용자 삽입 이미지

 

:

중급 튜토리얼 7-2

Ogre3D 삽질란/Intermediate Tutorial 7 2009. 1. 15. 23:06

텍스쳐에 렌더링하기

render texture 생성하기

우선 텍스쳐생성부터 해야 합니다.

Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual("RttTex", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, mWindow->getWidth(), mWindow->getHeight(), 0, PF_R8G8B8, TU_RENDERTARGET);

첫번째 매개변수는 텍스쳐 이름인데 보통 RttTex 이름지어 집니다. 두번째는 리소스그룹, 세번째는 텍스쳐종류(지금은 2D 텍스쳐), 네번째와 다섯번째는 텍스쳐의 폭과 높이입니다. 그리고 밉맵의 수와 사용하게될 텍스쳐 포멧, 사용목적에 따른 flag값들을 설정해 줍니다. 텍스쳐포멧에는 매우 다양한 타입들이 존재합니다. 24비트 RGB 텍스쳐를 구성하는 가장 단순한 형태는 PF_R8G8B8 입니다. 만약 투명값을 가지는 알파채널이 필요하다면 PF_R8G8B8A8 값이 적당할 입니다.

몇가지 매개변수에 쓰일 정보값과 나중에 RenderTargetListener 넣을 현재 텍스쳐에 대한 render target 구해야 합니다.

Ogre::RenderTexture *renderTexture = texture->getBuffer()->getRenderTarget();

 

renderTexture->addViewport(mCamera);

renderTexture->getViewport(0)->setClearEveryFrame(true);

renderTexture->getViewport(0)->setBackgroundColour(ColourValue::Black);

renderTexture->getViewport(0)->setOverlaysEnabled(false);

render texture 구했다면 뷰포트를 추가시킬 차례입니다. RenderTexture 표현될 컨텐츠로 채워질 뷰포트 입니다. 뷰포트가 프레임마다 검은색으로 지워지도록 설정하고 뷰포트위에 아무것도 올라오지 않도록 하기위해서 오버레이속성을 비활성화 시킵니다.

 

텍스쳐를 파일로 저장하기

이제 여기서 한가지 검사를 하고 넘어가 봅시다. 방금전 앞에서 생성시켰던 RenderTexture 파일로 저장하는 입니다. RenderTexture클래스는 RenderTarget으로부터 파생되었기 때문에 내부컨텐츠를 파일로 저장시키는 함수사용이 가능합니다(RenderWindow에서도 똑같이 적용됩니다). 파일로 저장시키기전에 RenderTexture 업데이트 시켜줘야 함을 유의하세요. update() 함수를 사용하거나 setAutoUpdate() 함수를 호출하여 자동으로 업데이트가 수행되도록 있습니다.

// Either this way

renderTexture->setAutoUpdated(true);

// or this way

renderTexture->update();

renderTexture->writeContentsToFile("start.png");

프로그램을 실행하고나면 exe파일이 위치한 디렉토리에 png확장자를 가진 파일이 보일 입니다. 파일은 화면상에 보여졌던 컨텐츠를 담고 있습니다(이번에 사용되어졌던 평면텍스쳐입니다).

 

미니스크린 구현하기

간략한 소개

프로그램상에서 화면 오른쪽 하단에 작은 미니스크린을 구현할 차례입니다. Rectangle2D 장면에 추가하여 텍스쳐로 생성했던 RenderTexture 출력하도록 만듭니다. 결과적으로 같은장면을 2 보게 됩니다: 한번은 평소처럼 RenderWindow 출력하고 두번째는 Rectangle2D위에 텍스쳐로 출력합니다.

방법을 통해서 게임속에서의 TV화면(또는 비슷한) 구현이 가능합니다. 레벨의 어느 부분에 카메라를 배치하고 앞에서 소개드린 방법처럼 RenderTexture 생성한 다음 그것을 TV화면에 출력시키면 됩니다.

 

미니스크린용 사각영역 설정하기

Ogre::Rectangle2D 생성은 무척 간단합니다:

Ogre::Rectangle2D *miniScreen = new Ogre::Rectangle2D(true);

miniScreen->setCorners(0.5, -0.5, 1.0, -1.0);

miniScreen->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));

첫번째 라인에서 텍스쳐좌표 속성값을 true 설정합니다. 그리하여 나중에 사각형에 텍스쳐를 맵핑할 있게 됩니다. 두번째 라인에서는 사각형의 꼭지점 좌표를 설정합니다. 왼쪽은 -1.0, 오른쪽은 +1.0, 상단은 +1.0, 하단은 -1.0입니다. 그래서 사각형은 결과적으로 프로그램용 윈도우의 오른쪽 하단에 위치하게 됩니다. 그리고 사각형에 엄청나게 바운딩박스를 적용시켜 사각형의 장면노드를 바라보지 않더라도 항상 그려질 있도록 만듭니다. 이렇게 수동으로 크기를 설정하는 대신에 AxisAlignedBox::setInfinite() 사용해도 됩니다. 하지만 과거에 버그가 있던던 사례가 있었습니다. 이렇게 수동으로 박스를 설정하는것이 가장 안정된 방법입니다.

이제 미니스크린용 사각형이 생성되었습니다. 이제 SceneNode attach 차례입니다. 별로 생소한 코드는 없습니다.

Ogre::SceneNode *miniScreenNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode");

miniScreenNode->attachObject(miniScreen);

시점에서 실행시키면 프로그램 윈도우의 오른쪽 하단에 흰색 사각형이 자리잡고 있음을 있을 입니다.

사용자 삽입 이미지


재료들로부터 재질 생성하기

다음단계는 앞에서 생성했던 RenderTexture 출력하는 입니다. 이제 재질을 생성해야 합니다. 2가지 방법이 있는데 재질스크립트를 사용하거나 실행도중에 코드로 직접적으로 생성시키는 방법이 있습니다. 마지막 함수는 필요한 모든것을 하나의 파일에서 완료시키기 위해 호출되어질 입니다.

MaterialPtr material = MaterialManager::getSingleton().create("RttMat", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

Ogre::Technique *technique = material->createTechnique();

technique->createPass();

material->getTechnique(0)->getPass(0)->setLightingEnabled(false);

material->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex");

첫번째 라인은 재질을 생성하고 technique pass 2줄에 걸쳐서 추가합니다. 세번째 라인은 미니스크린에서 실제 텍스쳐가 색상이 어둡게 보이는 것을 방지하기 위해서 조명효과를 비활성화 시킵니다. 마지막 라인은 미리 생성해 두었던 RenderTexture 이용해 새로운 TextureUnitState 생성합니다. 이제 재질을 미니스크린으로 적용시킬 준비가 되었습니다.

miniScreen->setMaterial("RttMat");

실행시켜보면 예측하지 못한 결과가 보일 입니다: 미니스크린안에 미니스크린이 들어있습니다! 이를 해결하기위해 RenderTargetListener 소개합니다.

 

RenderTargetListener 클래스의 사용

간략한 소개

대부분의 경우 RTT위에는 장면상의 몇몇 객체들만 표시될 입니다. 지금 하려고 하는 경우에는 화면상에서 미니스크린이 아직 표시되지 않은상태의 화면, 미니스크린에 표시될 하나의 텍스쳐만 필요합니다. 그렇기 때문에 화면이 RenderTexture 저장되기 전에 미니스크린을 숨겨줘야 합니다. 바로 이러한 역할을 RenderTargetListener 담당합니다. RenderTargetListener클래스는 2개의 중요한 함수를 가지고 있습니다: preRenderTargetUnpdate() postRenderTargetUpdate()입니다. 함수 이름에서 추측할 있듯 첫번째 함수는 RenderTexture 채워지기 전에(여기서 미니스크린을 숨길 있습니다) 자동으로 호출되는 반면 두번째 함수는 RenderTexture 채워진 이후에 호출됩니다(여기서 미니스크린을 다시 보이게 합니다).

 

RenderTargetListener 구현하기

RenderTargetListener 구현하는건 간단합니다. 우선은 application class RenderTargetListener클래스로부터 상속받게끔 하여 자체적으로 listener 포함하게끔 만듭니다. 다음에 pre- postRenderTargetUpdate() 함수를 이용해서 미니스크린을 켜고 끕니다. 그러고 나면 어플리케이션 클래스는 기본적으로 다음의 형태를 띄게 됩니다 :

class RTTApplication : public ExampleApplication, public RenderTargetListener

{

protected:

   SceneNode           *mPlaneNode;

   Rectangle2D         *mMiniScreen;

 

   void createScene()

   {

       [...]

   }

 

   void createFrameListener()

   {

       [...]

   }

 

   void preRenderTargetUpdate(const RenderTargetEvent &evt)

   {

        mMiniScreen->setVisible(false);

   }

 

   void postRenderTargetUpdate(const RenderTargetEvent &evt)

   {

        mMiniScreen->setVisible(true);

   }

};

이제 마지막단계인 RenderTexture listener 추가하는 일이 남았습니다. 어플리케이션 클래스가 RenderTargetListener에서 상속되었으므로 매개변수로 넘기는 것이 가능합니다.

renderTexture->addListener(this);

되었습니다. 이제 프로그램에 미니스크린이 추가되었습니다. 간단한 형태입니다.

 

사용자 삽입 이미지

:

중급 튜토리얼 7-3 (마지막)

Ogre3D 삽질란/Intermediate Tutorial 7 2009. 1. 15. 22:36

RTTs and shaders

RTT 셰이더 보내기

RTT 종종 셰이더와 함께 사용됩니다. 그렇기에 RenderTexture 전달방법에 대해서 알아둘 필요가 있습니다. 걱정마세요. 무척이나 간단합니다.

가장 단순한 예를 들자면 셰이더를 위한 텍스쳐가 실행시간동안 한번도 바뀌지 않는경우 입니다. 텍스쳐를 바꿀 필요가 없을경우 재질스크립트의 이름만 알려주면 됩니다. 이번 예제에서 쓰인 경우는 RttTex입니다. 재질 속성파일에서의 texture_unit 속성은 다음처럼 되어야 합니다 :

texture_unit

{

    texture RttTex

}

만약 셰이더에 사용되는 텍스쳐가 바뀌게 된다면 다음의 2줄을 추가해 주세요 :

Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().getByName("Sepia");

material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("OtherRttTex");

첫번째 라인에서 새로 사용하고싶은 재질에 대한 포인터를 구하고(위에서 사용된 경우는 Sepia 셰이더 재질입니다) 두번째라인에서 텍스쳐이름을 적당한 이름으로 바꿔줍니다.

앞에서 설명드린 2가지 방법중 하나로 재질 스크립트내부에서 올바른 텍스쳐이름을 설정했다면 다음라인을 통해서 cg셰이더텍스쳐에 접근이 가능해 집니다:

uniform sampler2D SceneSampler : register(s0)

마무리 지어졌습니다. 미니스크린속의 텍스쳐는 셰이더효과를 통해서 다음과 같은 형태로 보일 입니다(sepia 셰이더 효과):

사용자 삽입 이미지

 

결론

RTT 시작하기위한 기초적인 내용이었습니다. 코드로 부터 차근차근 단계를 쌓아보고 그래픽효과에 대한 새로운 세상으로 도전해 보세요.

:

중급 튜토리얼 6-1

Ogre3D 삽질란/Intermediate Tutorial 6 2009. 1. 7. 13:58

중급 튜토리얼 6 (번역 : n_Sys)

중급 튜토리얼 6: 데칼 투영하기(Projective Decals)

튜토리얼 진행에 있어서 문제가 생긴다면 Help Forum 문의하세요.

목차

                               1 소개

                               2 시작하기

                                       2.1 스쳐

                                       2.2 코드

                               3 데칼 투영하기

                                       3.1 절두체

                                       3.2 재질 변경

                                       3.3 함수호출

                               4 뒷면투영현상 거하기

                                       4.1 소개

                                       4.2 하기

                                       4.3 재질 하기

                               5 하게 하기

                                       5.1

                                       5.2 Field of View 하기

                               6 마디

 

소개

이번 튜토리얼에서는 객체에 투영된 데칼을 장면속에 추가하는 방법을 다룹니다. 지면상의 표시점이나 조준점 또는 뭔가에 투영되어 표시되는 데칼을 표시해야 텍스쳐를 투영시키는 방법이 유용하게 쓰입니다(스플래팅처럼 목표객체가 영구히 바뀌지는 않습니다). 조준점이 투영된 오우거머리의 스크린 입니다 :



튜토리얼에 대한 코드는 여기 찾을 있습니다. 내용을 천천히 진행하면서 완성되어지는 결과물을 직접 확인하세요.

 

 

시작하기

새로운 텍스쳐

프로젝트를 시작하기전에 앞으로 사용하게될 2개의 이미지를 추가해야 합니다. 다음 2개의 그림파일 링크를 오른버튼 클릭으로 오우거가 참조할 있는 위치에 저장하세요 : decal.png decal_filter.png

제일 무난한 위치는 media/materials/textures 폴더입니다(대부분 사람들의 OgreSDK 포함되어 있을 입니다).

초기 코드

프로젝트에 cpp파일을 하나 생성하고 다음 코드를 추가하세요 :

#include "ExampleApplication.h"

 

// A FrameListener that gets passed our projector node and decal frustum so they can be animated

class ProjectiveDecalListener : public ExampleFrameListener

{

public:

    ProjectiveDecalListener(RenderWindow* win, Camera* cam, SceneNode *proj, Frustum *decal)

        : ExampleFrameListener(win, cam), mProjectorNode(proj), mDecalFrustum(decal), mAnim(0)

    {

    }

 

    bool frameStarted(const FrameEvent& evt)

    {

        return ExampleFrameListener::frameStarted(evt);

    }

 

protected:

    SceneNode *mProjectorNode;

    Frustum *mDecalFrustum;

    float mAnim;

};

 

class ProjectiveDecalApplication : public ExampleApplication

{

protected:

    SceneNode *mProjectorNode;

    Frustum *mDecalFrustum;

    Frustum *mFilterFrustum;

 

    void createScene()

    {

        // Set ambient light

        mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));

 

        // Create a light

        Light* l = mSceneMgr->createLight("MainLight");

        l->setPosition(20,80,50);

 

        // Position the camera

        mCamera->setPosition(60, 200, 70);

        mCamera->lookAt(0,0,0);

 

        // Make 6 ogre heads (named head0, head1, etc.) arranged in a circle

        Entity *ent;

        for (int i = 0; i < 6; i++)

        {

            SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();

            ent = mSceneMgr->createEntity("head" + StringConverter::toString(i), "ogrehead.mesh");

            headNode->attachObject(ent);

            Radian angle(i * Math::TWO_PI / 6);

            headNode->setPosition(75 * Math::Cos(angle), 0, 75 * Math::Sin(angle));

        }

    }

 

    // The function to create our decal projector

    void createProjector()

    {

    }

 

    // A function to take an existing material and make it receive the projected decal

    void makeMaterialReceiveDecal(const String &matName)

    {

    }

 

    // Create new frame listener

    void createFrameListener(void)

    {

        mFrameListener= new ProjectiveDecalListener(mWindow, mCamera, mProjectorNode, mDecalFrustum);

        mRoot->addFrameListener(mFrameListener);

    }

};

 

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

#define WIN32_LEAN_AND_MEAN

#include "windows.h"

#endif

 

#ifdef __cplusplus

extern "C" {

#endif

 

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

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

#else

    int main(int argc, char **argv)

#endif

    {

        // Create application object

        ProjectiveDecalApplication app;

 

        try {

            app.go();

        } catch(Exception& e) {

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

            MessageBoxA(NULL, e.getFullDescription().c_str(),

                "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);

#else

            std::cerr << "An exception has occurred: " << e.getFullDescription();

#endif

        }

 

        return 0;

    }

 

#ifdef __cplusplus

}

#endif

컴파일 실행시켜보세요. 6개의 오우거머리가 보일것입니다.

 


:

중급 튜토리얼 6-2

Ogre3D 삽질란/Intermediate Tutorial 6 2009. 1. 7. 13:56

데칼 투영하기

절두체

절두체는 near far 끝점으로 실제로 보여지는 공간을 피라미드형태로 표시합니다. 오우거에서는 카메라와 함께 사용되어 출력하는데 이용됩니다(카메라 클래스는 Frustum 클래스로부터 상속받습니다). 튜토리얼에서는 데칼을 화면상의 메쉬로 투영시키는데 절두체가 사용될 입니다.

프로젝터를 생성하기위해 첫번째로 해야 일은 사용될 절두체를 생성하고 SceneNode attach하는 입니다. createProjector함수에 다음코드를 추가하세요 :

       mDecalFrustum = new Frustum();

       mProjectorNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("DecalProjectorNode");

       mProjectorNode->attachObject(mDecalFrustum);

       mProjectorNode->setPosition(0,5,0);

이렇게 만들어진 프로젝터는 필름영사기와 유사하게 멀리갈수록 데칼 크기가 커지는 형태입니다. 거리에 상관없이 일정한 데칼의 크기, 모양을 유지하도록 생성시키고 싶다면 다음 코드를 추가하면 됩니다(하지만 지금은 그렇게 하지마세요) :

       // Do not add this to the project

       mDecalFrustum->setProjectionType(PT_ORTHOGRAPHIC);

       mDecalFrustum->setNearClipDistance(25);

직교성 절두체의 field of view, 화면비율, near clip 거리를 설정하여 프로젝터가 떨어진 거리와는 상관없이 일정한 크기의 데칼이 표시되므로 적절한 크기와 형태를 사전에 예측해야 합니다.

진행하기전에 여기서 절두체가 어디로 데칼을 투영하며 비추고 있는지를 알아두세요. 프로그램에서는 형태로 오우거머리가 나열되어 있고 중앙에 절두체가 위치하며(5 unit거리만큼 살짝 떨어져 있긴 합니다) -Z방향을 바라보고 있습니다(방향을 따로 바꾸지 않은 기본값입니다). 최종적으로 데칼이 오우거머리의 뒷면을 투영하게 됩니다.

 

재질 변경

객체에 데칼이 보여지기 위해서는 객체가 데칼을 받을 있도록 되어야 합니다. 일반적인 텍스쳐위에 데칼이 그려지는 과정을 새로 하나 추가함으로써 구현합니다. 절두체는 투영될 데칼의 위치, 크기, 모양을 결정합니다. 데모에서는 데칼을 받을 있도록 객체의 재질을 직접적으로 수정을 가할 이지만 대부분의 실제 프로그램에서는 원본재질의 사본을 따로 보관해둠 으로써 원래재질로 되돌릴 있도록 해야 합니다.

가장먼저 해야 일은 재질 포인터를 얻고 재질처리단계를 하나 추가합니다. makeMaterialReceiveDecal함수를 찾아서 다음코드를 추가하세요 :

       MaterialPtr mat = (MaterialPtr)MaterialManager::getSingleton().getByName(matName);

       Pass *pass = mat->getTechnique(0)->createPass();

처리단계가 추가되었습니다. 이제 블렌딩과 조명에 대한 설정을 해야 합니다. 객체에 입혀진 기존의 텍스쳐와 혼합된 형태의 새로운 텍스쳐가 추가되어야 합니다. Scene blending Transparent alpha 설정시켜주고 depth bias 1 설정합니다( 데칼은 투명처리가 되지 않습니다). 마지막으로 조명을 disable 시켜줌으로써 장면상의 조명값에의해 재질이 변함없이 보여질 있도록 합니다. 만약 데칼이 조명의 영향을 받도록 설정하고 싶다면 마지막줄 함수호출을 실행하지 않으면 됩니다 :

       pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);

       pass->setDepthBias(1);

       pass->setLightingEnabled(false);

decal.png 이미지를 이용하여 새로운 텍스쳐상태를 생성합니다. 그리고 두번째 함수는 텍스쳐투영을 활성화시키고 생성된 절두체를 입력받습니다. 마지막 2 함수들은 필터링과 어드레싱모드를 설정합니다 :

       TextureUnitState *texState = pass->createTextureUnitState("decal.png");

       texState->setProjectiveTexturing(true, mDecalFrustum);

       texState->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

       texState->setTextureFiltering(FO_POINT, FO_LINEAR, FO_NONE);

어드레싱모드를 clamp 바꾸면 데칼이 객체위에 반복되어 나타나는걸 방지할 있습니다. 필터링옵션으로는 확대시 기본선형(standard linear)으로, 축소시에는(FO_POINT), 밉매핑시에는 아무런 옵션도 사용되지 않습니다. 이러한 옵션은 데칼이 최소화되었을때 데칼의 외곽경계선부분(투명색) 흐릿해지는것을 방지해 줍니다. 이러한 옵션을 사용하지 않는다면 데칼이 투영된 바깥쪽이 무척 지저분해 보일 입니다.

이것으로 재질에 필요한 설정은 모두 끝났습니다.

 

함수호출

재질과 프로젝터를 설정하는 함수가 완성되었습니다. 설정을 실제로 적용시키기 위해서는 호출되어야 합니다. 다음 코드를 createScene멤버함수 마지막부분 추가하세요 :

       createProjector();

       for (unsigned int i = 0; i < ent->getNumSubEntities(); i++)

           makeMaterialReceiveDecal(ent->getSubEntity(i)->getMaterialName());

이전루프에서 ent변수에 오우거머리 엔티티를 이미 저장해뒀습니다. 사용되는 모든 오우거머리들은 동일한 재질이 사용되므로 랜덤하게 하나의 객체를 잡아서 그에 해당하는 재질이름을 얻어내기만 하면 됩니다.

컴파일 실행시켜보세요. 데칼이 투영된 오우거머리 몇개가 보일겁니다.

 

뒷면투영현상 제거하기

소개

프로그램을 실행시켰을때 눈치채셨을지도 모르겠습니다. 실제로는 2개의 데칼이 투영되었습니다. 하나는 절두체가 바라보는 -Z방향으로, 다른하나는 절두체의 뒷면인 +Z방향으로 오우거 머리를 투영하고있습니다. 이렇게 보이는 이유는 절두체의 정면으로 투영될때 절두체의 뒷면으로도 (반전된)데칼이 반응하기 때문입니다.

절대로 이런 결과를 원하지는 않습니다. 잠시후 뒷면투영현상을 제거하기위해 필터에 대해 소개드릴 입니다.

 

프로젝터 수정하기

뒷면투영현상을 걸러내기위해서 보이는방향만을 보여지게끔 필터기능을 가진 새로운 절두체가 필요합니다. createProjector멤버함수에 다음코드를 추가하세요 :

       mFilterFrustum = new Frustum();

       mFilterFrustum->setProjectionType(PT_ORTHOGRAPHIC);

       SceneNode *filterNode = mProjectorNode->createChildSceneNode("DecalFilterNode");

       filterNode->attachObject(mFilterFrustum);

       filterNode->setOrientation(Quaternion(Degree(90),Vector3::UNIT_Y));

특별하게 새로운 코드는 보이지 않습니다. 이전코드와 다른점이 있다면 노드가 뒤로 바라보게끔 90 회전한 뿐입니다.

 

재질 수정하기

재질에 추가시킨 텍스쳐 처리단계에 또다른 텍스쳐상태를 추가시켜야 합니다. MakeMaterialReceiveDecal 다음코드를 추가하세요 :

       texState = pass->createTextureUnitState("decal_filter.png");

       texState->setProjectiveTexturing(true, mFilterFrustum);

       texState->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

       texState->setTextureFiltering(TFO_NONE);

이전코드와 차이점이 없습니다. 절두체필터, 텍스쳐필터를 사용하고 필터링기능을 껐습니다. 이제 실행시켜보세요. 이제 정면으로 투영된 데칼만 보일 입니다.

 

화려하게 투영하기

간단한 회전

투영을 화려하게 보이게 하기 위하여 프로젝터를 회전하고 Field of View 갱신할 입니다. 다음코드를 frameStarted멤버함수에 추가하여 프로젝터를 회전시킵니다 :

       mProjectorNode->rotate(Vector3::UNIT_Y, Degree(evt.timeSinceLastFrame * 10));

실행시켜 보세요. 원으로 배치된 오우거머리를 따라돌며 데칼이 투영됨을 있을 입니다.

 

Field of View 수정하기

프로젝터의 field of view 수정해 봅시다. Orthographic(직교성) 프로젝터를 사용하지 않았으므로 field of view값을 조절하여 투영되는 객체의 사이즈를 늘리거나 줄일 있습니다. 보여지기 위해서 FOVy (field of view Y)값이 15~25 사이의 각도값이 되어야 합니다. 다음의 코드는 데칼의 사이즈를 늘리거나 줄이게 됩니다(frameStarted멤버함수에 추가하세요) :

       mAnim += evt.timeSinceLastFrame / 2;

       if (mAnim >= 1)

           mAnim -= 1;

 

       mDecalFrustum->setFOVy(Degree(15 + Math::Sin(mAnim * Math::TWO_PI) * 10));

이제 실행시켜 보세요.

:

중급 튜토리얼 6-3 (마지막)

Ogre3D 삽질란/Intermediate Tutorial 6 2009. 1. 7. 13:52

마지막 한마디

데칼에 대해서 마지막으로 한가지 드리고 싶은 말씀은 만약 프로그램상에서 데칼을 사용할 계획이라면 데칼의 외곽 경계선 부분의 픽셀들은 반드시 완전한 투명값(zero alpha) 되어야 합니다. 그렇지 않으면 텍스쳐 클램핑작업으로 인해 데칼이 지저분해 보일 입니다.

: