레이블이 Computer Graphics인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Computer Graphics인 게시물을 표시합니다. 모든 게시물 표시

2009년 3월 26일 목요일

Occlusion culling

occlusion culling

HW query 이용한 방식 : 하드웨어로 부터 그려진 픽셀의 개수를 얻을수 있음을 이용
- Occluder 바운딩박스 draw
- 오브젝트 바운딩을 그린후 query. 값이 0 이 아닐경우 실제 오브젝트 그린다.

쿼리를 위한 바운딩을 그릴때에는 zwrite & color off.


Ref.
http://www.gamasutra.com/features/19991109/moller_haines_01.htm
http://www.gamedev.net/reference/programming/features/occlusionculling/default.asp

2009년 1월 29일 목요일

Global terrain

행성(또는 지구) 전체의 지형을 표현하기위해선 구형태에 맞는 메쉬및 텍스쳐링이 필요하다
여러 방법이 있겠지만 기존 mmorpg에서 많이 사용되고 있는 하이트필드 & 쿼드트리 구조를 사용하고자 하면 지구를 위도/경도 방식으로 분할하여 각 지역에 기존의 맵을 매치 시키는것이 적합하다고 생각된다
하지만 이방법의 가장 큰 단점은 극지방으로 갈수록 왜곡이 심해지며 극지방의 표현이 어렵다는 것이다
위도/경도분할이 아닌 3ds max 지오스피어같은 삼각형 메쉬를 이용하면 왜곡의 정도를 줄이고 극지방또한 표현에 문제가 없겠지만 구조가 복잡해지고 이는 구현의 어려움과 실시간 게임, 특히 mmorgp에 적용하기에는 적합하지 않다고 생각된다.
위도/경도 방식을 사용하면서 극지방에 대한 보완방법을 찾아보려했으나 아직까지는 별다른 해법을 찾지못했다. 극지방을 사용하지 않고 그냥 텍스쳐로 처리하는 방법이 현재로선 최선이며 차후 좀더 자료를 찾아보고 생각해봐야겠다.
아울러 지형에서 우주로 나갈때 실제 메쉬 오브젝트 LOD -> 텍스쳐로 변경하여야 될듯한데 되도록 표가안나게 하는법, 지형 LOD방식에는 현재 구현된 미리계산된 정해진크기의 LOD 레벨및 연결부위사용 대신 실시간적으로 분할하는 ROAM과 같은 방식도 고려해 봐야 한다. 뭐 역시 나중에 좀더 알아봐야될듯..;;

Reference

http://download.microsoft.com/download/5/6/f/56f5fa07-51a4-4c0d-8a9a-2e8539214f2e/GDC2006_Szofran_Adam_Terrain_v1.doc

2008년 12월 23일 화요일

HLSL알수없는 버그

HLSL 픽셀 쉐이더 코드중

첫번째:
vSample *= tex2D( SSAOSampler, TexCoord ).r;
vSample.x += 1.1f;
return vSample;

두번째:
float4 vSample2 = vSample * tex2D( SSAOSampler, TexCoord ).r;
vSample2.x += 1.1f;
return vSample2;

결과값의 차이는?
첫번째처럼 구현했다가 이상한결과가 나와 몇가지삽질중 두번째처럼 다른변수를 하나더만드니 제대로 나온다.. 뭥미.

개발환경: DirectX SDK April 2007 / VS2005 / WindowsXP

2008년 12월 3일 수요일

Ambient Occlusion 2 - SSAO

Screen Space Ambient Occlusion(SSAO) 은 깊이맵을 이용하여 음영을 계산하는 방법이다
한 픽셀의 음영값은 자신과 그 주변의 깊이값을 비교하여 주변의 깊이값이 작으면(카메라에 가까이있음) 어두워지게 처리한다. 이는 깊이값이 클경우 주변의 오브젝트에 둘러싸여 빛이 차단되었다고 가정하는것인데 실제적으로 3차원의 오브젝트에 적용하기에는 무리가 있다고 본다 (카메라방향의 깊이값 하나만으로는 오브젝트의 모양을 알수없고 빛의 차단여부또한 계산이 불가능)
하지만 그 결과값이 실제와 다르더라도 언뜻 보기에 그럴싸한 그림자가 생기며 계산과정이 단순하기 때문에 게임과 같은 실시간 랜더링을 필요로 하며 정확한 음영을 반영하지 않아도 무리가 없는 프로그램에는 매우 효과적인 방법이라 할수 있다

