블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2731)
Unity3D (814)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (57)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (51)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
03-29 07:22

겜브리오의 Frame Render Sytstem 에서는 랜더클릭별로 알파프로세스를 지정해 줄 수 있다.

구조를 설명하자면.. 각 Mesh들은 랜더클릭의 랜더링 함수가 호출될때 클릭별로 설정된 CullingProcess에 의하여 보여지는 영역들에 대한 메쉬들의 집합을 구한다. 이 RenderObject들의 리스트(NiVisibleArray)를 가지고 랜더링을 하게되는데 이것은 SceneGraph상의 순서(생성순, 노드어태치순)으로 일괄적으로 랜더링되며 AssetViewer나 NiApplication에서는 NiAlphaSortProcessor를 사용한다. 이것을 연결하지 않을시 디폴트로된 기본 솔트프로세스가 연결되어지는데 이건 그냥 순서대로 그리는것이다.

NiAlphaSortProcessor를 보면 NiBackToFrontSortProcessor를 상속하게 되는데 위에 불투명한랜더링객체(알파가 없는, NiSortedAdjustNOde가 적용된)를 우선적으로 그리고, 알파가 있는 랜더링 객체를 기본적으로 Mesh의 피봇중심(BoundCenter)과 카메라와의 거리(ZBuffer)을 이용하여 뒤에서부터 앞으로 정렬하여 나온 NiVisibleArray의 내용을 그린다.

하지만 위와같은 랜더링시 문제점도 있어서

1) 알파텍스쳐가 쓰인 큰오브젝트(폭포, 스카이박스)의 경우 폭포의 피봇중심과 그 폭포앞의 오브젝트들(폭포앞물튐파티클등)이 서로 카메라의 위치에 따라 혹은 폭포와 스카이박스피봇와의 거리차등..의 문제로 인해서 앞뒤판정이 실제와 차이나게 생길수있고

2) 알파를 적용한 빌보드와 파티클이 같이 나오는 경우 파티클이 뒤에서 빌보드를 통과한다거나 앞에서 뒤로 빌보드를 통과 하거나 혹은 빌보드와 근접시.. 카메라의 위치에 따라 잘못판단되는 경우가 생길수있다.
예) 두장의 알파빌보드를 근접하여 놓았을경우 카메라 방향에 따라 앞뒤면이 잘못 나올수있다.

3) NiSortAdjustNode를 썼을 경우에도 불투명 오브젝트로 처리하게 되니 만약 NiSortAdJustNode 뒤에 불투명한 오브젝트가 있고 그것이 나중에 랜더링 된다면 이 NiSortAdjustNode를 쓴 알파오브젝트에는 실제로 뒤에 오브젝트가 나오지 않게 될 것이다.
예) NiSortAdjustNode를 쓴 폭포뒤에 불투명한 동굴이 있다고 쳤을때 실제로 어태치된 순서가 동굴이
나중에 어태치 되어있다면 동굴은 폭포수에 그려지지 않을 것이다.

위와 같은 문제를 해결하기 위해선 디자이너들이 알파에 대한 정렬 프로세스를 확실히 이해 한 상태에서 작업을 해야 한다는것이다.

파티클이나 빌보드의 경우 겹쳐저도 상관없는 경우 ZTest만 하고 ZWrite는 하지 않게 하여 (Zmode10), 테스트를 하여 투명우산 앞에 그릴지 뒤에 그릴지를 판단하고 그려질땐 Zbuffer를 쓰지 않아 같은 파티클의 경우 섞이게 만들고. 넓은 반투명 빌보드의 겹침현상은 기본적으로 두개의 오브젝트의 피봇중심이 가까워서 일어나는 현상임으로 이런경우는 실제피봇중심만 거리를 두게끔 처리함으로서 해결할수 있을 것이다. 이렇게 되어도 카메라의 거리에 따라 문제가 생길수 있는 부분은 존재하는데 확실히 랜더링 순서를 알고있는 메쉬집합체의 경우 깊이를 쓰는 부분에서 순서대로 깊이를 판단해서 NiVisibleArray에 넣어 주어 랜더링 하는 방법이 있는데

나의 경우에는 디자이너와 협의하여 순서를 확실히 아는 오브젝의 경우 Aset_이라는 이름으로 판단하였다.

아래는 사용중인 CustomAlphaSortProcessor 의 핵심 부분이다.


