예전부터 고쳐야지 고쳐야지를 맘만 먹고 못 고쳤던 IME 문제를 해결하였습니다.

GFx를 이용하여 UI를 개발하면서 IME문제 (한글을 입력할 경우 조합시 한글이 깨지는 문제) 가 있었습니다. 참 답답하였죠. 예제와 포럼에 있는 글들을 싹 찾아서 똑같이 해보았것만 똑같은 현상이 일어났습니다. 정확하게는 "한글" 이라는 글자를 입력할 경우 "한+ㄱ+ㅡ"를 입력하는 중에 Text필드에서는 "한뉢"이라는 글자가 나오는 문제였습니다. 조합시 깨지는 거죠. 아.. 첨엔 조합글자에 대한 폰트의 문제이구나.라고 생각하에 폰트를 swf파일에 포함도 시켜보고 저희가 쓰고 있는 fontlib를 똑같이 마춰보기도 하고 별짓을 다해보았으나.. 역시 똑같은 증상만 나오더라구요. (참고로 GFx에서는 한글이 코어에 다 포함이 되고 있어 따로 IME 셋팅을 안하셔도 됩니다.) 한 일주일을 열심히 찾아봤습니다. 역시나..ㅜ.ㅜ 결론적으로는 제가 일주일동안 곰곰히 생각한 결과 Gamebryo엔진에 대한 문제라고 생각을 했습니다. 찾아본결과 틀린 부분이 한 부분이였거든요. 메세지처리에서 OnDefult가 먼저 불리느냐 Process가 먼저 불리느냐에 차이...! 예제에서는 OnDefault부분을 먼저 처리를 하고 Process함수를 처리를 하는데 저희쪽에서는 Process를 먼저 처리를 하더군요. (자세히 Gamebryo엔진 Application 메세지 처리 부분을 안보았지만...그렇게 호출을 하는 것 같습니다. 콜스택에도 그렇게 나오니깐요..)

저희 파트장님과 함께 열심히 찾아본 결과~! 맞습니다. Process를 먼저 처리를 해서 TranslateMessage와 DispatchMessage를 하면서 메세지의 code가 바뀌어서 생기는 문제였습니다. (정확히 DispathMessage입니다.) 아~~~~~~~ 얼마나 허무하던지.. 아무튼 이문제를 프레임웍을 전혀 안고치고 최적의 꽁수를 펼쳐~ 해결할 방법을 모색한 결과~!
기존에 Process에서 해결하고 있었던 GFx Handle 이벤트를 OnDefault와 같이 처리를 하도록 바꿨습니다. 기존에는 PreProcessKeyboard로 키다운, 키업을 IME Message를 던졌는데 이걸 IME관련 메세지 (WM_IME_SETCONTEXT, WM_IME_CHAR등등 )을 여기서도 같이 처리하겠끔 바꿨습니다. 단 GFx 이벤트 타입은 IME_PreProcessKeyboard로 설정을 하구요.

저와 같이 Gamebryo 2.6에 Scaleform 3.2 인테그레이션 해서 쓰시는 (3.1도 마찬가지 일 것입니다.) 분들은 이와 같은 방법으로 해결하셔도 좋을 듯 합니다. 단~! 이 방법이 과연 옳은 방법인지는 저도 잘 모르겠습니다. 정확히는 프레임웍의 호출 순서를 바꿔야 하겠죠.
아무튼 맘 내키지 않는 방법입니다. ㅋ ^-^

'Or.......... > Work' 카테고리의 다른 글

Scaleform - GFx [Gamebryo 2.6 - Scaleform 3.2 Integrations]  (0) 2010.09.02
Scaleform - GFx [Product]  (0) 2010.08.26
Scalform - GFx [Prologue]  (1) 2010.08.09
Shader Tree  (0) 2009.11.05
Overview of the Major Structural Changes in Direct3D 10  (0) 2009.08.27
,

UI 기획이 확 바뀌어 UI 리뉴얼에 들어갔습니다. 모가 바꼈을 까요~? 기획서를 봤습니다. 헛 흠 ..... Scaleform 홈페이지나 Scaleform 홍보 동영상에서 보았던 3D UI가 저희 프로젝트 기획서에 딱하니 있습니다. 네..ㅜ.ㅜ 3D UI를 하자는 거죠..

그래서 현재 사용하고 있는 Gamebryo 2.6 - Scaleform 3.1 버전을 3.2로 업그레이드 해야하는 작업이 생겼습니다. 예전에 3.0에서 3.1로 업그레이드할때 쫌 약간의 문제가 있었는데.. 이번에도 잘 될까 하고~ 두려움을 앉고 업그레이드 작업에 돌입했습니다. 참고로 Gamebryo 엔진용 Scaleform integration 배포판은 LightSpeed - 3.1 Integration 만 있습니다. 전 이걸 Gamebryo 2.6 버젼으로 수정하여 사용하고 있습니다. (네.. 수정할 것이 좀 있습니다.) 아무튼~! Integration 작업에 돌입하였습니다. 사용하고있는 3.1 Include 파일, 라이브러리, 소스, 서드파티 등을 다 지우고 3.2 버젼 으로 업그레이드 했습니다.

Gamebryo 엔진 Scaleform Integration인 NiGFx를 빌드를 했는데 ~ 엇 예상했던 거와 반대로 빌드가 깔끔하게 되었습니다. 기억으로는 3.0에서 3.1로 업그레이드할 때 약간 수정을 했던걸로 알고 있었는데 3.1에서 3.2로 업그레이드에선 인터페이스가 하나도 안바뀐 모양입니다. (이때까지 행복했습니다.) 그래서 테스트 겸 클라이언트를 실행했습니다. 헛 ㅜ.ㅜ 바로 죽어버리네요... 디버그로 찾아봤는데 .... 헛 GFx 내부 GRendererD3DxImpl -> PopRenderTarget에서 죽어버리네요.. 이유가 RenderTarget에 대한 정보를 스택에 넣는데 RenderTarget이 초기화가 안된 상태에서 스택에 들어가서 문제였습니다. 열심히 해결책을 찾고자 Scaleform 포럼에 들어갔습니다.
찾아 본 결과~ 나와 같은 경우를 겪은 사람들이 두명 밖에 없더군요. 그나마 다행입니다. 이런 문제점이 있어 글을 남겨서.. ^-^  글을 읽은 결과~! 딱 한마디로 써놨습니다. "너가 아마도 SetDisplayRenderTarget 함수를 호출하지 않았을꺼다. SetDisplayRenderTarget 놈을 호출해라~!" 라고 Scaleform 답변이 있었습니다. 언제? 어디서? 저놈을 해줘야 하는지가 없네요..ㅠ.ㅠ 이것까지 친절하게 알려주지..
[죽는 이유가 무비파일에서 어떠한 필터를 쓰거나 AS에서 필터 관련을 썼을 경우 GFx에서 내부 플래시 필터 Update시에 현재 RenderTarget을 스택에 push하고 렌더링때 pop을 해서 RenderTarget을 가져오는데 push할때 현재 RenderTarget이 아무것도 없이 초기화가 안된상태에서 push를 해서 생기는 문제였습니다.]

그래서 열심히 어디다 넣을까를 찾아봤습니다. NiGFx에서는 Scaleform의 GRenderer를 생성을 NiGFxRendererPair에서 따로 생성해서 사용하고 있었습니다. 그래서 해결책은~! NiGFxRendererPair에서 Initialize에서 SetDisplayRenderTarget를 해주면 됩니다.
[참고하세요~]
GRenderTargetD3D9::D3D9RenderTargetParams RTParams;
pkDevice->GetRenderTarget(0, &RTParams.pRenderSurface);
pkDevice->GetDepthStencilSurface(&RTParams.pStencilSurface);

m_spScreenRenderTarget = *m_spTheGRenderer->CreateRenderTarget();
((GRenderTargetD3D9*)m_spScreenRenderTarget.GetPtr())->InitRenderTarget(RTParams);
m_spTheGRenderer->SetDisplayRenderTarget(m_spScreenRenderTarget);

RTParams.pRenderSurface->Release();
RTParams.pStencilSurface->Release();

요렇게 해주시면 됩니다.

,

Scaleform 은 크게 3개의 제품으로 나누어져 있습니다.

코어인 GFx, 언어설정 및 다국어 지원을 해 줄 수 있는 IME, 플래시 비디오를 지원을 해 줄 수 있는 Video.
요렇게 3가지로 구성이 되어 있습니다. 다행이도 한글지원은 코어인 GFx에서 다 알아서 해주기때문에 IME 는 필요가 없지만 다른 나라에서도 서비스를 하기위해선 필요하겠죠.

현재 GFx 3.1을 사용하고 있지만 곧 3D UI, GFx 최적화 툴이 들어있는 3.2버젼으로 업그래이드 할 예정입니다. (현재 클라이언트에서요...)

Scaleform 쪽에서는 4.0을 올해 선보인다고 작년 KGDC에서 발표를 했는데 아직 모르겠습니다. Scaleform의 버젼업이 왜 이슈가 되냐면 버젼업에 따라 지원되는 AS 버젼이 정해지기 때문입니다. 현재 나온 3.2까지는 AS 2.0버젼을 지원하고 있습니다.

현재 저희는 겜브리오 엔진을 사용해서 겜브리오 엔진에 GFx Integration을 하여 사용하고 있습니다. 다른 팀에서는 GFx를 모듈로 만들어서 사용하고 있구요. Scaleform쪽에서는 각 엔진에 따른 GFx Integration를 제공하고 있습니다. (제가 알기로는 언리얼, 겜브리오 밖에 못 본듯...) 그러나 겜브리오 GFx Integration은 버젼이 겜브리오 2.2 와 최근에 나온 Lightspeed 만 제공하고 있습니다. 2.6을 쓰고 있는 저희로썬 Integration을 뜯어고쳐야하는..ㅜ.ㅜ 아무튼~! 현재 고쳐서 열심히 쓰고 있습니다.

단~! GFx Integration은 GFx의 모든 기능을 포함하고 있지 않습니다. 아주 기본적인 기능만 제공하고 있죠. 즉! 필요하면 Integration을 수정해서 써라~! 이말입니다. ㅋ 예를 들어 플래시안에 PNG로드가 필요하면 Integration안에 PNG로드하는 부분을 넣어야 하구요. 또 XML 파싱부분도 필요하면 직접 넣어야 합니다. (PNG로드 모듈, XML 파싱 모듈은 GFx에 원래 있습니다. 단 Integration에는 빠져 있습니다.) 이 부분 때문에 솔직히 많이 애 먹었습니다. ^-^

GFx 쓰면서 가장 많이 느꼈던건 정말 잘쓰면 최고의 UI엔진이지만 어쭙지않게 쓰면 그냥 기존에 사용했던 UI모듈을 쓰는게 훨 낫다고 느꼈습니다. 그만큼 플래시를 잘하고 이해가 높은 디자이너와 UI에 대한 기획을 잘하는 사람 GFx를 잘 컨트롤 할 수 있는 프로그래머 이 세명의 조화가 가장 중요합니다.

다음에는 실제 적용한 GFx 겜브리오 Integration에 대해서 쓰겠습니다.
,

록맨 온라인 팀에 들어와서 개발을 시작한지 언 일년이 지났다. 일년동안 해왔던 일은 Gamebryo 2.6엔진에 Shader 관련, 클라이언트 프로파일러 작업, 가장 큰 UI 작업... (UI작업을 나 혼자....ㅜ.ㅜ - 솔직히 말이 안되지만.. 뭐 위에서 시키는데 해야지요..)

