[DX11 입문 제22장] AmbientOcclusionApp 예제 잘못된 부분이 있는 것 같습니다.

GPG 시리즈 관련 질답, 논의 공간.

운영자: 류광

Post Reply
비회원

AmbientOcclusionApp 예제 잘못된 부분이 있는 것 같습니다.

전체글 글쓴이: 비회원 » 2016-10-04 15:51

오탈자는 아니고요.
http://www.d3dcoder.net/d3d11.htm
여기서 새로 다운받아서 해봐도 마찬가지입니다.

"skull.txt"모델텍스트파일에서 정점 정보를 가져올때.
Chapter 22 Ambient Occlusion\AmbientOcclusion\Models\skull.txt
에 있는 파일에는 정점이 위치(Pos)와 법선정보(Normal)와 인덱스정보(indices)만 있습니다.
주변광정보?(AmbientAccess)는 없죠.
이 정보는 BuildVertexAmbientOcclusion()함수를 통해 구해오는걸로 알고 있는데요.

문제는 BuildSkullGeometryBuffers()함수에서 "skull.txt"를 통해 버텍스정보를 가져올때
vertices.AmbientAccess이 값의 초기화가 안되어 있습니다. 즉 마이너스쓰레기값이 들어있고

주변광차폐값을 구하는 BuildVertexAmbientOcclusion()에서
초기화 되지 않은 vertices.AmbientAccess값(마이너스 쓰레기값)에다가
float ambientAccess = numUnoccluded / NumSampleRays; 구해진
vertices[i0].AmbientAccess += ambientAccess; 처럼 ambientAccess을 더하니
해골모델이 그냥 검정색으로만 나옵니다..

그래서 BuildSkullGeometryBuffers() 부분에
for(UINT i = 0; i < vcount; ++i)
{
fin >> vertices.Pos.x >> vertices.Pos.y >> vertices.Pos.z;
fin >> vertices.Normal.x >> vertices.Normal.y >> vertices.Normal.z;

vertices.AmbientAccess = 0.0f; // <-- 이부분
}

AmbientAccess을 초기화해주었던..
책에 있는 그림처럼 날 나왔습니다.
제가 찾은게 맞는지요?..

그리고 SSAO예제도 실행하면 아무것도 안그려지던데..
이부분은 아직 소스를 안봐서 모르겠네요.. 확인해보고 글 올리겠습니다.
하드웨어 성능때문일수도 있겠네요.

사용자 아바타
류광
전체글: 3760
가입일: 2001-07-25 09:00
사는 곳: GPGstudy
연락처:

전체글 글쓴이: 류광 » 2016-10-04 19:50

논리적으로는 비회원님 지적이 맞습니다. AmbientAccess에 쓰레기 값이 있으면 당연히 결과가 제대로 나오지 않아야 합니다. 그러나... 디버거로 살펴보니 해당 for 문에 진입하기 전에 이미 AmbientAccess들이 0.0f으로 되어 있네요. std::vector 생성 시 구조체 멤버들이 자동으로 0으로 초기화된 것으로 보이는데요(구조체의 기본 생성자가 멤버들을 0으로 또는 멤버 형식의 기본 생성자로 초기화하는 게 아마 C++ 표준에 맞는 방식일 겁니다). 디버거로 한 번 살펴 보시고요. 만일 쓰레기 값들이 들어 있다면, VS의 어떤 최적화 설정 때문에 구조체의 멤버가 자동으로 0으로 초기화되지 않는 걸 수도 있습니다.

사용자 아바타
류광
전체글: 3760
가입일: 2001-07-25 09:00
사는 곳: GPGstudy
연락처:

전체글 글쓴이: 류광 » 2016-10-04 19:59

잠깐 검색해 보니 VS 2010까지는 멤버 초기화 관련해서 버그가 있었네요: http://stackoverflow.com/questions/3931 ... 89#3931589

비회원

개발 환경은 VS2015입니다.

전체글 글쓴이: 비회원 » 2016-10-05 08:20

이상하군요.. 류광님 말씀이 맞는데요..
std::vector<Vertex::AmbientOcclusion> vertices(vcount);
이런식으로 초기화시 vcount만큼 0으로 초기화 되는게 맞는데...

제 컴파일러에서 더버깅해보면 쓰레기값이 들어가네요..
그래서

struct AmbientOcclusion2
{
int na;
float fa;
float fb;
};

구조체를 하나 정의해서 해보니 0.0으로 잘 초기화 되더군요..
이상하다 싶어서 구조체에

struct AmbientOcclusion2
{
int na;
float fa;
float fb;
XMFLOAT3 Pos;
};

XMFLOAT3 변수를 추가하니
std::vector<Vertex::AmbientOcclusion2> vTemp(vcount);
디버깅하니 쓰레기값이 들어갑니다.

이게 최적화옵션문제는 아닌 것 같은데..
아니면, 문법적 오류나 버그.. 라고도 할 수 없고...
제 환경에서만 이런 문제가 발생한다면.. 아마 컴파일러 문제일 가능성이 크겠지요..
환경은 아무튼 vs2015에서 플랫폼도구집합을 Visual Studio 2013 (v120)로 설정하고 컴파일합니다.

비회원

그리고..

전체글 글쓴이: 비회원 » 2016-10-05 08:29

추가로 테스트해본거 말씀드리자면..

구조체안에 구조체변수(ex, XMFLOAT3)가.. 생성자가 정의된 구조체변수일경우에만 이런 문제가 발생합니다.

구조체안에 구조체변수가 있어도 그 구조체가 생성자가 없는 구조체이면 정상적으로 0으로 초기화됩니다.

사용자 아바타
류광
전체글: 3760
가입일: 2001-07-25 09:00
사는 곳: GPGstudy
연락처:

전체글 글쓴이: 류광 » 2016-10-06 14:35

사용자 정의 생성자가 없으면 컴파일러가 기본 생성자를 만들어 주고, 그 기본 생성자는 기반 클래스들과 멤버들에 대해 각각 해당 기본 생성자를 호출한다... 정도로 알고 있었는데(그렇다면 사용자 정의 생성자가 있는 XMFLOAT3 멤버를 추가해도 int, float 등은 여전히 0이 되어야 하는데요) 좀 더 복잡한 사정이 있나 봅니다. 그러고 보니 Effective C++ 시리즈나 뭐 그런 쪽 책에서 본 것 같기도 하고요. 어쨌든 명시적으로 초기화해 주는 것이 컴파일러 간 차이 문제도 피하고 코드의 의도도 명확해지니 바람직하겠습니다.

Post Reply