상세 컨텐츠

본문 제목

[3D프로그래밍] 클리핑 관련

프로그래밍 관련/3D,2D DRAW 관련

by AlrepondTech 2018. 6. 25. 17:40

본문

반응형

 

=================================

=================================

=================================

 

 

 

출처: http://3dprog.tistory.com/entry/Etc-2D-%ED%81%B4%EB%A6%AC%ED%95%91

 

 

2d 그래픽 처리중에서 일정영역 밖으로 나가는 부분을 제외하는 기술을 

클리핑

이라고 합니다 

이를 처리하기 위해 필요한 인자는 3개 
코드: 

-------------------------------------------------------------
클리핑영역(입력:const)
대상영역(입력&출력)
원본영역(출력)
------------------------------------------------------------- 

이 필요합니다. 

간단히 알고리즘을 알아보면 
코드: 

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

if

 대상영역이 클리핑 영역을 완전히 벗어나는가?:

return

; # 출력 안함

else

: # 그렇지 않다면 클리핑영역에 걸쳐있거나 안에 있는것이다

if

 대상영역오른쪽이 클리핑영역오른쪽에 걸치는가?:
원본영역오른쪽=클리핑영역오른쪽-대상영역왼쪽

else


원본영역오른쪽=대상영역오른쪽-대상영역왼쪽

if

 대상영역왼쪽이 클리핑 왼쪽영역에 걸치는가?
원본왼쪽=클리핑왼쪽-대상왼쪽;
대상왼쪽=클리핑왼쪽

else

:
원본왼쪽=0;
-------------------------------------------------------------
위아래쪽도 같은 왼쪽오른쪽처리와 같다 

실제 예를 들어 상황에 대입해보면 
코드: 

예) clip(0~600)

if

 

dst

(100~500):
src.right=500-100=400;
-> 

dst

(100, 500), src(0, 400)

if

 

dst

(100~700):
src.right=600-100=500
dst.right=clip.right=600;
-> 

dst

(100, 600), src(0, 500)

if

 

dst

(-100, 300):
src.right=300-(-100)=400
src.left=0-(-100)=100
dst.left=0
-> 

dst

(0, 300), src(100, 400)

if

 

dst

(-200, 800):
src.right=600-(-200)=800;
dst.right=600;
src.left=0-(-200)=200;
dst.left=0;
-> 

dst

(0, 600), src(200, 800)

이런식이 된다


코드: 

bool

 

IsClipRange

(

long

 leftClip, 

long

 rightClip, long leftDst, 

long

 rightDst)
{

if

 (leftDst > rightClip)
return false;

if

 (rightDst < leftClip)
return false;

return

 true;
}

bool

 

GetClipSourceRange

(

long

 leftClip, 

long

 rightClip, 

long

& rLeftDst, 

long

& rRightDst, 

long

* pRetLeftSrc, 

long

* pRetRightSrc)
{

if

 (!

IsClipRange

(leftClip, rightClip, rLeftDst, rRightDst))

return

 false;

if

 (rRightDst > rightClip)
{
*pRetRightSrc = rightClip - rLeftDst;
rRightDst = rightClip;
}

else


{
*pRetRightSrc = rRightDst - rLeftDst;
}

if

 (rLeftDst < leftClip)
{
*pRetLeftSrc = leftClip - rLeftDst;
rLeftDst = leftClip;
}

else


{
*pRetLeftSrc = 0;
}

return

 true;
}

bool

 

GetClipSourceRect

(

const RECT

& c_rrcClip, 

RECT

& rrcDst, 

RECT

* prcRetSrc)
{

if

 (!

GetClipSourceRange

(c_rrcClip.left, c_rrcClip.right, rrcDst.left, rrcDst.right, &prcRetSrc->left, &prcRetSrc->right))

return false

;

if

 (!

GetClipSourceRange

(c_rrcClip.top, c_rrcClip.bottom, rrcDst.top, rrcDst.bottom, &prcRetSrc->top, &prcRetSrc->bottom))

return

 false;

return true

;
}