void NiCustomAlphaSortProcessor::PreRenderProcessList(const NiVisibleArray* pkInput, NiVisibleArray& kOutput, void* pvExtraData)
{
if (!pkInput) return;

NiRenderer* pkRenderer = NiRenderer::GetRenderer();
NIASSERT(pkRenderer);

NiPoint3 kWorldLoc, kWorldDir, kWorldUp, kWorldRight;
NiFrustum kFrustum;
NiRect<float> kViewport;
pkRenderer->GetCameraData(kWorldLoc, kWorldDir, kWorldUp, kWorldRight,
kFrustum, kViewport);

const unsigned int uiInputCount = pkInput->GetCount();

if (m_uiAllocatedDepths < uiInputCount)
{
NiFree(m_pfDepths);
m_pfDepths = NiAlloc(float, uiInputCount);
m_uiAllocatedDepths = uiInputCount;
}


NiSortedObjectList kItems0;

unsigned int uiDepthIndex = 0;

bool bSet = false;
float f;
for (unsigned int ui = 0; ui < uiInputCount; ui++)
{
NiRenderObject& kMesh = pkInput->GetAt(ui);

// NiSortAdjustNode인 경우
if( !kMesh.GetSortObject() ) // NiSortAdjustNode는 알파로 처리하되.. 알파보다는 먼저 랜더링 되게 변경.
{
kItems0.AddTail(&kMesh);
}
else if (IsTransparent( kMesh ) )
{
NiNode * pkParent = kMesh.GetParent();
NiFixedString name = kMesh.GetName();
if( name.Contains("Aset_") || ( pkParent && pkParent->GetName().Contains("Aset_") ) )
{
kOutput.Add(kMesh);

if( bSet == false )
{
f = ComputeDepth(kMesh, kWorldDir);
m_pfDepths[uiDepthIndex++] = f;
}
else
{
f = f-0.1f;
m_pfDepths[uiDepthIndex++] = f;
}

bSet = true;
}
else
{
bSet = false;
kOutput.Add(kMesh);
m_pfDepths[uiDepthIndex++] = ComputeDepth(kMesh, kWorldDir);
}


}
else
{
// 불투명한 오브젝트는 바로그린다. (NoSort 포함);
NiAVObject* pkAVObj = &kMesh;
if (NiIsKindOf(NiRenderObject, pkAVObj))
{
// FOutputLOG( (char *)(const char *) kMesh.GetName() );
kMesh.RenderImmediate(pkRenderer);
}

}

}

// NiSortAdjustNode는 불투명랜더링이 끝나면 이것도 바로 랜더링
while (kItems0.GetSize())
{
NiRenderObject* pkGeom = kItems0.RemoveHead();
pkGeom->RenderImmediate(pkRenderer);
}

//

SortObjectsByDepth(kOutput, 0, kOutput.GetCount() - 1);

/* // 로그를 남겨보자..
FOutputLOG("====알파만 걸러서 순서가 어뜨케 되나..=====================");
for(int i = 0; i<kOutput.GetCount(); i++)
{
NiRenderObject& kMesh = kOutput.GetAt(i);
FOutputLOG((char*)(const char*)kMesh.GetName());
}
*/


}

반응형

'Gamebryo > Lecture' 카테고리의 다른 글

Mesh의 생성 ( Particle, 검궤적 등 )  (0) 2011.11.08
게임브리오 2D Line관련  (0) 2011.10.30
무기잔상효과  (0) 2011.02.08
캐릭터 기울기 연산  (0) 2011.02.08
Gamebryo 셋팅  (1) 2011.01.06
Posted by blueasa
, |

<NiFont를 생성시킬 때 나온 메세지>

 

NiRenderer WARNING: NiDX9Renderer::Do_RenderMesh> Zero primitive count in submesh 0 of NiRenderObject '(null)' pointer: 23fba74, skipping render.

 

NiFont 에서 폰트로딩시 텍스쳐를 자체적으로 만드는데, 텍스쳐사이즈 2048*2048 이 넘어가는 거면, 텍스쳐이미지를 더 생성시킨다.

텍스쳐이미지가 1장일때 저 메시지가 안나온다...;;

텍스쳐이미지가 2장이상일때, PrimiviteCount가 NULL 값이 나오는데, NULL값이 나와서 Warnning이 뜨는거다...

2장이상일때는 특별한 처리가 필요할 듯하다...


 
[출처] 게임브리오 Do_RenderMesh() Warnning Error|작성자 나루

반응형

'Gamebryo > Bug Report' 카테고리의 다른 글

[버그리포팅] Attach/Detach 문제..  (0) 2010.06.21
Posted by blueasa
, |

HLSL로 작성된 셰이더 파일을 컴파일/디버깅 하는 프로그램으로는

RanderMonkey나 FX Composer 등이 존재한다.

하지만 아무래도 사용하기 불편한게 사실이다.