록맨 온라인 UI는 GFx를 사용하여 다이나믹한 UI를 만드는게 목표~! (하지만 결과는~ 2D !!)

아무튼 GFx를 하면서 생겼던 이슛를 하나씩 적을 것입니다. ^-^/

참고..로...

누가 GFx가 쉽다고 했나요? 누가 GFx가 다 해준다고 했나요? -> 과대 광고에 속지마세요~!!!

개발하면서 많은 에로점이 있었습니다. ㅜ.ㅜ

'Or.......... > Work' 카테고리의 다른 글

Scaleform - GFx [Gamebryo 2.6 - Scaleform 3.2 Integrations]  (0) 2010.09.02
Scaleform - GFx [Product]  (0) 2010.08.26
Shader Tree  (0) 2009.11.05
Overview of the Major Structural Changes in Direct3D 10  (0) 2009.08.27
Scene Graph Rendering  (0) 2009.08.27
,

Shader Tree

2009. 11. 5. 11:52
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

Differences between Direct3D 9 and Direct3D 10:

The following page provides a basic outline of key differences between Direct3D 9 and Direct3D 10. This documentation is preliminary and incomplete; it serves as a prelude to a comprehensive Direct3D 9 to Direct3D 10 porting and cross-platform development guide which will be provided in a future release of the DirectX SDK. The outline below provides some initial insight to assist developers with Direct3D 9 experience to explore and relate to Direct3D 10.

 

Overview of the Major Structural Changes in Direct3D 10

The general API usage for Direct3D 10 is in its basic structure not unlike previous versions of Direct3D. The process of rendering using the Direct3D 10 device is structurally similar to Direct3D 9 where you follow the flow of a pipeline:

Set a vertex stream source,
Set input layout (Vertex Stream Decl in Direct3D 9 speak),
Declare primitive topology,
Set textures,
Set state objects,
Set shaders,
Draw

Where the Draw command is the call that ties the operations of the Set calls together and the ordering of Sets is arbitrary so long as they occur before the Draw. The major differences in the Direct3D 10 API design are as follows:

  • Removal of Fixed Function
  • Removal of CAPS bits - Direct3D 10's base feature set is guaranteed
  • Stricter management of
    • resource access,
    • device state,
    • shader constants,
    • shader linkage (inputs and outputs to shaders) between stages
  • API entry point names changed to reflect the virtualization of GPU memory (Map() instead of Lock()).
  • Provision of a Debug Layer which may be added to the device at creation time
  • Primitive Topology broken out from the Draw Call, this is now an explicit device state
  • Constant buffer slots on the device instead of explicit constants
  • Shader authoring is done entirely in HLSL. The HLSL compiler now resides in the primary Direct3D 10 DLL.
  • New programmable stage - the Geometry Shader (GS)
  • Shorter stage names in the API
    • VS - Vertex Shader, GS - Geometry Shader, PS - Pixel Shader
  • Removal of Begin Scene / End Scene
  • Common 2D, focus and adapter-management functionality refactored into a new component: DXGI

We will discuss many of the items listed above in more detail during the rest of this document.

Removal of Fixed Function

It is sometimes surprising that even in a Direct3D 9 engine that fully exploits the programmable pipeline, there remains a number of areas that depend on the Fixed Function (FF) pipeline. The most common areas are usually related to screen space aligned rendering for UI. It is for this reason that you are likely to need to build a FF emulation shader or set of shaders which provide the necessary replacement behaviors.

This documentation contains a whitepaper containing replacement shader sources for the most common FF behaviors.

Fixed Function EMU Sample

Note that some Fixed Function pixel behavior including Alpha Test has been moved into shaders.

Device Object Creation Time Validation

The Direct3D 10 pipeline has been redesigned from the ground up in hardware and software with a primary intention of reducing the amount of CPU overhead (at Draw time) to a minimum. To reduce costs, all types of device data have been assigned an object with explicit creation methods provided by the device itself. This design point enables strict data validation to occur at object creation time and not during the Draw call as it often does with Direct3D 9.

Engine Abstractions / Separation

Applications, including Games, that wish to support both Direct3D 9 and Direct3D 10 at the same time need to have the rendering layers abstracted from the rest of the code base. There are many ways to achieve this but key to all of them is the design of the abstraction layer for the lower level Direct3D device. All systems should communicate to the hardware through the common layer which is designed to provide GPU resource and low level type management.

Direct Removal of Direct3D 9 Dependencies

When porting large, previously tested code bases, it is important to minimize the amount of code changes to those which are absolutely necessary to preserve previously tested behaviors in the code. Best practices include clearly documenting where items change using comments. It's often useful to have a commenting standard for this work which enables quick navigation through the code base and provides measures to determine the amount of code still needing updating.

The following is an example list of standard single line / start block comments which could be used for this work.

// D3D10 REMOVED
Use this where lines / blocks of code are removed
// D3D10 NEEDS UPDATE

It helps to added additional notes to the NEED UPDATE comment that suggests what work / new API should be used for later visits to the code for behavior conversion.

Heavy use of assert(false) should also be used where \\ D3D10 NEEDS UPDATE occurs to ensure you do not unknowingly run errant code

// D3D10 CHANGED
Areas where major changes have occurred should be kept for future reference but commented out
// D3D10 END
End code block qualifier

For multiple lines of source you should use the C style /* */ comments too but add the relevant start / end comments around these areas.

Tricks for Quickly Resolving Application Build Issues

Overriding Direct3D 9 Types

It may be useful to insert a high level header file containing type definitions / overrides for Direct3D 9 base types which are no longer supported by the Direct3D 10 headers. This will help you minimize the amount of changes in the code and interfaces where there is a direct mapping from a Direct3D 9 type to the newly defined Direct3D 10 type. This approach is also useful for keeping code behaviors together in one source file. In this case, it is a good idea to define version neutral / generally named types which describe common constructs used for rendering yet span both Direct3D 9 and Direct3D 10 APIs. For example:

#if defined(D3D9) typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; #else //D3D10 typedef ID3D10Buffer IDirect3DIndexBuffer; typedef ID3D10Buffer IDirect3DVertexBuffer #endif 

Other Direct3D 10 specific examples of this include:

typedef ID3D10TextureCube IDirect3DCubeTexture; typedef ID3D10Texture3D IDirect3DVolumeTexture; typedef D3D10_VIEWPORT D3DVIEWPORT; typedef ID3D10VertexShader IDirect3DVertexShader; typedef ID3D10PixelShader IDirect3DPixelShader; 

Resolving Link Issues

We advise that you should develop Direct3D 10 and Windows Vista applications using the latest version of Microsoft Visual Studio (version 8 at the time of writing). However, it is possible to build a Windows Vista application which depends on Direct3D 10 using the earlier 2003 version of Visual Studio. Direct3D 10 is a Windows Vista platform component which has dependencies (as with the Server 2003 SP1 platform SDK) on the following lib: BufferOverflowU.lib is needed to solve any buffer_security check linker issues.

Simulating Device CAPs

Many applications including games contain areas of code which depend on device CAPS data being available. This can be worked around by overriding enumeration and forcing device CAPS to sensible values, you should aim to re-visit the areas where there are dependencies on CAPS later for full removal of CAPS where possible.

Driving the Direct3D 10 API

The next section of this article focuses on specific areas for driving the Direct3D 10 API and notes ways to deal with the changes in behavior that Direct3D 10 brings.

Resource Creation

The Direct3D 10 API has designed resources as generic buffer types which have specific bind flags according to the planned usage. This design point was chosen to facilitate near ubiquitous access of resources in the Pipeline for scenarios such as rendering to a vertex buffer then instantly drawing the results without interrupting the CPU. The following example demonstrates allocation of vertex buffers and index buffer where you can see that the resource description only differs by the GPU resource bind flags.

The Direct3D 10 API has provided texture helper methods for explicitly creating texture type resources but as you can imagine, these are really helper functions.

CreateTexture2D()
CreateTextureCube()
CreateTexture3D()

When targeting Direct3D 10, you are likely to want to allocate more items during resource creation time than you are used to with Direct3D 9. This will become most apparent with the creation of Render Target buffers and Textures where you need to also create a view for accessing the buffer and setting the resource on the device.

Tutorial 1: Direct3D 10 Basics

Views

A view is a specifically typed, interface to data stored in a pixel buffer. A resource can have several views allocated on it at once and this feature is highlighted in the Single Pass Render to Cubemap sample contained in this SDK.

Programmers Guide page on Resource Access

CubeMap Sample

Static versus Dynamic Resource Access

For best performance, applications should partition their data use in terms of the static vs dynamic nature of the data. Direct3D 10 has been designed to take advantage of this approach and as such, the access rules for resources have been tightened up over Direct3D 9. For static resources you should ideally create it as IMMUTABLE and populate the resource with its data during creation time.

Direct3D 10 Effects

Use of the Direct3D 10 Effects system is outside the scope of this article. The system has been written to take full advantage of the architectural benefits that Direct3D 10 provides. See the following section more detail on its use:

[ Link unavailable at this time ]

HLSL without Effects

The Direct3D 10 Shader pipeline may be driven without the use of the Direct3D 10 Effects system. Note that in this instance, all constant buffer, shader, sampler and texture binding must be managed by the application itself. See the sample link and following sections of this document for more detail:

Direct3D 10 without Effects sample

Shader Compilation

The Direct3D 10 HLSL compiler brings enhancements to the HLSL language definition and therefore has the ability to operate in 2 modes. For complete support of Direct3D 9 style intrinsics and semantics, compilation should be invoked using the COMPATIBILITY MODE flag which can be specified on a per compile basis.

More information about compatibility mode can be found here:HLSL Compatibility mode

The Direct3D 10 shader model 4.0 specific HLSL language semantics and intrinsics can be found at the link referenced below. Major changes in syntax from Direct3D 9 HLSL to take the most notice of are in the area of texture access. The new syntax is the only form supported by the compiler outside of compatibility mode.

[ Link unavailable at this time ]

Creation of Shader Resources

The creation of compiled shader instances outside of the Direct3D 10 Effects system is done in a very similar manner to Direct3D 9 however, in Direct3D 10, it is important to keep the Shader Input signature around for later use. The signature is returned by default as part of the shader blob but may be extracted to reduce the memory requirements if needed.

[ Link unavailable at this time ]

Shader Reflection Layer Interface

The shader reflection layer is the interface by which information about the shader requirements may be obtained. This is particularly useful when creating Input Assembly linkages (see below) where you may need to traverse the shader input requirements to ensure you are supplying the correct input structure to the shader. You can create an instance of the reflection layer interface at the same time as creating an instance of a compiled shader.

Input Assembler Layouts - Vertex Shader / Input Stream Linkage

The Input Assembler (IA) replaces the Direct3D 9 style Vertex Stream Declaration and its description structure is very similar in form. The main difference that the IA brings is that the IA layout object created must directly map to a specific format of shader input signature. The mapping object created to link the input stream to shader may be used across any number of shaders where the shader input signature matches that of the shader used to create the Input Layout.

To best drive the pipeline with static data, you should consider the permutations of input stream format to possible shader input signatures and create the IA layout object instances as early as is possible and reuse them where possible.

Impact of Shader Dead Code Removal

The following section details a significant difference between Direct3D 9 and Direct3D 10 that is likely to require careful handling in your engine code. Shaders which contain conditional expressions often have certain code paths removed as part of the compilation process. In Direct3D 9, any input elements that match the associated code removed are also from their shader input structure. This no longer occurs in Direct3D 10 as the intention is to allow the same Input Signature to be used across all possible permutations of the shader code without invoking the rather costly change of Input Layout. This has an impact on the engine when handling large shaders and creating Input Layouts. Elements which are removed by dead code optimizations in the compiler must still be declared in the Input Structure. The following example demonstrates this situation:

Vertex Shader Input Structure Example

typedef struct { float4 pos: SV_Position; float2 uv1 : Texcoord1; float2 uv2 : Texcoord2; * } VS_INPUT; 

* Direct3D 9 dead code removal would remove the declaration in the shader due to conditional dead code removal

float4x4 g_WorldViewProjMtx; bool g_bLightMapped = false; VS_INPUT main(VS_INPUT i) { VS_INPUT o; o.pos = mul( i.pos, g_ WorldViewProjMtx); o.uv1 = i.uv1; if ( g_bLightMap ) { o.uv2 = i.uv2; } } 

In the above example, under Direct3D 9, the uv2 element would be removed due to dead code optimizations in the compiler. Under Direct3D 10, the dead code will still be removed but the shader Input Assembler layout requires the definition of the input data to exist. The shader reflection layer provides the means to handle this situation in a generic manner whereby you can traverse the Shader Input requirements and ensure that you provide a full description of the Input Stream to shader signature mapping. The following code snippet demonstrates use of the reflection layer to determine shader requirements during Input Assembler layout specification:

// This example helper function checks the Shader Signature to see if // it expects a particular semantic // The HardwareShader_t input structure contains a pointer to a // previously acquired shader reflection layer as follows: // // typedef struct HardwareShader_s // { // ID3D10Blob *pShaderBlobwithSignature; // ID3D10ShaderReflection *IReflect; // // // DEBUG - helps to keep the shader filename around for debugging // #ifdef _DEBUG // char filename[MAX_PATH]; // #endif // // } HardwareShader_t; // bool CheckShaderSignatureExpectations(const HardwareShader_t *pShader, const LPCSTR pSemantic) { D3D10_SHADER_DESC shaderDesc; D3D10_SIGNATURE_PARAMETER_DESC paramDesc; Assert(pShader); Assert(pSemantic); Assert(pShader->IReflect); pShader->IReflect->GetDesc(&shaderDesc); for (UINT k=0; k<shaderDesc.InputParameters; k++) { pShader->IReflect->GetInputParameterDesc( k, &paramDesc); if (wcscmp( pSemantic, paramDesc.SemanticName)==0) return true; } return false; } 

State Object Creation

When porting engine code, it may help to initially use a default set of state objects and disable all Direct3D 9 device render state / texture state setting. This will cause rendering artifacts but is the quickest way to get things up and running. You can later construct a state object management system which can use a compound key to enable maximum reuse of the number of state objects being used.

Porting Content

Texture Formats

The format names for Direct3D 9s DXT* texture formats have been changed and are now part of the DXGI headers. The DXGI component is responsible for allocating and managing buffer data Direct3D 10 provides wrapper functions for ease of use purposes. As such DXGI has the responsibility of defining the supported color format types in Direct3D 10. Mapping of Direct3D 9 format names are listed in the following chart:

Link to Chart which should be added as another page in the docs:

Direct3D 9 Texture/Vertex/Index Format Equivalent Direct3D 10 Format.
D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
D3DFMT_R8G8B8 Not available
D3DFMT_A8R8G8B8 Not available
D3DFMT_X8R8G8B8 Not available
D3DFMT_R5G6B5 Not available
D3DFMT_X1R5G5B5 Not available
D3DFMT_A1R5G5B5 Not available
D3DFMT_A4R4G4B4 Not available
D3DFMT_R3G3B2 Not available
D3DFMT_A8 DXGI_FORMAT_A8_UNORM
D3DFMT_A8R3G3B2 Not available
D3DFMT_X4R4G4B4 Not available
D3DFMT_A2B10G10R10 DXGI_FORMAT_R10G10B10A2
D3DFMT_A8B8G8R8 DXGI_FORMAT_R8G8B8A8_UNORM & DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
D3DFMT_X8B8G8R8 Not available
D3DFMT_G16R16 DXGI_FORMAT_R16G16_UNORM
D3DFMT_A2R10G10B10 Not available
D3DFMT_A16B16G16R16 DXGI_FORMAT_R16G16B16A16_UNORM
D3DFMT_A8P8 Not available
D3DFMT_P8 Not available
D3DFMT_L8 DXGI_FORMAT_R8_UNORM Note: Use .r swizzle in shader to duplicate red to other components to get D3D9 behavior.
D3DFMT_A8L8 Not available
D3DFMT_A4L4 Not available
D3DFMT_V8U8 DXGI_FORMAT_R8G8_SNORM
D3DFMT_L6V5U5 Not available
D3DFMT_X8L8V8U8 Not available
D3DFMT_Q8W8V8U8 DXGI_FORMAT_R8G8B8A8_SNORM
D3DFMT_V16U16 DXGI_FORMAT_R16G16_SNORM
D3DFMT_W11V11U10 Not available
D3DFMT_A2W10V10U10 Not available
D3DFMT_UYVY Not available
D3DFMT_R8G8_B8G8 DXGI_FORMAT_G8R8_G8B8_UNORM (in DX9 the data was scaled up by 255.0f, but this can be handled in shader code).
D3DFMT_YUY2 Not available
D3DFMT_G8R8_G8B8 DXGI_FORMAT_R8G8_B8G8_UNORM (in DX9 the data was scaled up by 255.0f, but this can be handled in shader code).
D3DFMT_DXT1 DXGI_FORMAT_BC1_UNORM & DXGI_FORMAT_BC1_UNORM_SRGB
D3DFMT_DXT2 DXGI_FORMAT_BC1_UNORM & DXGI_FORMAT_BC1_UNORM_SRGB Note: DXT1 and DXT2 are the same from an API/hardware perspective... only difference was premultiplied alpha, which can be tracked by an application and doesn't need a separate format.
D3DFMT_DXT3 DXGI_FORMAT_BC2_UNORM & DXGI_FORMAT_BC2_UNORM_SRGB
D3DFMT_DXT4 DXGI_FORMAT_BC2_UNORM & DXGI_FORMAT_BC2_UNORM_SRGB Note: DXT3 and DXT4 are the same from an API/hardware perspective... only difference was premultiplied alpha, which can be tracked by an application and doesn't need a separate format.
D3DFMT_DXT5 DXGI_FORMAT_BC3_UNORM & DXGI_FORMAT_BC3_UNORM_SRGB
D3DFMT_D16 & D3DFMT_D16_LOCKABLE DXGI_FORMAT_D16_UNORM
D3DFMT_D32 Not available
D3DFMT_D15S1 Not available
D3DFMT_D24S8 Not available
D3DFMT_D24X8 Not available
D3DFMT_D24X4S4 Not available
D3DFMT_D16 DXGI_FORMAT_D16_UNORM
D3DFMT_D32F_LOCKABLE DXGI_FORMAT_D32_FLOAT
D3DFMT_D24FS8 Not available
D3DFMT_S1D15 Not available
D3DFMT_S8D24 DXGI_FORMAT_D24_UNORM_S8_UINT
D3DFMT_X8D24 Not available
D3DFMT_X4S4D24 Not available
D3DFMT_L16 DXGI_FORMAT_R16_UNORM Note: Use .r swizzle in shader to duplicate red to other components to get D3D9 behavior.
D3DFMT_INDEX16 DXGI_FORMAT_R16_UINT
D3DFMT_INDEX32 DXGI_FORMAT_R32_UINT
D3DFMT_Q16W16V16U16 DXGI_FORMAT_R16G16B16A16_SNORM
D3DFMT_MULTI2_ARGB8 Not available
D3DFMT_R16F DXGI_FORMAT_R16_FLOAT
D3DFMT_G16R16F DXGI_FORMAT_R16G16_FLOAT
D3DFMT_A16B16G16R16F DXGI_FORMAT_R16G16B16A16_FLOAT
D3DFMT_R32F DXGI_FORMAT_R32_FLOAT
D3DFMT_G32R32F DXGI_FORMAT_R32G32_FLOAT
D3DFMT_A32B32G32R32F DXGI_FORMAT_R32G32B32A32_FLOAT
D3DFMT_CxV8U8 Not available
D3DDECLTYPE_FLOAT1 DXGI_FORMAT_R32_FLOAT
D3DDECLTYPE_FLOAT2 DXGI_FORMAT_R32G32_FLOAT
D3DDECLTYPE_FLOAT3 DXGI_FORMAT_R32G32B32_FLOAT
D3DDECLTYPE_FLOAT4 DXGI_FORMAT_R32G32B32A32_FLOAT
D3DDECLTYPED3DCOLOR Not available
D3DDECLTYPE_UBYTE4 DXGI_FORMAT_R8G8B8A8_UINT Note: Shader gets UINT values, but if Direct3D 9 style integral floats are needed (0.0f, 1.0f... 255.f), UINT can just be converted to float32 in shader.
D3DDECLTYPE_SHORT2 DXGI_FORMAT_R16G16_SINT Note: Shader gets SINT values, but if Direct3D 9 style integral floats are needed, SINT can just be converted to float32 in shader.
D3DDECLTYPE_SHORT4 DXGI_FORMAT_R16G16B16A16_SINT Note: Shader gets SINT values, but if Direct3D 9 style integral floats are needed, SINT can just be converted to float32 in shader.
D3DDECLTYPE_UBYTE4N DXGI_FORMAT_R8G8B8A8_UNORM
D3DDECLTYPE_SHORT2N DXGI_FORMAT_R16G16_SNORM
D3DDECLTYPE_SHORT4N DXGI_FORMAT_R16G16B16A16_SNORM
D3DDECLTYPE_USHORT2N DXGI_FORMAT_R16G16_UNORM
D3DDECLTYPE_USHORT4N DXGI_FORMAT_R16G16B16A16_UNORM
D3DDECLTYPE_UDEC3 Not available
D3DDECLTYPE_DEC3N Not available
D3DDECLTYPE_FLOAT16_2 DXGI_FORMAT_R16G16_FLOAT
D3DDECLTYPE_FLOAT16_4 DXGI_FORMAT_R16G16B16A16_FLOAT

For uncompressed formats, DXGI has limited the support for arbitrary pixel format patterns; all uncompressed formats must be of type RGBA. This may require swizzling of existing assets pixel formats which we advise that you compute as an offline pre-process pass where possible.

Porting Shaders

Direct3D 10 Shaders are Authored in HLSL

Direct3D 10 limits the use of assembly language to that of debugging purposes only, therefore any hand written assembly shaders used in Direct3D 9 will need to be converted to HLSL.

Shader Signatures and linkage

We have already discussed the requirements for Input Assembly linkages to Vertex shader input signatures earlier in this document (see above). Note that the Direct3D 10 runtimes have also tightened the requirements for stage to stage linkage between shaders. This change will affect shader sources where the binding between stages may not have been fully described under Direct3D 9. For example:

VS_OUTPUT PS_INPUT float4 pos : SV_POSITION; float4 pos : SV_POSITION; float4 uv1 : TEXCOORD1; float4 uv1 : TEXCOORD1; float4x3 tangentSp : TEXCOORD2; float4 tangent : TEXCOORD2; * float4 Color : TEXCOORD6; float4 color : TEXCOORD6; 

* Broken VS - PS Linkage - even though the Pixel Shader may not be interested in the full matrix, the linkage must specify the full float4x3.

Note, the linkage semantics between stages must match exactly however, the target stages inputs may be a prefix of the values being output. In the example above, the pixel shader could have position and texcoord1 as the only inputs, but it could not have the position and texcoord2 as the only inputs due to the ordering constraints.

HLSL Shader Stage linkages

Linkages between shaders may occur at any of the following points in the pipeline:

Input Assembler to Vertex Shader
Vertex to Pixel Shader
Vertex to Geometry Shader
Geometry Shader to Pixel Shader
Geometry Shader to Stream Out

Constant Buffers

For ease of porting content from Direct3D 9 an initial approach to constant management outside of the Effects system might involve the creation of a single constant buffer containing all the required constants. It is important for performance to order constants into buffers by the expected frequency of update. This organization will reduce the amount of redundant constant sets to a minimum.

[ Link unavailable at this time ]

Additional Direct3D 10 Differences to Watch For

Integers as Input

In Direct3D 9, there was no real hardware support for integer data types, however in Direct3D 10 hardware supports explicit integer types. If you have floating point data in your vertex buffer, then you must have a float input. Otherwise the int will be the bit pattern representation of the floating point value. Integer inputs are also not allowed as input to a pixel shader unless the value is marked constinterp which is due to the interpolation for the pixel shader not being an integer interpolation.

Reference Counting Behavior Changes

Unlike previous Direct3D versions, the various Set functions will not hold a reference to the devices objects. This means that the application must ensure that it holds a reference on the object for as long as it would like that object to be bound to the pipeline. When the ref count of the object drops to zero, then the object will be unbound from the pipeline as it is destroyed. This style of reference holding is also known as weak-reference holding, so therefore each bind location on the Device object holds a weak-reference to the interface/ object. Unless explicitly mentioned otherwise, this behavior should be assumed for all Set methods. Whenever destruction of an object causes a bind point to be NULLed out, the Debug Layer will issue a warning. Note, calls to device Get methods such as OMGetRenderTargets() will increase the reference count of objects being returned.

Test Cooperative Level

The functionality of the D3D9 API IDirect3DDevice9::TestCooperativeLevel is analogous to setting the DXGI_PRESENT_TEST flag in the Flags parameter of IDXGISwapChain::Present.

'Or.......... > Work' 카테고리의 다른 글

Scalform - GFx [Prologue]  (1) 2010.08.09
Shader Tree  (0) 2009.11.05
Scene Graph Rendering  (0) 2009.08.27
kd-tree Introduction  (0) 2009.08.27
Grass Rendering  (0) 2009.08.27
,

Scene Graph Rendering

from Or........../Work 2009. 8. 27. 15:07

원문 : http://www.nd.edu/~chuang1/summer03Images/scenegraph01.pdf

 

Scene Graph Rendering

 

 

Dirk Reiners

OpenSG Forum

dirk@opensg.org

 

이 수업에서 이 부분은 렌더링을 위한 씬그래프 시스템에 대해서 설명할 것이다. 씬그래프는 응용프로그램 개발을 단순화하고 이용 가능한 그래픽 하드웨어를 최적의 환경으로 사용할 수 있도록 도와줄 수 있다.

 

이 문서는 당신이 3D 컴퓨터 그래픽스에 대한 몇몇 기본 지식들을 가지고 있다고 가정한다. 만약 폴리곤, 방향성 광원(directional light source), 그리고 텍스처가 당신에게 아무런 의미도 없다면 당신은 이 수업을 따라가는데 문제를 느끼게 될 것이다. 이상적인 수준은 OpenGL을 사용하는 프로그램을 작성한 적이 있거나, "OpenGL Programming Guide"[1] 나 "Computer Graphics"[2]를 읽어본 수준이다.(역주 : D3D 라도 상관없을 듯)

 

첫 번째 섹션은 씬그래프의 기본 구조 및 표준 OpenGL 프로그램과의 차이에 대해서 설명한다. 주변에는 오픈 소스 및 상업용의 씬그래프가 많이 널려 있기 때문에 섹션 2는 가장 일반적으로 사용되는 것에 대한 짧은 개관을 제공한다. 나머지 장에서는 대부분의 씬그래프에 적용되는 일반 개념 및 특정 예제로서 OpenSG 의 사용에 대해 설명한다. 그 다음의 두 섹션은 일반적인 노드 구조체에 대해서 설명하고 그래프를 순회(traverse)하는 방법에 대해서 설명한다. 가장 중요한 단말 노드인 기하도형은 섹션 5에 설명되어 있다. 디스플레이된 기하도형, 변환 상태 및 재질 등을 지정하는 다른 것들은 섹션 6에서 다룬다. 몇 개의 다른 씬 그래프 지정 기능은 섹션 7에 설명되어 있듯이 다른 노드 유형 내부에 감춰져 있다. 씬 그래프의 메모리 공간을 최소화하기 위해 데이터는 여러 가지 방식으로 공유될 수 있는데, 섹션 8은 세부사항을 제공한다. 섹션 9 는 멀티스레딩에서의 중요한 부분 및 씬 그래프가 그것을 지원하기 위해서 어떤 것이 수행되는 지에 대해 다룬다. 섹션 10은 모든 부분에서 예제로서 사용되었던 OpenSG 에 대해서 약간 다룬다. 마지막 섹션은 씬 그래프의 장단점 및 씬그래프를 사용하기 좋은 상황에 대해서 다룬다(힌트 : 그런 상황이 그렇게 많지는 않다).

 

1. 씬그래프란 무엇인가?

 

OpenGL 과 같은 저수준 그래픽 라이브러리들은 immediate 모드 기반이다. 모든 프레임에 대해서 응용프로그램이 그래픽 하드웨어로 모든 데이터를 전송하는 것이 필수적이다. 통신 모델은 "이 폴리곤과 이것, 그리고 이것을 취하고 렌더링 해주세요"라는 것과 같다.

 

씬그래프는 retained 모드 기반이다. 데이터는 한 번만 전달되고 필요할 때만 갱신된다. 통신 모델은 "이것은 내 데이터이며 이제 이미지와 저것 그리고 저것을 렌더링해 주세요"라는 것과 같다.

 

씬그래프가 관리하는 데이터는 그래프로서 구조화된다. 노드는 직접 링크에 의해 서로 연결되며, 루트 노드는 씬 데이터의 시작점을 정의하는데 사용된다. 렌더링을 위해서 이 그래프는 루트로부터 순회를 시작한다. 씬그래프는 보통 acyclic(역주 : 비환식) 그래프이다. 즉 한 노드에서 루트로 가는 과정에 있는 그래프 내의 다른 상위 노드들 사이의 연결이 존재하지 않는다(원문 :  i.e. there are no links from a node to any of its predecessors in the graph on the way to the root.). 이것은 루프를 생성하고 결국 순회를 무한 루프로 이끈다.

씬그래프와 수학적 그래프의 차이는 씬그래프들은 여러 가지 다양한 요소들을 포함하고 있다는 것이다. 즉 노드들은 서로 다른 유형이다. 인테리어와 단말 노드 사이에 눈에 띄는 차이가 있다. 단말 노드는 가시적인 기하도형을 담고 있으며, 인테리어 노드는 그래프를 논리적 그룹(fig. 1 참조)으로 구조화한다.


 
여러 종류의 인테리어 노드가 존재하지만 가장 기본적인 형태는 단일 그룹이다. 다른 인테리어 유형은 섹션 6과 7 에서 설명되며 많지는 않지만 다른 유형의 단말 노드로 존재하기도 한다. 그렇지만 가장 중요한 단말 노드는 기하도형이다(섹션 5를 참조).
 
2. 어떤 씬그래프가 있는가?
 