출처: http://3dprog.tistory.com/entry/Etc-2D-클리핑 [3D 프로그래밍]

 

 

=================================

=================================

=================================

 

 

 

반응형

 

 

728x90

 

 

 

출처: http://sugame.tistory.com/203

 

 

소프트웨어 렌더링 - 3. 직선 클리핑

직선을 이루는 2점이 화면 바깥에 있는경우에는 화면끝에서 잘라줘야됩니다.  직선 클리핑은 대부분 많이 사용하는 코헨-수더랜드(Cohen-Sutherland) 알고리즘에 대해서 설명하겠습니다.
이 알고리즘은 직선을 이루는 2점의 위치를 파악하여 그 점이 화면 바깥에 있을경우 직선의 기울기를 구하여 직선과 화면영역과의 교점을 구하여 화면 안쪽으로 점을 바꿔주는것입니다. 

 

 


그림에서 점p1은 0x1000위치에 있고 점p2는0x0010위치에 있습니다.

 

점p1의 y값에 대한 화면역역의 교점은 0입니다. x값은 직선의 기울기를 구하여 화면영역의 교점을 찾습니다new_x = p1.x + -p1.y * (p2.x - p1.x) / (p2.y - p1.y ) + 0.5f현재 x위치에 x값이 교점까지 진행한 길이 만큼 더해준 것 입니다. -p1.y는 0x1000위치는 y값이 음수이기때문에 양수로 바꾼것이고 0.5를 더 한것은 new_x가 정수형이기때문에 반올림을 하기 위한 것입니다.p2도 위와 같은방법으로 구하여 주면됩니다.그리고 각각 위치에 따라 특성이 다르기때문에 switch문으로 각각의 위치에 따라 다르게 코딩을 해야합니다.

 

알고리즘 정리 

1. 점p1, p2의 위치를 찾는다. 

2. 점p1과 p2의 위치가 둘다 0x0000 이면 화면영역안에 점이 있는것이기때문에 클리핑할필요없이 함수를 빠져나간다. 

3. 두 점이 둘다 화면바깥에 있고 직선이 화면영역을 걸치지 않는경우는 그릴필요가 없기때문에 함수를 빠져나간다. 

4. 점p1부터 클리핑을 해준다. switch문으로 0x0001, 0x0002, 0x0004, ... 0x1010의 경우를 따로따로 구현한다. 

5. 클리핑된 점을 점p1, p2에 대입한다.
소스가 약간 길기 때문에 첨부된 소스를 참고하시기 바랍니다. 



출처: http://sugame.tistory.com/203 [프로그래밍 저장소]

 

 

04_ClipLine.zip
다운로드

 

 

 

=================================

=================================

=================================

 

 

출처: http://gpgstudy.com/forum/viewtopic.php?t=19541

 

 

소프트웨어 렌더러를 만드는 중입니다.

클리핑에 관해 의문점이 있어서 질문드립니다.

리얼 타임 렌더링 2판 39쪽에서 클리핑은 투영을 한 뒤, (-1 ~ +1)정규 시야 영역에서 수행한다고 나와있습니다. 

그에 반해 DirectX9를 이용한 3D GAME 프로그래밍 입문 (흔히들 말씀하시는 용책) 114페이지에서는 
투영 전에 절두체 평면으로 클리핑을 한다고 되어있습니다.

 


위가 리얼 타임 렌더링 아래가 용책입니다.

간단히 말해 "클리핑은 투영 전? 투영 후? 언제 해야 하는가?"가 궁금합니다.

제가 생각하기에는 용책에서 말한 것 과 같이 투영 전에 절두체 평면으로 잘라야 한다고 생각하는데요.

 



단적인 예로 위에 그림 처럼 정점 하나가 원점에 있는 삼각형 123을 클리핑하면 3이 제거 되고 
(녹색으로 표시된)4, 5가 추가되야 하는데
1과 5는 카메라에서 바라보는 한 직선상에 있기 때문에 정규 시야 영역에서 x좌표가 같은 
녹색 점에 있어야 합니다. 2와 4도 마찬가지고요.