input으로 들어가는 변수나 리소스들을 일일이 매핑해줘야 하는 것도 그렇고,

그렇게 작성된 셰이더 파일을 다시 내가 작업하는 IDE 툴로 가져오는 것도

귀찮은 일이다.

이럴 때 내가 사용하는 작업환경이 Visual Studio 2005, 또는 Visual Studio 2008 이라면

External Tool ( 외부 도구 )를 사용해서 편하게 셰이더 파일을 컴파일/디버깅 할 수 있다.

아래와 같이 'Tools' 메뉴에 있는 External Tool을 클릭하자.




그리고는 'Add'를 눌러서 새로운 External Tool을 하나 만든 다음에 아래와 같이

Command에는 fxc.exe 파일의 경로를 넣어주자.

(fxc.exe는 ms에서 제공하는 셰이더 파일 컴파일러이다. )

( 내가 설치한 DirectX SDK 폴더 경로 )\Utilities\bin\x86\fxc.exe

그리고 Arguments에는 아래와 같이 넣어주자.

물론 옵션은 자기가 넣고 싶은 걸로 바꿀 수 있다.

주의할 사항이 있는데 맨 앞의 '/'앞에 한 칸 띄어야 하고, '/Tfx_4_0' 뒤에도

한 칸 띄어야 한다는 것이다. ^^

/Tfx_4_0 "$(ItemPath)"





출처 : 
http://gigaboy.egloos.com/10732591

반응형

'Gamebryo > Shader' 카테고리의 다른 글

알파블렌딩 렌더 설정  (0) 2011.07.22
알파 텍스쳐 블렌딩 공식  (0) 2011.07.22
[펌] Soft Particle (Depth bias blend)  (0) 2011.06.15
쉐이더  (0) 2011.04.04
HDR  (0) 2011.04.04
Posted by blueasa
, |
로그 메씨지 & 메씨지박스출력
NiMessageBox::DisplayMessage("MOUT::CreateScene -- W../res/data/script/model.xm Loading script Failed","script error");
본 & 스키닝 구조정리
- NiSkiningInstance
NiAVObject *const* GetBones() : 본의 포인터배열 얻기
본도 오브잭트로 여긴다. 위치정보를가진 일종에 더미로 여긴다.노드와 비슷하나 자식을가지지는 못하는..
그러나 여기서 본의 갯수는알수가없다.
그래서...
이런식으로 스킨데이터를얻어온다.
NiSkinData* pkOldSkinData = spOldSkinInstance->GetSkinData();
- NiSkinData
스킨데이터에서 본의 갯수를알수있다.
pkOldSkinData->GetBoneCount()
본의 정점 링크정보를 얻기
NiSkinData::BoneData* pkOldBoneData = pkOldSkinData->GetBoneData();
본데이터를 카피하는코드의예