씬그래프는 오랫동안 존재해 왔다. 다음 리스트는 완벽하지 않지만 가장 잘 알려진 것들이다 :
 
    - OpenSG (http://www.opensg.org)[3]
    - Open Inventor (http://oss.sgi.com/projects/inventor)[5]
    - PLIB (http://plib.sf.net)
    - SGL (http://sgl.sf.net)
    - OpenRM (http://openrm.sf.net)
    - Open Scene Graph (http://www.openscenegraph.org)
    - Performer (http://www.sgi.com/products/performer)[4]
 
이들 모두는 C++로 작성되어 있으며 Inventor 와 Performer는 C 인터페이스도 가지고 있다. SourceForge(www.sf.net)에서 "scene graph" 라고 검색하면 다른 많은 시스템들을 찾을 수 있다. 그러나 대부분은 더 이상 개발되지 않는 것들이다.
 
이들 중 세 가지(Performer, Open Scene Graph, OpenSG) 는 VR Juggler 바인딩을 가지고 있으며, 결국 VR 응용프로그램을 위한 좋은 후보이다. Performer 는 오픈 소스가 아니고 상업 제품임에 주의하라.
 
3. 노드 구조
 
씬그래프의 모든 노드는 몇 가지 공통적인 속성을 가지고 있다.
 
하나는 경계 볼륨이다. 노드의 경계 볼륨은 단순한 볼륨인데, 보통 축 정렬 경계상자(AABB) 나 구이다. 그것들은 현재의 노드의 하위에 있는 모든 노드들의 내용을 둘러 싼다. 그것은 씬그래프에 의해 노드의 가시성을 검사하기 위해서 사용된다. 만약 노드의 경계 볼륨이 가시 영역 바깥쪽에 있다면, 그 아래의 모든 노드들은 비가시화될 것이며 OpenGL 로 넘길 필요가 없을 것이다. 대규모의 씬에서 이것은 렌더링 속도에 있어 큰 영향을 끼친다.
 
여기에서 다른 씬그래프들은 조직화에 있어 약간의 다른 차이를 보인다. OpenSG 는 자식이 단말 노드로 사용되지 않더라도 모든 노드 내부에 자식의 리스트를 유지한다. 왜냐하면 그것은 구조를 단일화하고 순회를 단순화하기 때문이다. 또한 그것은 부모 노드의 포인터를 유지한다. 부모 및 그것들의 중요성에 대해서 세부적으로 알고자 한다면 섹션 8을 참조하라.
 
OpenSG의 특징은 노드가 Node 자체와 Core, 이 두 개로 분할된다는 것이다. Node 는 경계 볼륨, 부모에 대한 포인터, 자식 노드들에 대한 포인터 등과 같은 일반 정보를 모두 유지한다. Core 는 다른 유형의 노드들과 구분하기 위해서 사용된다(예제 그래프를 위해서는 fig.2 를 참조).

가장 단순한 Core 는 Group 인데, 이는 별다른 정보를 가지고 있지 않고 단지 그래프를 구조화하기 위해서만 사용된다.

4. 순회
 
씬그래프나 일반목적의 그래프 상에서의 기본 연산은 그래프의 순회이다. 루트 노드에서 시작해서 모든 노드가 방문될 때까지 노드들 사이의 링크를 따라간다. 대부분의 씬그래프 순회는 깊이 우선이다. 즉 같은 수준의 노드로 가기 이전에 자신의 모든 자식 노드를 순회한다(fig. 3 참조).
 

어떤 순회는 씬그래프 시스템에 의해 미리 정의되지만, 응용프로그램이 씬그래프를 순회하는 것도 가능하다. 어떤 유틸리티 함수는 그것을 매우 단순화할 수도 있다.

 

4-1 Actions

 

순회를 캡슐화하는 클래스들은 OpenSG 에서는 Actions 라고 불린다. 순회를 위해서 루트 노드와 함께 호출되는 것이 action 오브젝트이다. 다른 시스템들은 노드 메서드를 사용하지만, 기본 전제는 항상 루트 노드로부터 순회를 시작하는 것이다. 노드의 종류에 따라 다른 연산이 실행되고, 자식들은 순회로부터 선택되거나 배제된다.

다른 시스템에서는 다른 종류의 순회를 할 수 있다. 가장 중요한 것은 Rendering 순회이지만, 대부분의 시스템은 Intersect (역주 : 마우스 선택이나 충돌과 같은 검사를 위한) 순회도 포함하고 있다.
 
4-1-1. Render Action
 
(다른 시스템에서는 Draw 라 불리기도 하는)RenderAction 의 역할은 씬그래프의 데이터를 저수준 그래픽 라이브러리 명령어로 변경해, 결국 그래프를 이미지로 변경하는 것이다.
 
여기서 흥미로운 부분은 씬그래프가 수행할 수 있는 최적화이다. 왜냐하면 그것은 전체 씬에 대한 고차원의 지식을 가지고 있기 때문이다. 단순히 뷰어의 FOV(field of view, 시야각) 내에 존재하는지 여부를 통해 노드나 전체 하위 트리의 가시성 테스트할 수도 있지만, 더 복잡한 검사도 가능하다. 그러나 단순한 테스트라 하더라도 씬에 대해 고려해야할 많은 데이터를 이미 제거했기 때문에 비용이 적어진다.(원문 : It can test nodes or whole subtrees for visibility, in the simplest case just for inclusion in the field of view of the viewer, but more complex tests are possible. Even the simple test however will already remove a large part of the data from consideration for most scenes.)
 
씬그래프는 전체 씬을 렌더링하기 위해 저수준 라이브러리의 상태를 만드는데 필요한 변경을 최적화하고 최소화할 수도 있다. 이것은 파이프라인을 따라가는 시스템에 대해 렌더링 효율을 괄목할 만큼 증가시켜줄 수 있다.
 
렌더링은 씬그래프 시스템에서 대부분의 노력이 배치된 곳이며, 가장 효율적인 그래픽 하드웨어 용법을 만드는 방식에 대한 경험을 포함하고 있다. 그래서 결국 높은 렌더링 효율을 기대할 수 있는 것이다.
 
4-1-2. Intersect Action
 
다른 일반적인 action 은 IntersectAction 이다. 이것은 그래프의 기하도형이 레이(ray, 종종 레이 집합)에 충돌하는지 검사하며 결국 씬 내의 기하 오브젝트에 대한 충돌 테스트를 허용하게 된다. 이들은 오브젝트 픽킹 및 선택 혹은 땅바닥 기하도형으로부터 일정한 거리를 유지하기 위한 단순한 충돌 검사에 사용될 수 있다.
 
다시 말하지만 씬그래프에 내장된 고수준 데이터는 세부적인 기하도형과 함께 다뤄지기 이전에 씬의 많은 부분을 테스트함으로써 최적화될 수 있다.  결국 씬그래프는 수작업 검사보다 더 효율적일 수 있지만 그것을 프로그래밍하기 위해서는 응용프로그램 작성자가 괴로워진다고 말할 수 잇다.
씬그래프가 항상 광선추적(ray-tracing) 렌더러를 대체하는 데 있어 유용지는 않을 것이다. 그럼에도 이것은 더욱 특수화된 많은 요소들을 포함하고 있는 경향이 있기 때문에 광선 추적을 위한 더 효율적인 자료 구조가 될 수 있다.
 
4-2 단순 순회
 
응용프로그램은 종종 씬그래프가 제공하지 않는, 예를 들어 특정 상태를 만족하거나 만족하지 않는 오브젝트를 검색하는 것과 같은 특별한 기능을 구현하기 위해서 씬그래프를 순회할 필요성을 가지게 된다.
 
물론 응용프로그램은 자체적으로 전체 순회를 구현하거나 씬그래프에 의해 구현되어 있는 기본 action 중 하나로부터 상속받을 수도 있다. 그러나 대부분의 응용프로그램의 순회는 매우 간단하며 복잡한 순회를 위해 필요한 하위 구조 전체를 필요로 하지는 않는다.
 
이런 경우를 위해 OpenSG 를 포함하는 일부 시스템은 그래프를 순회하고, 만나게 되는 모든 노드를 사용자 제공 함수나 메서드로 넘겨 작업하고, 순회를 계속할지 말지를 결정하기 위한 단순한 방법을 제공한다. OpenSG 에서는 이 함수가 traverse() 라 불리며, 여러 상황에서 몇 가지 다양한 방식으로 이용할 수 있다.
 
세부적인 것은 이 문서의 뒷 부분으로 넘기도록 한다. 세부적인 것을 원한다면 OpenSG traverse tutorial 을 참조하라(섹션 10에 튜토리얼을 얻는 방법이 나와 있다).

5. 기하도형
 
씬그래프에서 가장 중요한 노드 유형은 기하도형인데, 이것은 최종적으로 렌더링되는 기하 데이터를 저장하고 있기 때문이다. OpenGL 에서 기하도형은 glBegin() 의 첫 번째 호출과 glEnd() 의 마지막 호출 사이에서 오브젝트에 대해 발생 가능한 모든 것들을 유지하고 있다. OpenGL 은 매우 유연하기 때문에, 그 데이터를 지정하기 위한 여러 가지 가능한 방식이 존재한다.
 
공통 인터페이스 스타일이 제공되며 그것은 모든 현재 씬그래프에 의해서 약간 다양하게 사용된다. 그것은 이 데이터를 분리된(개별) 배열에 나누어 저장하는데 기반하며, OpenGL VertexArray 인터페이스와 매우 유사하다.
 
5-1. 정점 속성
 
OpenGL 에서 한 프리미티브의 각 정점은 여러 개의 속성을 가질 수 있다. 물론 가장 중요한 것은 정점의 위치이다. 다른 공통적인 것은 법선인데, 이는 조명 계산, 색상, 텍스처 좌표를 위해서 사용된다. 씬그래프는 개별 배열을 이들 속성을 위해서 사용한다. 이 배열들이 관리되는 방식은 씬그래프마다 다르다. 가장 간단한 경우 씬그래프 자체는 단지 데이터에 대한 포인터만을 저장하고, 응용프로그램이 데이터를 다룰 책임이 있다. 다른 선택은 데이터를 기하도형 자체에 저장하는 것인데, 일반적으로 STL 벡터나 이와 유사항 동적 크기 배열 형식에 저장한다.
 
이러한 접근의 장점은 그 데이터의 유형이 고정된다는 것이다. OpenGL은 그것이 받아들일 수 있는 종류의 데이터에 대해서 매우 유연하며, 다른 응용프로그램들은 다른 필요성을 가진다. 개별 유형의 기하도형을 다른 매개변수 유형을 위해 생성하는 것이 가능하다. 그러나 다른 속성 유형을 위한 다른 차원(1 ~ 4)의 조합이나 다른 데이터형(unsigned/signed, byte/short/int/float/double)의 조합은 현실적이지 않은 완벽함을 위해 수 백개의 클래스를 생성하게 하는 상황을 만들게 될 것이다.
 
OpenSG 는 속성을 Properties 라는 자신만의 자료 구조에 넣음으로써 그 문제를 해결한다. Geometry Core 자체는 단지 이러한 Properties 에 대한 참조만을 유지한다. 모든 종류의 속성을 위해서 Properties 추상 기저 클래스가 존재하며, 여러 유형의 구체적인 버전이 존재한다. 이러한 방식으로 단일 Geometry Core 유형은 모든 다양한 자료형에 접근할 수 있다.

 
5-2. 프리미티브
 
정점들 자체는 기하도형을 정의하기에는 충분하지 않으며, 그것들은 올바른 방식으로 연결되어야 한다. OpenGL 은 정점들을 연결하기 위한 여러 개의 다양한 방식을 가지고 있다. 그것들을 단순한 점이나 삼각형, 쿼드 및 폴리곤을 통해 연결된 라인으로 그리는 것으로부터 삼각형 스트립이나 팬과 같은 연결된 프리미티브로 그리는 것까지 아주 다양하다. 이들 역시 씬그래프에 의해 매핑될 필요가 있다.

이것은 여러 가지 방식으로 수행될 수 있다. 하나는 여러 가지 프리미티브 유형을 위한 여러가지 기하도형을 가지고 있으며, 단지 하나의 기하도형 당 하나의 프리미티브만을 허용하는 것이다. 어떤 시스템들은 Geometry 를 각각이 자신만의 프리미티브 유형을 가질 수 있는 여러 개의 소규모 기하도형으로 분할함으로써 부하를 줄이려고 시도하기도 한다.
기하도형은 프리미티브 유형이 모두 같더라도 반드시 한 개 이상의 프리미티브 인스턴스를 유지해야만 한다. 일부 유형들(예를 들어 점, 라인, 삼각형)에 대해서는 단일 정점 카운트면 충분하다. 왜냐하면 그것들은 이미 고정된 개수의 정점에 의해 정의된 여러 개의 기하 프리미티브를 포함하기 때문이다. 다른 유형들(예를 들어 폴리곤, 스트립, 팬)은 프리미티브 인스턴스마다 개별 length 를 필요로 한다. 이들 length 는 보통 정점 속성과 같이 기하도형의 속성으로서 저장된다.
 
OpenSG 는 사용할 프리미티브 유형의 리스트를 유지하는 types 속성도 추가함으로써 혼합 프리미티브 유형을 허용한다. 이 types 속성 내의 모든 요소는 lengths 속성 내의 요소들과 관련이 있는데, length 를 모든 프리미티브 유형 인스턴스에 할당함으로써 그것을 정의하게 된다(fig. 4 를 참조). 이것은 여러 개의 프리미티브를 허용함으로써 최대의 유연성을 제공하며, 동질성과 함께 이질성 또한 제공한다.
 
5-3. 인덱싱
 
5-3-1. 단일 인덱싱
 
막혀있는 서피스, 정점들은 종종 여러 번 사용된다. 쿼드를 구성하는 단순한 그리드에서, 거의 모든 정점들은 네 개의 프리미티브에 의해서 사용될 것이다. 이 정점들을 네 번 저장하는 것은 스트림에 필요한 메모리를 많이 증가시키고, 결국 허용될 수 없게 된다.
 
그래서 인덱싱 레이어가 프리미티브와 정점들 사이에 삽입된다. 정점들을 property 에 주어진 순서대로 사용하는 대신데, 사용될 정점들이 중복되지 않도록 지정하기 위해서 인덱스가 사용된다. 2 혹은 4 바이트인 인덱스는 일반적으로 32 에서 120 바이트를 사용하는 정점보다 적은 양의 데이터를 사용하기 때문에, 이것은 메모리 소비를 꽤 줄여 준다(fig. 5 참조).
 
그러나 인덱싱은 부가적인 오버헤드를 야기한다. 즉 그것은 필요할 때만 사용되야 한다. 일부 씬그래프는 가하도형 노드 유형의 형태에서 차이를 보인다. OpenSG 는 단지 IndexProperty 의 유무 여부만을 검사한다.

 

5-3-2. 다중 인덱스

 

지금까지 속성은 모두 서로 연결되어 있었다. 즉 만약 colors, normals 가 존재한다면, 각 정점 위치에 대해 색상과 법선이 존재했다. 이것은 너무 많을 수도 있고 동시에 부족할 수도 있다.

 

만약 색상이 단지 제한된 하위집합만을 취한다면, 몇 십개의 색상만이 필요할 것이다. 즉 모든 정점들을 위해 개별 색상을 보유하는 것은 필요 이상의 메모리를 소비하게 되는 것이다. 한편으로 단일 정점 위치는 서로 다른 법선을 필요로 할 수 있다. 보통의 경우 면은 그것이 정점 기반으로만 수행된다고 해도 픽셀당 조명 계산의 느낌을 부여하기 위해서 smooth-shaded 처리가 된다. 만약 각진 모서리를 원한다면, 단일 정점은 서로 다른 법선을 사용해야만 한다.

 

다중 인덱싱은 가장 단순한 형태는 정점당 속성과 면당 속성 사이의 차이이다. 면당 속성은 정점과 연결되어 있지 않고 면과 연결되어 있다. 그것들은 보통 인덱싱되지 않는다. 그것들은 대부분의 경우 위에 주어진 법선 문제를 해결하지만, 색상 예제에서 주어진 반대 문제는 해결할 수 없다. 더욱 유연한 해결책은 모든 속성에 대해서 개별 인덱스를 소유하는 것이다.

 

OpenSG 는 다른 접근을 사용한다 : 삽입 인덱스(interleaved indices).  정점 당 인덱스 속성으로부터 단일 값을 취하는 대신에, 다중 값이 사용될 수 있다. 어떠한 인덱스가 어떠한 속성을 위해 사용되어야 하는지를 정의하기 위해서 인덱스 매핑이 사용된다. 인덱스 맵의 모든 요소는 모든 속성 조합을 지정할 수 있는 비트필드(bitfield)이다(역주 : 비트 조합이라는 의미인듯). 이것은 다른 속성을 위해 인덱스를 공유하거나, 각각을 위해 개별 인덱스를 소유하는 것을 가능하게 한다(fig. 6 참조).

 

다중 인덱싱에 있어서 한 가지 문제는 그것이 발생시키는 퍼포먼스 오버헤드이다. 그것은 OpenGL 의 정점 배열에 직접 매핑되지 못하며, 명시적인 호출을 사용해서 현실화되어야만 하는데, 그것은 특히 PC 플랫폼에서 퍼포먼스를 낭비한다. 정적 모델을 위해 이 비용은 그것들을 디스플레이 리스트에 배치함으로써 초기화 단계 안으로 상쇄될 수 있다. 동적 모델을 위해 이 비용은 모델이 렌더링될 때마다 지불되어야 하며, 결국 다중 인덱싱을 사용하기 위한 시도를 할 때는 조심해야 한다.
 
5-4. 접근
 
여러 가지 다양한 기하도형 데이터를 사용하면 접근이 복잡해 질 수 있다. 특히 OpenSG는 다양한 프리미티브 및 데이터형을 지원하는 단일 노드 유형만을 가지고 있다. 기하도형 데이터에 대한 접근을 단순화하기 위한 두 가지 메커니즘이 있다.
 
이 속성은 다른 데이터형을 감추는 일반 인터페이스를 소유한다. 그를 위해 모든 유형의 속성들은 모든 유형의 데이터가 변환될 수 있고 접근 가능한 일반(generic) 데이터형을 소유한다. 예를 들어 법선을 위한 Vec3f 혹은 위치를 위한 Pnt3f. 이 변환은 일부 데이터를 소실할 수 있다. 예를 들어 4D 좌표를 변환하는 것은 4 번째 좌표를 잃어버리도록 만들 것이다. 또한 그것은 퍼포먼스 패널티를 일으킨다. 왜냐하면 가상 함수를 통해서 접근하기 때문이고, 데이터가 복사/변환되어야만 할 것이기 때문이다. 결국 데이터형이 알려져 있고 수 많은 요소들이 접근될 필요가 있다면, 대신 형지정(type-specific) 접근을 사용하는 것을 추천한다.
 
두 번째 메커니즘은 서로 다른 프리미티브 유형 및 인덱싱에 대한 걱정을 극복하는데 도움을 준다 : 반복자(iterators).
 
OpenSG 는 세 가지 유형의 기하도형 반복자를 가지고 있다 : 프리미티브, 면, 삼각형. Geometry 는 STL 컨테이너와 같이 자신을 통해 반복하는데 적당한 반복자를 생성하기 위한 begin 및 end 메서드를 가지고 있다. 그것들은 모두 인덱스 참조해제(dereferencing) 에 대해 주의를 기울였고, 프리미티브의 값에 대한 직접 접근을 허용한다. 그것들은 Geometry 에 대한 접근을 허용하는데, 마치 기하도형의 모든 데이터가 서로 다른 배열에 개별적으로 저장된 것이 아니라, 개별 프리미티브를 위한 특정 자료형의 조합인것처럼 취급한다.
 
서로 다른 반복자 유형 사이의 차이점은 반복자가 어떠한 요소를 반복하고자 고려하고 있는지에 달려 있다. PrimitiveIterator 는 단지 types 속성을 통해서 단계를 진행한다. 즉 삼각형이 삼각형 반복 요소를 스트립(strip)하는 예만을 고려한다. FaceIterator 는 더욱 선택적이며 모든 점과 라인을 무시한다. 그것은 반복시마다 모든 잔존 프리미티브를 3 개나 4 개의 정점 폴리곤으로 분할한다. TriangleIterator 도 이와 유사하지만, 단지 삼각형만을 반환한다.
 
반복자는 임의의 기하도형을 사용해 작업하는 것을 매우 쉽게 만들어 주며, 어떠한 유형 및 인덱스가 사용되어야 하는지에 대해 신경쓰지 않게 해 준다.

 
6. 상태 제어
 
기하도형을 정의하는 것은 그래픽적 씬을 생성하는데 있어서 절반이며, 서피스, 조명, 변환 속성을 정의하는 것이 나머지 절반이다.

6-1. 변환
 
이 문맥에서 변환은 씬 내의 오브젝트를 움직이는 데 사용되는 기하 변환에만 국한되며, 카메라 조작과 관련된 변환에 대해서는 이 수업 노트의 다른 장에서 다룬다.
변환은 완전한 오브젝트에 적용되며, 오브젝트의 일부에 대해서 적용될 수 없다. 또한 변환은 씬그래프의 전체 하위트리에 유용하게 적용되어 혼합 오브젝트나 다중 오브젝트들을 주위로 이동시킬 수 있다. 그래서 이것들은 씬 그래프의 상태 계층을 위한 주요한 예제가 될 것이다.
변환은 행렬을 저장하거나 변환을 정의하는데 필요한 요소들을 저장하는 개별 노드 유형으로서 구체화된다(예를 들어 스케일, 방향, 이동). 변환은 트리의 아래에 있는 모든 것들에 영향을 미치며, 그것은 다른 변환을 포함한다.
 
변환은 축적된다. 즉 새로운 변환은 그것의 상위에 있는 것의 변환을 대체하지 않고 그것을 추가한다. 이것은 로컬 좌표계에서 변환을 정의하는 것을 허용하면서, 전체 시스템을 변환할 수 있도록 해 준다. 그리고 그것들은 계층적 변환 체인을 정의하는 것을 허용한다. 계층적 변환의 사용에 대한 주요 예제는 행성과 달을 가지는 행성계이다.
 
행성계에서 달은 자신의 행성 주변을 회전한다. 동시에 행성은 태양 주변을 회전한다. 절대 좌표로 달의 이동을 지정하는 것은 복잡한 처리가 될 것이다. 그것들을 자신의 행성에 상대적으로 지정하고, 동시에 행성-달 덩어리를 태양 주변으로 움직이는 것이 간단하다.

 
6-2. 광원
 
광원은 씬그래프의 문맥에서 흥미로운 문제를 제시한다. 씬그래프에서 광원노드의 위치는 두 개로 정의될 수 있다. 하나는 광원의 위치와 방향이다. 이것은 자동차에 붙어 있는 헤드라이트와 같은 오브젝트에 광원을 붙이는데 유용하다. 변환 계층을 위해 광원은 자동적으로 자동차의 이동을 따라갈 것이다. 조명에 영향을 받는 것을 정의하기 위해 다른 목적이 존재할 수 있다. 이것은 상태 계층과 관련이 있다. 즉 씬그래프에서 광원 아래에 존재하는 모든 것은 그것에 의해 조명을 받는다.
 
그래프 내에서 광원 위치에 대한 이 두가지 의미는 모순되며, 트리 내의 단일 위치를 사용해서는 해결할 수가 없다. 만약 그래프 내에서 광원의 위치가 한 번에 두 가지 의미를 가진다면, 헤드라이트 시나리오는 불가능할 것이다. 왜냐하면 조명은 단지 그래프 내에서 아래에 있는 것들에만 비칠 것이며, 즉 일반적인 헤드라이트의 행동을 취하지 않고 차의 일부가 아니라 길의 일부가 될 것이다. 그럼에도 불구하고 Inventor 는 이 기법을 사용한다.
 
다른 시스템들은 이 문제를 해결하기 위해서 다른 해법을 사용한다. 하나의 해결책은 모든 광원을 전역으로 정의하는 것이다. 즉 모든 것은 모든 광원에 의해서 조명을 받는다. 이 경우 그래프 내의 위치는 그 조명만의 위치를 잡는데만 사용될 수 있다. 이 해결책은 간단하지만 시스템의 표현력에 제약을 가하게 된다. Performer 는 각 기하도형에 어떠한 광원이 영향을 미치는지를 명시적으로 정의하도록 허용하는 차선책을 사용한다.
OpenSG 는 다른 해결책을 사용한다. 그래프에서 광원의 위치는 상태 계층 요소에 근거해 씬내에서 그것에 의해 영향을 받는 부분을 정의한다. 광원의 위치와 방향은 그래프 내의 다른 요소에  의해서 정의된다. 그 요소는 단지 광원에 의해서 참조되기만 하며 beacon(봉화, 등대?) 이라 불린다.

 
6-3. 재질
 
재질은 기하도형의 서피스 속성을 정의하는데 사용되며, OpenSG 에서는 실제로는 Geometry 노드의 속성이다. 재질의 속성은 대부분 OpenGL 재질 상태로부터 직접 매핑된다. 즉 emissive, ambient, diffuse, specular 색상 및 shininess이다.
 
OpenGL 에 직접적으로 매핑될 수 없지만 올바르게 구현되기 위해 많은 노력을 들인 순결해 보이는 재질은 투명도이다. 투명도와 OpenGL 은 서로 잘 맞지 않는다. 투명한 오브젝트는 다른 모든 오브젝트가 렌더링된 이후에 올바른 블렌딩 함수를 사용해 렌더링될 필요가 있으며, 그것들은 뒤에서 앞의 순서로 그릴 필요가 있다. 완전히 올바르게 그리려면 그것들은 면끼리 비교해 뒤에서 앞으로 그려지며, 겹치는 기하도형에 대해 겹치는 면을 분할하고 정렬해야 한다.
투명도를 위한 전체적이고 완벽한 지원은 매우 소비적이며, 특히 동적인 기하도형의 경우에 더 심하다. 결국 어떠한 씬그래프도 그것을 지원하지 않는다. 그것들에 대한 최선은 오브젝트 간 비교에 의해 투명한 오브젝트를 마지막에 렌더링하고, 뒤에서 앞으로 정렬하는 것을 지원하는 것이다. 즉 오브젝트는 뒤에서 앞으로 렌더링될 것이다(보통 참조 위치에 의해 정렬된다. 예를 들어 경계상자의 중심). 그러나 오브젝트 내부 정렬은 수행되지 않는다.
 
OpenSG 는 SimpleMaterial 과 SimpleTexturedMaterial 클래스를 이를 위해 사용한다. 또한 SimpleTexturedMaterial 은 텍스처 필터링을 정의하기 위한 매개변수와 함께 재질을 위한 텍스처로서의 이미지를 유지한다.

 
7. 다른 노드 유형
 
다른 씬그래프들은 다른 노드 유형의 형성을 위한 부가적인 기능을 제공한다. 이들 중 일부는 매우 ubiquitous 하며, 다른 것들은 적은 시스템에서만 작동한다. 다음은 약간의 일반적인 예들이다.
 
7-1. 스위치
 
Switch 노드는 단순하지만 Group 노드 상에서의 다양성을 위해 유용하다. t selects zero or
one of its children for traversal instead of all of them. 이것은 하위 그래프를 끄거나 모델의 정적 집합을 통해 순환하기 쉬운 방법이다.
 
어떤 시스템은 비트마스크를 사용해 자식 집합을 선택하는 것을 허용한다.
 
7-2. LOD
 
Level of Detail(LOD) 는 다소 단순하지만 대규모 씬에 대한 렌더링을 최적화하는데 효율적인 방법이다. 기본 발상은 멀리 있는 오브젝트들은 가까이 있는 오브젝트보다 덜 세부적으로 렌더링한다는 것이다.
 
이렇게 함으로써 씬그래프는 렌더링되는 오브젝트의 복잡성을 줄일 필요가 있다. 가장 좋고 쉬운 방법은 다른 복잡도를 가지는 여러 가지 버전의 오브젝트를 제공하도록 응용프로그램에 요청하는 것이다. 이들 각각은 어디에서 자신이 사용되어야 하는지를 알기 위해서 보통 관찰자로부터의 거리인 범위를 할당받는다. 이 범위는 다른 버전을 가지고 노드의 자식으로서 LOD 노드에 저장된다.
 
LOD 노드의 작업은 예를 들어 주어진 관찰자의 거리를 위한 올바른 자식을 선택하는 것이다. 일반적으로 그것은 단지 하나의 자식만을 선택하며, 현재 상황에서 가장 적합한 것을 찾는다. 즉 그 중 더 복잡한 것을 디스플레이한다.

 
7-3. 파티클
 
종종 단순하지만 동적으로 이동하는 대규모의 오브젝트들이 필요하다. 그 예는 ball-and-stick 분자 모델에서의 ball인 순환적인 대칭 오브젝트를 위해 사용될 수 있는 관찰자에 정렬된 쿼드 또는 투명 텍스처를 사용하는 연기 시뮬레이션이다. 다른 예는 궤적을 보여주는 화살일 수 있다.
 
Geometry 노드를 매우 간단한 수 천개의 이러한 단순 개체 각각을 위해 생성하는 것은 많은 오버헤드를 발생시킨다. 그것들을 모두 관철자 정렬로 바꾸는 것은 다중의 뷰가 씬 내에서 활성화되어 있다면 응용프로그램으로서는 불가능하다. 즉 씬그래프에서 배제해야 한다.

OpenSG 는 이러한 상황을 특정 Paticles 노드를 사용해 지원하는데, 이는 위치, 색상, 크기를 입력으로 취해 그것들을 매 프레임에 대해 여러 종류의 기하도형으로 변환한다.

 
8. 공유
 
8-1. 노드 기반
 
씬그래프는 씬을 렌더링하기 위한 모든 데이터를 소유할 필요가 있다. 그러나 많은 씬에는 다른 오브젝트의 복사본일 뿐인 오브젝트들이 존재한다. 단순한 예는 자동차의 휠이다. 같은 오브젝트에 대한 정확히 내 개의 복사본이 존재하며, 위치만 다를 뿐이다. 씬그래프를 위해 메모리를 효율적으로 사용하려면, 이들 오브젝트에 의해 사용되는 자료를 공유할 방법이 있어야만 한다.
 
이를 위한 한 방법은 다수의 부모에 대해 오브젝트 추가를 허용하는 것이다. 변환을 사용하여 서로 다른 복사본이 같은 데이터를 공유하면서 독립적으로 배치될 수 있도록 할 수 있다. 이것은 매우 간단한 기법이며, 이는 많은 씬그래프에서 사용된다.
 
그럼에도 불구하고 이것은 몇 가지 문제를 가지고 있다. 오브젝트가 포인터에 의해 더 이상 식별될 수가 없다. 모든 복사본이 같은 오브젝트이기 때문에, 포인터는 복사본의 의미를 알지 못한다. 결국 그래프를 따라 올라갈 때, 예를 들어 오브젝트의 전역 위치를 획득하기 위해 순회 과정 상의 변환을 누적하고자 할 때, 어떠한 방식으로 해야할지 알 수가 없다.
 
또 다른 문제는 이름과 같은 인스턴스 지정 데이터를 연결할 수가 없다는 것이다. 다시 말하는데 이 복사본은 모두 같은 오브젝트이며, 차이가 존재하지 않는다.
 
이것이 OpenSG 가 Node/Core 분할 정책을 사용하는 주요 이유이다. Node 는 단일하며, 그것들은 공유될 수 없다. 모든 Node 는 단지 단일 부모 포인터만을 가진다. Core 는 분할될 수 있으며, 그것들은 다수의 사용자를 가진다(fig. 7 참조).

 
Node 는 매우 작기 때문에 그것들을 복사하는데 있어서 발생하는 메모리 패널티는 문제가 안 된다. Cores 에 포함된 주요 데이터들은 공유될 수 있다. Graph 구조를 노드 내용으로부터 분할하는 것은 공유 제어를 허용하기도 한다. 예를 들어 Switch Core 를 공유하는 것은 단일 Core 상의 값을 설정하는 것을 허용해 씬 내의 여러 Node에 영향을 미칠 수 있다. 같은 원리가 LOD, Transformation, 다른 종류의 Core 에도 적용된다.
 
8-2. 기하도형
 
씬그래프 데이터의 대부분은 기하도형에 포함된다. 완전한 기하도형을 공유하는 것은 위에서 언급했던 노드 기반 공유와 함께 가능하다. 그러나 예를 들어 shaded 모델의 최상위에서 와이어프레임을 그린다거나 다른 색상으로 오브젝트의 일부를 그려서 강조한다거나 할 때 기하도형의 일부만을 공유하는 것이 좋은 상황이 존재한다.
 
어쨌든 기하도형의 데이터는 다른 속성으로 분할되었기 때문에, 개별 속성을 개별적으로 공유하기 위한 단계는 적다. 대부분의 씬그래프 시스템은 여러 가지 방식으로 그것을 허용한다. 왜냐하면 그 데이터는 응용프그램 혹은 OpenSG와 같은 것에 의해서 데이터를 자신만의 자료구조에 파생시키는 것에 의해 관리되기 때문이다.(원문 : As the data of the geometry is split into different properties anyway, it is a small step to sharing the separate properties separately. Most scene graph systems allow that in one way or another, either because the data is managed by the application anyway, or, like OpenSG, by splitting the data off into their own data structures.)
 
(역주 : 이 아래쪽은 중요하지도 않은 것 같고 뭔 소린지 이해가 안 되는 부분도 있고 해석하지 않습니다. 알아서들 보시길...)
 
9. Multi-Threading
 
Multi-threading is an aspect that is growing in importance, given the current trend in
processor designs to go to simultaneous multi-threading (SMT).
A number of scene graphs provide simple multi-threading support, which allows simultaneous
reading or rendering of the scene graph. For many applications this is
quite adequate, but for more demanding applications that use asynchronous simulation
threads needing consistent data and/or manipulate the graph it is not enough.
OpenSG supports these kinds of applications by allowing each structure to have multiple
aspects, i.e. multiple copies of itself. This is done efficiently by only copying the
bulk of the scene graph’s data, the geometry data, when it is needed.
Different aspects can be efficiently synchronized under application control, making
them contain the same data again. To support this in a general and easily extensible
way, OpenSG adds reflectivity to the system. Reflectivity is the ability of the system’s
structures to give out information about themselves, e.g. which fields they contain and
how to access those fields. This ability is used to automatically add synchronization
capabilities to each structure of the system.
It can also be used to write a generic OpenSG loader/writer that can automatically
handle new structures and extensions in the system without having to write any specific
code for it. An extension of this system also allows synchronizing scene graphs across
a cluster of machines. Again, no cluster-specific code needs to be written, the data is
automatically distributed and synchronized.
The difference between this kind of clustering and the kind of clustering the already
introduced systems clusterJuggler and netJuggler lies in the point on the pipeline the
distribution is done. Both netJuggler as well as clusterJuggler distribute the inputs to
all nodes. This approach minimized the amount of data to be sent over the network,
but the full application is running on all nodes and needs to process the input. If that
input processing takes a lot of calculation or depends on large external data this can
be a problem. OpenSG distribution on the other hand distributes after the inputs have
been processed but before OpenGL commands are generated.
This section can only give an idea of what’s done in OpenSG for multi-threading, see
[3] for more information.
 


10 Getting to know OpenSG

OpenSG is one example of the current breed of modern scene graphs. It is developed and distributed under the Open Source principle and is available including source code from www.opensg.org.

It is designed with multi-threading (see sec. 9 for details) and application extensibility in mind, i.e. changes to internal data structures are possible without having to change the library’s source code (and thus without having to reapply changes whenever the library changes).

The development is supported by a number of companies and research institutes (see www.opensg.org/forum for details), guaranteeing sustained development. Further development is also sponsored by the German Government by a research project called OpenSG PLUS (see www.opensg.org/OpenSGPLUS) which funds continuous development of the core as well as a lot of high-level functionality (NURBS rendering, subdivision surfaces, Clustering, Occlusion Culling, Volume Rendering, High-Level Shading to name but a few).

It is developed on Linux, Irix andWindows, with a MacOS X port pretty much working and an HP port in the works. It is hosted on SourceForge (www.sf.net) and uses the SourceForge infrastructure to build a developer community, mainly based on mailing lists and IRC.

The 1.0 version was released in October 2001, the 1.1 developer version will be released in April 2002. But an automatic dailybuild system makes sure that the current CVS always compiles on every platform and allows access to daily snapshots if needed.

Some automated documentation is created from the source code using the doxygen tool, but more useful as an introduction is the Starter Guide (www.opensg.org/starter) and the tutorial examples (available in the tutorials/ directory in the source and distributions).

11. When does it make sense to use a scene graph?
 
This part of the course talked about scene graphs and what they can do for a graphics
application. Of course they cannot solve all the problems, and they are not always the
best solution to every problem.
Their main strength and their main weakness is that they are a retained mode structure.
Having access to all the data making up the scene allows them to optimize the rendering
by only rendering visible objects and sorting them by state to make effective use of the
graphics hardware.
The weakness is that the data structure needs to be consistent with the application’s
data. If that data is very dynamic, especially if the node structure changes for every
frame, keeping the scene graph up-to-date can eat up the profit that it brings. If only the contents of the objects change it’s not as bad, especially if the maximum size of the
dynamic areas is known beforehand, but there is still some overhead involved.
Scene graphs really shine in complex scenes, complex in the sense that they consist of
a large environment that uses many different materials. For situations where there is
a small number of objects, all using the same rendering parameters, and all visible all
the time, a simple application obeying some basic rules (only change state if it is really
different, use vertex arrays with native data types) can reach a very good performance.
Note however that even these applications can get a taste of complexity quickly, as
soon as interaction gets involved and different kinds of markers, information displays
and higher level rendering features are needed, in which case a scene graph becomes a
more viable solution.

Besides being highly efficient rendering engines, scene graphs also tend to accumulate
useful utility functions for handling scene data. The most prominent examples are
loaders for models and images. Writing loaders is a job that nobody likes to do, so
being able to use somebody else’s work can already make using a scene graph worth
it. Similar reasoning applies to the intersection test (see sec. 4.1.2).

A special case is the clustering support given by OpenSG, as it simplifies bringing
an application to a cluster significantly, something which is becoming more and more
important and can turn into a lot of work quickly.

When faced with an already fully developed application that displays a single object
always centered on the screen, switching to a scene graph will only make sense in very
few situations. However, when starting a new project it can never hurt to start using
a scene graph. If the application turns out to be too simple for a scene graph going
back won’t be a big problem. But the amount of useful functionality that a scene graph
provides, especially in it’s domain of loading, processing and rendering scenes, can
become addictive pretty quickly. Try it, you might enjoy it!

References

[1] Mason Woo et.al. OpenGL(R) Programming Guide: The Official Guide to Learning
OpenGL, Version 1.2. Addison-Wesley Pub Co, 1999.

[2] James D. Foley, Andries van Dam, Steven K. Feiner, and John F. Hughes. Computer
Graphics, Principles and Practice, Second Edition. Addison-Wesley, Reading,
Massachusetts, 1990. Overview of research to date.

[3] Dirk Reiners, Gerrit Voss, and Johannes Behr. OpenSG Basic Concepts. In
OpenSG 2002 Symposium, Darmstadt, 01 2002.

[4] John Rohlf and James Helman. Iris performer: A high performance multiprocessing
toolkit for real-time 3d graphics. Proceedings of SIGGRAPH 94, pages
381–395, July 1994. ISBN 0-89791-667-0. Held in Orlando, Florida.


[5] Paul S. Strauss and Rikk Carey. An object-oriented 3D graphics toolkit. In Edwin
E. Catmull, editor, Computer Graphics (SIGGRAPH ’92 Proceedings), volume
26, pages 341–349, July 1992.

'Or.......... > Work' 카테고리의 다른 글

Shader Tree  (0) 2009.11.05
Overview of the Major Structural Changes in Direct3D 10  (0) 2009.08.27
kd-tree Introduction  (0) 2009.08.27
Grass Rendering  (0) 2009.08.27
Water Rendering  (0) 2009.08.27
,

kd-tree Introduction

from Or........../Work 2009. 8. 27. 14:57
⊙ Introduction
여기에서 다루는 kd-tree는 공간 DB로, 기존의 문자 DB와는 다르다. key 값 매칭 문제이고, 굉장히 큰 양을 공간 기반으로 검색한다. 공간 기반 검색이란, range로 표현된 질의를 검색한다는 것이다. Spatial data는 points, lines, polygons 등을 포함하고 있따.
Spatial data를 효율적으로 지원하기 위해서는, 다음과 같은 특징적 어려움을 알아야 한다.
① First, spatial data are latge in quantity, complex in structures and relationships
② Second, the retrieval process employs complex spatial operators like intersection, adjacency, and containment
③ Third, it is difficult to define a spatial ordering, so conventional techniques cannot be employed for spatial operations
→ spatial indices 필요!

(1) kd-tree : Binary-tree based indexing
kd-tree는 multi-attribute data index를 binary search하는 tree로, k는 표현될 데이터 공간의 차원을 가리킨다. 각 depth에서, 어떤 branch로 갈 것인가를 결정하는 데에 다른 attribute이 사용된다. 예를 들어, 2-d (x,y) tree에서는 짝수 depth에서 x 좌표가 branch 기준이라면, 홀수 depth에서는 y 좌표가 branch 방향의 기준이 된다. 마지막으로, 이 tree는 꼭 균형을 이룰 필요는 없다.

A가 제일 먼저 들어간 것을 알 수 있다. 즉, 최초의 분리자는 root이다.



① Principle
Node는 각각의 실제 data point를 나타내고, 검색 방향의 지표가 된다. (left, right 두 개의 child가 있다.→ 현재 노드 값 보다 작은가? 큰가?)
한 Node는 5개의 field로 구성되어 있다. LOSON(작은 값을 가진 left 자식), HISON(큰 값을 가진 right 자식), 좌표(x,y,...), NAME(해당 노드에 대한 정보. 포인터가 들어갈 수도 있다.), DISC(좌표 이름을 가리킨다. 즉, 이 노드는 x를 기준으로 했느냐 y를 기준으로 했느냐. 등. ).

② Insertion
Binary search tree에서의 insertion 방법과 유사하다. 다른 점이 있다면, 앞에서 설명 했듯이, depth마다 비교하는 attribute가 다르다는 것이다. tree의 bottom에 도달하면, 거기에 새 node를 넣는다.

매우 쉽다;



③ Search
Search 역시 매우 straightforward하다. 흐흐 BST 처럼 찾아 내려가면 된다. 여기에서 역시, 다른점은 depth마다 비교 기준의 attribute이 다르다는 점 뿐. 참 그리고, 질의가, 조건 질의가 가능하다는 것이 또 하나 틀린데, 예를 들어, 'Y>20인 점들을 찾아라' 라든지, '(75,15)에 가까운 점들을 찾아라' 등이 가능하다는 것이다.
Region Search는 Euclidean distance를 이용하여 구할 수있다. node (a,b) 근처 거리 d안에 있는 점들을 다 구하라는 질의가 들어오면, 우선 (a-d) ≤ x ≤ (a+d), (b-d) ≤ y ≤ (b+d) 안의 점들을 다 구한다. 그런데 이렇게 구한 점은, 반지름 d인 원 안에 있는 점이 아니라, 한 변이 2d인 정사각형 안에 들어오는 점이므로, 점들을 구한 다음에 range안에 들어오는 게 맞는지 확인이 필요하다.

Search 결과 Miami를 찾았다!



④ Deletion
앞에 insert나 search는 BST와 비슷하여 쉬웠지만, deletion은 좀 더 복잡하다. 각 depth마다, DISC가 달라서, 원래 tree의 root는 DISC가 x 지만, subtree의 root는 y가 될 수도 있기 때문에, 모든 subtree가 kd-tree가 아니다. 그래서 그냥 마구 삭제해 버리면 문제가 생긴다.
kd-tree로 부터 (a,b) 노드를 삭제한다고 할 때, (a,b)의 두 subtree가 empty tree이면 그냥 삭제하면 되고, 아니면 (a,b)의 subtree들 중에서 가장 적절한 대체 노드 (c,d)를 찾아서, replace시킨다. 이 (c,d)는 recursive하게 다시 삭제되는 것이다. 그렇다면, 이 대체 노드는 어떻게 찾는 것일까? 오른쪽 subtree에서 가장 작은 값을 가진 노드나, 왼쪽 subtree에서 가장 큰 값을 고르면 된다. 그러면 다음의 예를 보자.

사실 이것도 찬찬히 보면 매우 쉽다. 그죠?



⑤ 장단점
kd-tree는 partial matching search에 유용하지만, empty space가 없고, point search와 region search가 다 가능하다. 하지만, 균형이 심~하게 안맞으면 performance가 안좋다. kd-tree는 메모리 기반 index이다. File 기반에서는... 안좋다.

 

출처 : http://www.snisni.net/98

'Or.......... > Work' 카테고리의 다른 글

Overview of the Major Structural Changes in Direct3D 10  (0) 2009.08.27
Scene Graph Rendering  (0) 2009.08.27
Grass Rendering  (0) 2009.08.27
Water Rendering  (0) 2009.08.27
Flight Simulator : HUD - LCOSS  (0) 2009.08.27
,

Grass Rendering

from Or........../Work 2009. 8. 27. 14:55

으.. 오랫만에 쓰는 작업 스토리... (너무 바뻤음..ㅜ.ㅠ)

 

물 렌더링 관련 작업을 끝내고 풀 렌더링에 대해서 작업을 시작했습니다. 작업 시작해서 끝난지는 언 6~7개월 전 ㅡㅡㅋ 너무 바쁜관계로다가 지금 이렇게 씁니다. 아무튼....기존의 풀 렌더링 관련 툴이 있었는데 (역시 물 작업 툴과 같이..) 디자이너들이 쓰기가 불편하다고 하고 퍼포먼스 및 퀄러티가 안나와서 다시 개발을 하기로 맘을 먹었지용.. (뜯어 고치는 수준이 아니라 아예 첨부터...개발 ㄱㄱㄱ)

그래서 그런지 3번의 큰 소스 뒤업기를 통한 결과가..다들 만족 스러워한다는..

 

풀 렌더링의 목표는 퍼포먼스! 최적화!

일단 풀들은 여러 종류의 풀이 있듯이 Texture가 여러개가 있지용.. 매번 렌더링 타임때 Texture를 로드해서 풀을 렌더링하기엔 빡실듯 하여 Composite Texture를 사용하기로 결정~!

 

 

요렇게 한장의 Texture에 풀 이미지들을 다 모아서 관리하도록 ~!!

 

두번째로는 풀은 같은 모양의 아이로 반복되어 그려지고 있기때문에 Instancing 을 사용하도록 하였지요. 그러나 여기서도 문제가.. Instancing에는 Shader Instancing과 Constant Instancing, 또 하나 더 있는데 까먹었어용.. 아무튼 Shader Instancing과 Constant Instancing 두개 중 하나를 사용을 하기로 했었는데 Shader Instancing은 크기가 각각 틀린 풀들을 따로 처리하기가 빡세서 Constant Instancing을 사용하기로 했지요.. 결과적으로 풀을 많이 뿌려도 왠만한 FPS를 기대 할 수 있다는.. ^-^

 

결과~!

 

보나스 에피소드 : 원래는 안움직이는 풀을 만들려고 했으나.... 누군가의 압박으로 "요새 어떤 게임이 풀이 안움직이냐~ WOW를 봐라 풀이 움직인다~" 라고 해서 자연스럽게 움직이도록 다시 만들었지요... 그러나 열심히 알아본 결과 WOW에서 풀은 안움직인다는...ㅡㅡ;;; (제가 알아봤을땐 안움직이는데~ 움직이나용~? 미스테리라는..)

'Or.......... > Work' 카테고리의 다른 글

Scene Graph Rendering  (0) 2009.08.27
kd-tree Introduction  (0) 2009.08.27
Water Rendering  (0) 2009.08.27
Flight Simulator : HUD - LCOSS  (0) 2009.08.27
Line - Line Intersect  (0) 2009.08.27
,

Water Rendering

from Or........../Work 2009. 8. 27. 14:53

Water Rendering

 

물 관련해서 요번에 만든거다.

Terrain 관련 패치 기반을 가지고 있으면서도 좀 더 Water만의 특성을 살리면서 작업했다. (효율적인 렌더링을 위해서....) 까보고 보면 Terrian 패치와 틀은 비슷하지만 전혀 다른 놈이다.. 일단 Vertex도 LOD를 안하기 때문에 4개만 가지고 있고 (Index도 마찬가지) 그러면 퀄러티를 높여야했다.

 

(1차 작업 : Water Texture에 많은 의존을 두었다. - 고로 Water Texture가 좋을 수록 퀄러티는 좋아진다는 ㅡㅡ;;;)

캡쳐사진이라 그런지 물 출렁거림이 잘 안보인다. Shader로 작업했건만.. ㅡㅡ; 그래서 좀더 물 퀄러티를 높이고자 Bump맵핑을 시도하였다. 좀 더 멋지게 작업하고자.. 물 다운 물을 만들고자 Light도 먹고.. 뭐 Texture에 의존하지 말고 Light로 인해 좀 더 멋진 물을 만들 필요가 있었다.

그래서 열심히 작업한 결과~!

(2차 작업 결과 : 1차보단 만족스럽게 나왔다. 물 같기도 하고..ㅡㅡㅋ)

두번째 작업하면서 늘어난 기술은 Shader 디버깅과 nVidia FX Composer 툴 기술 밖에 ㅡㅡㅋㅋ 여하튼 또 켑쳐 사진이라 보이진 않겠지만 두개의 Bump Map을 가지고 짬뽕 시켜서 물이 출렁 출렁 되겠금 만들었다. 

'Or.......... > Work' 카테고리의 다른 글

Scene Graph Rendering  (0) 2009.08.27
kd-tree Introduction  (0) 2009.08.27
Grass Rendering  (0) 2009.08.27
Flight Simulator : HUD - LCOSS  (0) 2009.08.27
Line - Line Intersect  (0) 2009.08.27
,