SSAO 처리과정

1. 재질이 포함된 일반적인 장면 랜더링

2. 깊이값을 텍스쳐로 생성
1번의 과정에서 생성된 Depth buffer를 텍스쳐로 가져오는 방법이 효율적이나 DX9의 경우 직접 가져올수 있는 방법을 제공하지 않으며 depth surface를 사용하더라도 하드웨어에 따라 다른 결과가 나올수있다(nVidia그래픽카드가 문제라는듯..;;)
현재로서는 깊이값 생성을 위한 쉐이더를 작성하여 한번의 패스를 도는방식으로 구현했다
DX10에서는 깊이버퍼를 직접 가져올수 있다하니 좀더 빠른 처리가 가능할것이다

3. 깊이값이 저장된 텍스쳐를 이용하여 음영값을 계산
깊이값 비교시 랜덤한 위치의 값을 취하기 위해 랜덤텍스쳐를 미리 만든뒤 랜덤텍스쳐의 값을 이용해 주위의 깊이값을 얻어온다

3.5 음영값에 블러 적용
선택적인 항목이라 3.5라 했으나 실제적으로 블러를 적용하지 않으면 노이즈가 낀거같은 음영이 생기므로 해야된다 --;

4. 계산된 음영과 1에서 그린 장면을 합성

SSAO 쉐이더 -------------------
(웹에서 찾은건데 출처는 잘 기억이 안난다 ;; 그리고 조금 수정했음)

float sampleRadius = 10.0f; // 주변값샘플링을 위한 반경값
float distanceScale = 500.0f; // Occlusion 강도
float4x4 Projection;

float3 cornerFustrum;

struct VS_OUTPUT
{
float4 pos : POSITION;
float2 TexCoord : TEXCOORD0;
float3 viewDirection : TEXCOORD1;
};

VS_OUTPUT VS(
float4 Position : POSITION, float2 TexCoord : TEXCOORD0)
{
VS_OUTPUT Out = (VS_OUTPUT)0;

Out.pos = Position;
Out.TexCoord = TexCoord;

// 카메라 fustrum의 값. 아래와 같이 계산해서 올려주면 된다
// float farY = (float)tan(m_pCamera->GetFov()*.5f) * m_pCamera->FarPlane();
// float farX = farY * m_pCamera->GetAspectRatio();
//
// D3DXVECTOR3 vCornerFustrum;
// vCornerFustrum.x = farX;
// vCornerFustrum.y = farY;
// vCornerFustrum.z = m_pCamera->FarPlane();
// m_pEffect->SetValue("cornerFustrum", &vCornerFustrum, sizeof(float)*3);

// 카메라에서 바라보는 방향
float3 corner = float3(cornerFustrum.x * Position.x,
-cornerFustrum.y * Position.y, cornerFustrum.z);

Out.viewDirection = corner;
return Out;
}


texture depthTexture;
texture randomTexture;

sampler2D depthSampler = sampler_state
{
Texture = ;
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};

sampler2D RandNormal = sampler_state
{
Texture = ;
ADDRESSU = WRAP;
ADDRESSV = WRAP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};