for(i=0;i<pkOldSkinData->GetBoneCount();i++)
{
ppkNewBones[i] = spOldSkinInstance->GetBones()[i];
pkNewBoneData[i].m_kBound = pkOldBoneData[i].m_kBound; //본의위치정보계산용
pkNewBoneData[i].m_kSkinToBone = pkOldBoneData[i].m_kSkinToBone; //???
pkNewBoneData[i].m_usVerts = pkOldBoneData[i].m_usVerts; //본에의해 영향을받는 버텍스갯수
pkNewBoneData[i].m_pkBoneVertData = NiNew NiSkinData::BoneVertData[pkNewBoneData[i].m_usVerts]; //본에의해 영향을받는 버텍스링크정보
for (unsigned short us = 0; us < pkNewBoneData[i].m_usVerts; us++)
{
//본에의해 얼마나 영향받을지 가중치
pkNewBoneData[i].m_pkBoneVertData[us].m_fWeight = pkOldBoneData[i].m_pkBoneVertData[us].m_fWeight;
//영향받는 버텍스인덱스
pkNewBoneData[i].m_pkBoneVertData[us].m_usVert = pkOldBoneData[i].m_pkBoneVertData[us].m_usVert;
}
}
//새로운 스키닝 정보만들기
// Create the new NiSkinData and NiSkinInstance objects.
NiSkinData* pkNewSkinData = NiNew NiSkinData(uiNumNewBones, pkNewBoneData,
pkOldSkinData->GetRootParentToSkin(), spNewPartClone->GetVertices());
pkNewSkinData->SortAndMergeBoneData();
NiSkinInstance* pkNewSkinInst = NiNew NiSkinInstance(pkNewSkinData,
spOldSkinInstance->GetRootParent(), ppkNewBones);
// 새로운 스킹닝정보 붙이기
spNewPartClone->SetSkinInstance(pkNewSkinInst);
벡토를각도로
irr::core::vector3df v3Angle;
irr::core::vector3df v3Temp = irr::core::vector3df(Heading.x,Heading.z,Heading.y);
v3Angle = v3Temp.getHorizontalAngle();
SadowGeomerty 분석
UpdateShadowGeometryBound : 컬링되지 않도록 타겟오브잭트와 같은 범위를 지정한다.
아래소스와같이 데칼을 붙이기위한지형에대한 지오메트리(삼각형들)를 얻기위해서 카메라노드(m_spCamera)의 절두체를 조작해서 얻는다. 이동할때마다 회전을 보정하지않는이유는 태양광이기 때문에 방향변화가 거의없기때문이다.
void ShadowGeometry::UpdateShadowCamera(float fTime)
{
// this function moves the shadow camera so that it appears to view the
// target (caster) from infinity, facing a fixed direction. This is done
// by moving the camera so the the desired fixed direction vector is
// always coincident with the line through the caster's bounding volume
// center and the camera location
if (!m_spCamera)
return;
// get the "look at" point
NiPoint3 kTarget = m_spCaster->GetWorldBound().GetCenter();
// translate the camera to a distant point such that the camera is looking
// directly at the target point
m_spCamera->SetTranslate(kTarget - (m_kLightDir * 500.0f));//카메라는 이미빛으 방향과 일치되있다.
// set the field of view of the camera to enclose the bounding sphere of
// the caster object.
float fRadius = m_spCaster->GetWorldBound().GetRadius();
float fFOV = fRadius /
(kTarget - m_spCamera->GetWorldLocation()).Length() * 0.95f;
NiFrustum kFrust = m_spCamera->GetViewFrustum();
kFrust.m_fLeft = -fFOV;
kFrust.m_fRight = fFOV;
kFrust.m_fTop = fFOV;
kFrust.m_fBottom = -fFOV;
m_spCamera->SetViewFrustum(kFrust);
m_spCamera->Update(fTime);
}
특정방향쳐다보기(유도탄공식)
NiPoint3 kYVec = -m_kLightDir.Perpendicular();
NiPoint3 kZVec = m_kLightDir.UnitCross(kYVec);

// Rotate the camera based on the orthonormal frame
NiMatrix3 kRotation(m_kLightDir, kYVec, kZVec);
m_spCamera->SetRotate(kRotation);
m_spCamera->Update(0.0f);

광원과 같은방향으로 바라보기 예..
camera 설정하기
pkRenderer->SetCameraData(m_spCamera);
타입캐스팅
-일반포인터 타입캐스팅
NiNode* pkCamOri;
pkCamOri = NiDynamicCast(NiNode, m_spCharacterRoot->GetObjectByName("camOrient"));
타입이맞지않으면 NULL이된다.
-스마트포인터 타입 캐스팅
NiGeometry* pkGeom = NiSmartPointerCast(NiGeometry,m_kCastingObjects.GetAt(i));
겜브리오엔진 회전 기초
카메라는 기본적으로 시 점벡터가 (1,0,0), 업벡터는 0,0,1 이므로

pitch->roll ->yaw

- 쿼터니온

//쿼터니온 변환
{
NiQuaternion kQua,q1,q2,q3;

q3.FromAngleAxisZ(m_fPitch);// 피치 ..이부분중요 90도 롤하기이전에는 요 이후에 피치가된다.

q1.FromAngleAxisX(NI_PI/2); //롤
q2.FromAngleAxisZ(-m_fHeading); //요

kQua = q2*q1*q3;
m_spCamera->SetRotate(kQua);
}

- 오일러회전

FromEulerAnglesYZX(..)

오일러 회전행렬 만들기 , 접미사의 순서가 거꾸로임 즉 위의 경우 x으로 돌리고,z축돌리고 y축돌리라는뜻

짐벌락 주의...