하지만 투영 후 정규 시양 영역에서 잘라버리면 녹색이 아닌 빨간 점이 추가되버리거든요.
(정점1, 2는 당연히 정규 시야 영역안에 있을 테고요 
정점 3의 투영 전 좌표는 0, 0, 0, 1이므로 투영 후에는 0, 0, -2nf / f-n , 0 이 되니까 
z축 위에 있게 됩니다)

설명하기 쉽게 점 하나가 원점에 있다고 가정했지만 굳이 원점에 있지 않아도
비슷한 오류가 생기며 이런 오류가 안 생기려면 투영 전에 클리핑을 해야 한다고 생각합니다.

제 생각에 오류가 있거나 답을 알고 계신다면 꼭 알려주시기 바랍니다.
 
비회원

 

전체글 글쓴이: 비회원 » 2008-04-23 16:45

d3d나 ogl에서는 World - View - Projection 을 곱한 후, w로 나누기 전의 공간인 동차공간에서 backface-culling과 clipping을 수행합니다. 


동차공간 클리핑에 관해서는 'homogeneous clipping'로 구글사마께 물어보세요. 

간단히 설명하면 

투영 공간에서는 
-1 <= x/w < 1 요렇게 되는데 

동차 공간에서는 
-w <= x < w 이니까 

w 기준으로 4차원상에서 클리핑을 수행하는 겁니다.
 
rOseria
전체글: 31
가입일: 2006-11-04 08:35
사는 곳: 현재 A 모사

소프트웨어 렌더러 상에서 구현해주는 것이라면, 전자겠죠.

전체글 글쓴이: rOseria » 2008-04-23 19:05

리얼 타임 렌더링 2판 39쪽에서 클리핑은 투영을 한 뒤, (-1 ~ +1)정규 
시야 영역에서 수행한다고 나와있습니다.
이 클리핑은 레스터라이즈 될 때, 화면 밖을 벗어나거나/걸쳐지거나 near - z 평면 뒤로 넘어가서
 뒤집히는 경우를 방지하기 위해서 하는 것입니다.
그에 반해 DirectX9를 이용한 3D GAME 프로그래밍 입문 (흔히들 말씀하시는 용책) 114페이지에서는 
투영 전에 절두체 평면으로 클리핑을 한다고 되어있습니다.
이것은 컬링이라고 말하기도 합니다.

소프트웨어 렌더러를 만드실 때 구현하는 클리핑은 전자인 것으로 할고 있습니다.
windows Genuine user -
 
비회원

 

전체글 글쓴이: 비회원 » 2008-04-23 22:26

투영 이전, 투영 이후 클리핑 하는 것은 가능할겁니다. 계산 방법이 틀릴 뿐이지요.

클리핑 볼륨과의 충돌지점을 계산한 후에 충돌이 일어날 경우 삼각형을 여러 개로 분할하게 되는데요.

투영 이전에 하면 충돌지점에 대한 단순한 비례식만으로 분할로 인한 폴리곤 각 변의 길이와 
정점들에서의 Z값이 계산이 됩니다만, 투영 이후에 하면 비례식에 덧붙여서 투영으로 인한 Perspective 변환이 
추가로 고려되어야 원하는 클리핑을 이룰 수 있습니다.

제가 잘못알고 있는 것인지는 몰라도, 투영 이후에 해도 된다고 책에 써놓은 것은 실제로 만들어보지도 않고 
무책임하게 써 놓은 것 같습니다. 제가 잘못한 것일지는 몰라도 책 보고 그렇게 했다가 하루 정도 까먹었습니다.

투영 이전에 클리핑 하는 것을 추천드립니다.
 
teminhong
전체글: 5
가입일: 2005-08-24 02:37

 

전체글 글쓴이: teminhong » 2008-04-24 17:58

투영후, 투영 전 둘 다 가능하고 
투영 후에 하려면 정규화 이전에 해야 하는군요.
답변 해주신 분들 감사합니다.

 

 

 

 

 

 

 

 

=================================

=================================

=================================

 

 

반응형


관련글 더보기

댓글 영역