float4 PS(VS_OUTPUT IN) : COLOR0
{
float4 samples[16] = // 16개의 샘플링을위한 값들
{
float4(0.355512, -0.709318, -0.102371, 0.0 ),
float4(0.534186, 0.71511, -0.115167, 0.0 ),
float4(-0.87866, 0.157139, -0.115167, 0.0 ),
float4(0.140679, -0.475516, -0.0639818, 0.0 ),
float4(-0.0796121, 0.158842, -0.677075, 0.0 ),
float4(-0.0759516, -0.101676, -0.483625, 0.0 ),
float4(0.12493, -0.0223423, -0.483625, 0.0 ),
float4(-0.0720074, 0.243395, -0.967251, 0.0 ),
float4(-0.207641, 0.414286, 0.187755, 0.0 ),
float4(-0.277332, -0.371262, 0.187755, 0.0 ),
float4(0.63864, -0.114214, 0.262857, 0.0 ),
float4(-0.184051, 0.622119, 0.262857, 0.0 ),
float4(0.110007, -0.219486, 0.435574, 0.0 ),
float4(0.235085, 0.314707, 0.696918, 0.0 ),
float4(-0.290012, 0.0518654, 0.522688, 0.0 ),
float4(0.0975089, -0.329594, 0.609803, 0.0 )
};

normalize (IN.viewDirection);
float depth = tex2D(depthSampler, IN.TexCoord).a;
float3 se = depth * IN.viewDirection;

float3 randNormal = tex2D( RandNormal, IN.TexCoord * 200.0 ).rgb;

float finalColor = 0.0f;

for (int i = 0; i < 16; i++)
{
// 랜덤한 값 추출을 위해 샘플값에 랜덤텍스쳐에서 가져온 값을 이용하여 반사벡터를 취한다
// 꼭 반사벡터가 아니어도될거 같아서 몇가지 다른 방법을 취해봤으나 이게 제일보기좋음
float3 ray = reflect(samples[i].xyz,randNormal) * sampleRadius;

float4 sample = float4(se + ray, 1.0f);
float4 ss = mul(sample, Projection);

// 0~1 범위의 uv 공간으로 변환
float2 sampleTexCoord = 0.5f * ss.xy/ss.w + float2(0.5f, 0.5f);
float sampleDepth = tex2D(depthSampler, sampleTexCoord).a;

if (sampleDepth == 1.0)
{
finalColor ++;
}
else
{
// depth > sampleDepth 일 경우 occlusion 적용
float occlusion = distanceScale* max(depth - sampleDepth, 0.0f);
finalColor += 1.0f / (1.0f + occlusion * occlusion * 0.1);
}
}

return float4(finalColor/16, finalColor/16, finalColor/16, 1.0f);
}


technique SSAO
{
pass P0
{
VertexShader = compile vs_3_0 VS();
PixelShader = compile ps_3_0 PS();
}
}

2008년 11월 18일 화요일

Tone mapping

톤맵핑은 전체신의 현재 밝기를 계산하여 전체적인 톤을 조절하는것. .끝 -_-;;
- 전체신의 밝기계산은 다운샘플링을 이용한다
- 기존의 값과 변경되는 값의 변화를 서서히 적용하면 사람 눈의 암(명)적응과 같은 효과를 나타낼수있다
- 사실 구현한지 좀 되서리 구체적인내용까지는 생각나지 않는다 조만간 다시봐야되므로 그때 좀더 추가할것임.

Ambient Occlusion

SHADOW 기법의 하나로 주변광의 적용
주변광의 차단을 계산하여 음영값을 구한다

------------------------------------------------------

GPU Gems Chapter 17
- AO 기본 개념 설명
- 오브젝트의 각 포인트에 대해 랜덤하게 생성된 조명(레이)과의 충돌 검사를 통해 음영계산
  (OUTPUT :수정된 노말 벡터)
- 하드웨어가속  : 실질적인 충돌검사대신 조명의 방향에서 생성된 깊이맵을 이용해 차단판단
하드웨어의 발달은 깊이맵을 빠르게 생성할수 있게 해준다(nVidia예제참고)

-> 실시간(게임)에 사용하기에는 느리다

------------------------------------------------------

GPU Gems 2 Chapter 14

- 메쉬의 각 포인트를 디스크로 단순화한 모델
- 차단(충돌) 검출이 단순화 된다
- nVidia 예제참고

-> GPU Gems 에 소개된 방법보다 빠른 수행속도를 보여준다
    구형의 그래픽카드에서는 여전히 느리다

------------------------------------------------------

Screen Space Ambient Occlusion(SSAO)

- 시각좌표에서의 깊이맵을 이용하여 AO과정 단순화
- 깊이맵은 시각좌표에서의 높이값이므로 주변값들과의 비교를 통해 차단상태를 판단한다
- 근사화 기법으로 오류가능성이 있어보이나 나쁘지 않은 결과을 보여주는 듯하다
- 크라이2엔진, 스타크래프트2등 게임에 적용되고 있음

-> 현재 분석중.. 차후 분석및 구현이 끝난후 추가사항 기록할것



홈