NiNode의역활
이름그대로그밑으로자식을달수있는노드를말한다.
재귀적으로노드를 순회할때...
재귀호출함수(..)
{
들어가면서처리해야될꺼.....
if (NiIsKindOf(NiNode, pkObject))
{
NiNode* pkNode = (NiNode*) pkObject;
for (unsigned int ui = 0; ui < pkNode->GetArrayCount(); ui++)
{
재귀호출함수()
}
}
트리 끝까지 들어 간 다음 처리 해야될꺼 .....
}
식으로 코드구성할수있다.
즉 NiNode가이닌것은(상속개체포함) 밑으로 자식을가질수없다.
예제>
static void DisableZBuffer(NiAVObject* pkObject)
{
NiProperty* pkProp = pkObject->GetProperty(NiZBufferProperty::GetType());
if (pkProp)
{
((NiZBufferProperty*)pkProp)->SetZBufferTest(false);
((NiZBufferProperty*)pkProp)->SetZBufferWrite(false);
}
if (NiIsKindOf(NiNode, pkObject))
{
NiNode* pkNode = (NiNode*)pkObject;
for (unsigned int i = 0; i < pkNode->GetArrayCount(); i++)
{
NiAVObject* pkChild = pkNode->GetAt(i);
if (pkChild)
DisableZBuffer(pkChild);
}
}
}
static void DisableZBuffer(NiAVObject* pkObject)
{
NiProperty* pkProp = pkObject->GetProperty(NiZBufferProperty::GetType());
if (pkProp)static void DisableZBuffer(NiAVObject* pkObject)
{
NiProperty* pkProp = pkObject->GetProperty(NiZBufferProperty::GetType());
if (pkProp)
{
((NiZBufferProperty*)pkProp)->SetZBufferTest(false);
((NiZBufferProperty*)pkProp)->SetZBufferWrite(false);
}
if (NiIsKindOf(NiNode, pkObject))
{
NiNode* pkNode = (NiNode*)pkObject;
for (unsigned int i = 0; i < pkNode->GetArrayCount(); i++)
{
NiAVObject* pkChild = pkNode->GetAt(i);
if (pkChild)
DisableZBuffer(pkChild);
}
}
}
디파인 2개 검사해보기
#if defined(MYDEBUG) || defined(_DEBUG)
#endif
정적라이브러리링크시유의사항

-정적인 데이터 모듈관리(NiStaticDataManager)

기능별로 로더를따로등록한다.
int NiStream::RegisterLoader(const char* pcName, CreateFunction pfnFunc)

라이브러리별로 로더를 묶어서 올리는 함수지정
static void AddLibrary(InitFunction pfnInit, ShutdownFunction pfnShutdown);

기본외예 Animation,Collision 관련 로더를 활성시키려면 관련헤더파일을 인크루드시켜야한다.
예>
#include <collision.h>
#include <animation.h>

Nif파일로드시 이점에 주의하지않으면 로더가 없는부분은 데이터를 읽어들이지않는다.
2 D텍스춰 기능정리
-스크린텍스춰 만들기 & 사용하기 기본

//소스텍스춰 생성
NiSourceTexture* pkTexture = NiSourceTexture::Create(NiApplication::ConvertMediaFilename("emergentlogo.tga"));

NiScreenTexture* pkScreenTexture = NiNew NiScreenTexture(pkTexture);
pkScreenTexture->AddNewScreenRect(32, 32,pkTexture->GetWidth(), pkTexture->GetHeight(), 0, 0);

-NiScreenTexture 주요기능
AddNewScreenRect(찍을위치x,찍을위치y,끈어올크기가로,세로,끈어올위치x,y) ;

SetTexture(pkTexture) //소스 텍스춰지정

-스크린텍스춰 변경하기

먼저 변경공지를때려준다.
m_spScreenTexture->MarkAsChanged(NiScreenTexture::EVERYTHING_MASK);
AddNewScreenRect,또는 RemoveScreenRect 를 써서 추가삭제를한다.

-화면에출력
NiScreenTextureArray m_kScreenTextures;
를 화면 랜더링큰난후 한번씩찍어준다.
예>
void NiApplication::RenderScreenItems()
{
m_spRenderer->SetScreenSpaceCameraData();
const unsigned int uiSESize = m_kScreenElements.GetSize();
unsigned int i;
for (i = 0; i < uiSESize; i++)
{
NiScreenElements* pkElements = m_kScreenElements.GetAt(i);
if (pkElements)
pkElements->Draw(m_spRenderer);
}

const unsigned int uiSTSize = m_kScreenTextures.GetSize();
for (i = 0; i < uiSTSize; i++)
{
NiScreenTexture* pkTexture = m_kScreenTextures.GetAt(i);
if (pkTexture)
pkTexture->Draw(m_spRenderer);
}
}


반응형

'Gamebryo' 카테고리의 다른 글

Gamebryo Default Coordinate  (0) 2011.06.17
[Link] 게임브리오 강의  (0) 2011.03.28
gamebryotip  (1) 2011.03.21
Posted by blueasa
, |

출처 : http://blog.naver.com/spinx85/140127478677
반응형

'Gamebryo > Shader' 카테고리의 다른 글

HLSL Shader file ( fx file ) 컴파일 하기  (0) 2011.08.27
알파 텍스쳐 블렌딩 공식  (0) 2011.07.22
[펌] Soft Particle (Depth bias blend)  (0) 2011.06.15
쉐이더  (0) 2011.04.04
HDR  (0) 2011.04.04
Posted by blueasa
, |

Device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
 Device->SetRenderState( D3DRS_SRCBLEND,  어쩌구);
 Device->SetRenderState( D3DRS_DESTBLEND, 저쩌구 );

 

 뭐 이런식으로 설정해서 나오는 알파블렌딩 적용을 통해 나오는 최종값 공식입니다.

 

 FinalColor = TexelColor × SourceBlendFactor + PixelColor × DestBlendFactor

 

 한글로 설명하면

 결과색상 = 소스칼라값 * 소스 블렌딩 계수 + 대상칼라값 * 대상 블렌딩 계수

 

 소스 - 프레임 버퍼에 전송하고자 하는 픽셀 - 그리고자 하는 픽셀

 대상 - 그리고자 하기 이전에 이미 프레임 버퍼에 존재하던 픽셀

 

 이런 최종값을 알파 텍스쳐 블렌딩 계수 변경을 통해 직접 수정할수 있다.

 

Constants

D3DBLEND_ZERO

Blend factor is (0, 0, 0, 0).

D3DBLEND_ONE

Blend factor is (1, 1, 1, 1).

D3DBLEND_SRCCOLOR

Blend factor is (Rs,Gs,Bs,As).

D3DBLEND_INVSRCCOLOR

Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As).

D3DBLEND_SRCALPHA

Blend factor is (As, As, As, As).

D3DBLEND_INVSRCALPHA

Blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As).

D3DBLEND_DESTALPHA

Blend factor is (Ad, Ad, Ad, Ad).

D3DBLEND_INVDESTALPHA

Blend factor is (1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad).

D3DBLEND_DESTCOLOR

Blend factor is (Rd, Gd, Bd, Ad).

D3DBLEND_INVDESTCOLOR

Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad).

D3DBLEND_SRCALPHASAT

Blend factor is (f, f, f, 1); f = min(A, 1 - Ad).

 Device->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_ZERO);
 Device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );

 

 이런 상태 설정후에 블렌딩 방정식은 다음과 같게된다

 

result =   (Src-R, Src-G, Src-B, Src-A) * (0, 0, 0, 0) + (Dest-R, Dest-G, Dest-B, Dest-A) * (Src-R, Src-G, Src-B, Src-A)

         =   (Src-R*0 ,Src-G*0 ,Src-B*0 ,Src-A*0)

           + (Dest-R*Src-R ,Dest-G*Src-G ,Dest-B*Src-B ,Dest-A*Src-A)

         =  (Dest-R*Src-R ,Dest-G*Src-G ,Dest-B*Src-B ,Dest-A*Src-A)   

 


출처 :  http://cafe.naver.com/jzsdn/6116

반응형

'Gamebryo > Shader' 카테고리의 다른 글

HLSL Shader file ( fx file ) 컴파일 하기  (0) 2011.08.27
알파블렌딩 렌더 설정  (0) 2011.07.22
[펌] Soft Particle (Depth bias blend)  (0) 2011.06.15
쉐이더  (0) 2011.04.04
HDR  (0) 2011.04.04
Posted by blueasa
, |

Gamebryo Default Coordinate

Gamebryo / 2011. 6. 17. 15:53



게임브리오 좌표계가 OGL이랑 같다는 글을 보고 그러려니..하면서 지냈는데

아무리봐도 이상해서 테스트 해보니 게임브리오 기본 좌표계는 이미지 왼쪽과 같았습니다.

오른손 좌표계는 맞지만 OGL 좌표계와 같다고 하면 사람 헷갈립니다.(저처럼..)

겜버려 샘플들을 보다보면

kRotX.MakeXRotation(-NI_HALF_PI);
kRotZ.MakeZRotation(NI_HALF_PI);
m_kCamera.m_spOrientNode->SetRotate(kRotZ * kRotX);

부분을 볼 수 있습니다.

위 로테이션을 거치면 이미지의 우측과 같게 되고,

거기서 3DS Max와 맞추기 위해서 -X / -Y / Z를 사용하면 3DS Max와 같은 좌표계 입니다.

너무 헷갈려서 그려보고 기록을 남기기 위해서 올려 놓습니다.


P.s. 인터넷을 뒤져도 생각과는 다른 좌표계라서 제 생각이 틀렸을수도 있습니다. 
       틀린 부분이 있다면 지적 부탁 드립니다. (_ _)
 

출처 : Mine

[추가] 카메라 좌표계

Max의 카메라와 Gamebryo의 카메라는 방향 벡터가 월드 스페이스 축에 맵핑되는 방식이 서로 다릅니다. 아래 표는 카메라와 관련하여 Max 축에서 Gamebryo 축으로 맵핑되는 걸 보여줍니다. 이 전환은 익스포트 시에 Gamebryo 카메라에서 회전으로써 자동으로 처리됩니다.

지오메트리와 노드들의 좌표계는 Max Gamebryo 모두 같습니다.

카메라 방향

Max 좌표 축

Gamebryo 좌표 축

Up

+ Z

+ Y

Right

+ X

+ Z

Forward

+ Y

+ X



출처 : 게임브리오 문서 중, Coordinate System and 3ds Max 에서 발췌

반응형

'Gamebryo' 카테고리의 다른 글

[펌] 게임브리오 관련..  (0) 2011.07.25
[Link] 게임브리오 강의  (0) 2011.03.28
gamebryotip  (1) 2011.03.21
Posted by blueasa
, |

소프트 파티클은 들인 노력과 비용에 비해서 큰 시각적 효과를 볼 수 있는 방법인 것 같다. 최근 엔진을 Deferred 시스템으로 엔진을 바꾸면서 소프트 파티클을 사용 하기가 쉬웠다( 비단 soft particle뿐 아니라 DOF, SSAO등 깊이 버퍼가 필요한 놈들은 죄다 ㅎㅎ).

연기나 불 등 여러개의 파티클을 사용하는 이펙트들이 오브젝트와 겹치면 좌측 이미지처럼 경계가 날카롭게 나타난다. 소프트 파티클은 이 칼같이 나타나는 경계를 우측처럼 스무스하게 바꿔 주는 것이 기본 목표이다.

알고리즘도 간단하다. PS단에서 파티클 깊이(카메라로부터의 거리)와 뒷 오브젝트의 깊이가 근접할 수록 알파를 더 빼주는 것이다.

더 빼주는 알파 값 D = saturate(( Z object - Z particle) * scale)

단, 그림과 같이 단순하게 위의 수식으로만으로는 덜 자연스럽게 페이드 아웃이 되어 엣지가 존재하기 떄문에 pow()를 걸어주어 좀 더 자연스러운 페이드 아웃이 되게 한다.

당연한 소리가 되겠지만 파티클의 깊이 정렬이 되어 있어야 자연스러운 모습이 나올 것이다. Volumetric Particles니 뭐니 해서 좀 더 귀찮게 하던데, 큰 시각적 차이도 없어 보이고 소팅만 제대로 되어 있으면 굳이 그렇게 까지 할 필요는 없어 보인다.

이 글을 당신 역시 언능 해보시라~ 야구동영상 볼 시간 조금만 아끼면 금방 해보거늘!!!
반응형

'Gamebryo > Shader' 카테고리의 다른 글

알파블렌딩 렌더 설정  (0) 2011.07.22
알파 텍스쳐 블렌딩 공식  (0) 2011.07.22
쉐이더  (0) 2011.04.04
HDR  (0) 2011.04.04
겜브리오 쉐이더 제작시 주의사항  (0) 2011.04.04
Posted by blueasa
, |

체인 라이트닝 참 재미있는 이펙트이다.

 

MMORPG 에서 사용되는 대부분의 이펙트는 공격자->발사체->피격자 의 형태에 맞아 들어가는데

 

체인라이트닝은 이러한 구조가 여러가 엮어져 있는 형태이다.

 

 

 

 

100% 코드로 하기도 애매하고,

 

그렇다고 디자이너가 만들기도 애매한데,

 

결국 코드와 디자인을 반씩 섞어서 만드는 대표적인 이펙트가 "체인 라이트닝" 이펙트이다.

 

워크래프트3 와 와우를 보고서는 체인라이트닝 집어넣자고 기획자가 하루가 멀다하고 징징거린다.

 

참으로 큰일이지만 다른게임에서 되는거 안된다고 하기에는 내가 너무 무능해 보인다.

 

 

1) 첫 시도 -> 코드로 100% 생성을 시도하다.

 

체인라이트닝의 저러한 연출을 디자이너가 하기는 힘들다고 생각하고

코드로 연동하는것이 좋다고 생각했다.

 

게임 엔티티와 연동하는 저런 부분을 3dsMAX 에서 처리하기는 매우 힘들다고 생각했기 때문이다.

 

그래서 체인라이트닝의 번개부분을 노이즈함수 코드를 분석하면서 만들었는데

 

결과는 처참했다.

 

그냥 습작으로는 쓸만했지만 게임상에서 쓸만한 퀄리티가 아니였다.

 

솔직하게 말해서 프로그래머가 3dsMAX 로 번개를 만들어도 퀄리티가 엉망일텐데,

 

코드로 SetPosition 하면서 만든 번개가 퀄리티가 좋을리 없었다.

 

결국 코드로 100% 생성한 체인 라이트닝인 폐기 되었다.

 

 

2) 2차 시도, 체인라이트닝을 생각해보자.

체인 라이트닝 이펙트 자체를 분석하면서

 

체인라이트닝에서 실질적으로 연동해야 하는 부분은

결국 A->B->C->D 로 개별 장거리공격이 연장되는 요소밖에 없다는것을 알게 되었다.

 

그렇다면 개별요소 A->B, B->C, C->D 로 가는 개별 이펙트 자체는

얼마든지 맥스에서 제작할수 있었다.

 

맥스에서 체인라이트닝의 한토막만 만들고 코드로는 연결시키는것이다.

 

 

 

체인라이트닝의 애니메이션은 3부분으로 구성된다.

 

팽창기 : 번개가 공격자에서 피격자로 팽창하는 부분.

지속시간 : 번개가 지글지글 거리는 부분

수축기 : 번개가 공격자부분에서 소멸하기 시작하여 소멸하는 부분.

 

 

문제는 지금까지의 이펙트 렌더링 모듈이 키프레임 애니메이션밖에 지원하지 않아서

번개의 표현하기 위해서는 VertexAnimation 과 텍스춰 애니메이션을 추가로 지원해야 했다.

 

다른게 아니라, 디자이너가 번개를 표현하기 위해서는 맥스에 있는

Noise Modifier 를 반드시 사용해야 하는데 이를 추출할 방법이 VertexAnimation 밖에 없었다.

 

 

 

몇가지 문제가 있었다.

 

맥스에서 만든것을 단지 단순하게 공격자->피격자 거리에 따라서

늘려주기만 할뿐이니 거리에 따라서 이펙트가 왜곡되는 문제도 있었다.

 

이를 해결하는 꽁수 비슷한 방법으로

거리에 따라서 아예 이펙트를 3벌 만들었다.

 

근거리/중거리/원거리 이렇게 미리 이펙트를 3벌 만들어서 거리에 따라서

가장 비슷한 형태의 이펙트를 공격자->피격자를 연결하는데 사용했다.

 

물론 이러한 문제는 이펙트를 "코딩" 으로 제작했다면 발생하지 않는 문제이다.

하지만 "코드" 로는 디자이너의 섬세한 디자인역시 기대할수 없다는 점이 문제이다.

 

결국 맥스로 만든 이펙트를 여러벌 들고 있는것으로 타협을 보았다.

 

체인 라이트닝 이펙트는 좀 "랜덤"스러운 맛이 있어야 하는데,

 

이 부분역시 그냥 이펙트를 여러벌 들고 있는것으로 해결했다.

실제로 체인 라이트닝 이펙트는 거리당 3개, 랜덤속성을 묘사하기 위해서 추가로 3벌씩

도합 3*3 = 9 개의 이펙트가 존재했다.

 

실제로 체인라이트닝이라는 이펙트 하나를 만들기 위해서 상당한양의 리소스가 소비되었지만

그만한 가치는 있다고 판단한다.

 

내가 과연 옳은 방향으로 해결한것일까?

 

이펙트 제작에 있어서 모범 해답은 없다.

결과를 만드는것 자체가 빠듯한 상황에서 모범해답까지 찾을 사치까지 누리고 싶지는 않다.

 

글로는 한방에 스윽하고 적었지만, 게임에서 쓸수 있는 상태의 "체인라이트닝" 을 만들기 위해서

"한달" 동안 디자이너와 삽질을 해야했다.

 

디자이너가 맥스파일을 넘기면 시험삼아서 적용해보고 수정요청하고 다시 코드수정하고

맥스파일 다시 수정요청하고, 이런식으로 10번정도 반복하면 되는데,

 

아무 체계도 없는 막막한 상황에서 삽질로 하나씩 하나씩 완성하는것이니.

디자이너 입장에서도 고역이다.

 

"체인라이트닝" 한번 만들더니 "이펙트 담당할사람 따로 뽑아라" 라고 파업선언을 하더니

더이상 이펙트작업을 하지 않았다.

애니메이터에게 이펙트작업을 시킨것부터가 약간은 무리수가 있었지만 빠듯한 상황에서는 어쩔수가 없다.

 

다른사람들은 어떻게 작업하는지 궁금하다.


출처 : http://blog.daum.net/gdocument/29

반응형
Posted by blueasa
, |



출처 : stnzone.com/gboard/blog/download.php?mb_id=neojzs&id=1135
반응형
Posted by blueasa
, |