2024년 11월 17일 일요일

소멸자(Destructor) 테스트

 

프로그램 종료할 때 마다 가끔 오류가 난다든지 있어서

한번 테스트 해본 결과,

소멸자가 실행 안되고 그대로 종료



테스트는 소멸자에 텍스트 파일 하나 

출력하게 하는 걸로 함


원인은 Visual Studio의 빨간 네모 버튼인 디버깅 중지 버튼


콘솔에서 Ctrl+c 누르거나

콘솔 창 X버튼을 누를 경우 소멸자가 실행 안되는 결과가 나옴


반대로 윈도우 창의 X버튼을 누른경우에는 소멸자가 정상 작동하였음


2024년 11월 3일 일요일

DirectX11 Tutorial - Reflect

 반사 구현

원본 모델을 그리고, 반사된 위치에 한 번 더 그리는 원리

이를 거울영역으로 잘라내서 거울에 반사된 것처럼 보이게 함


거울면을 마스킹 영역으로 하여

반사된 화면과 겹치는 부분만 통과시켜 그림


깊이스텐실 테스트 설정

{//거울용
	D3D11_DEPTH_STENCIL_DESC maskDesc;
	ZeroMemory(&maskDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));

	maskDesc.DepthEnable = true;
	maskDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
	maskDesc.DepthFunc = D3D11_COMPARISON_LESS;

	maskDesc.StencilEnable = true;
	maskDesc.StencilReadMask = 0xFF;
	maskDesc.StencilWriteMask = 0xFF;

	maskDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	maskDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	maskDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
	maskDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	maskDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	maskDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	maskDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
	maskDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	result = m_device->CreateDepthStencilState(&maskDesc, &m_maskState);
	if (FAILED(result))
	{
		return false;
	}


	D3D11_DEPTH_STENCIL_DESC mirrorDesc;
	ZeroMemory(&mirrorDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));

	mirrorDesc.DepthEnable = true;
	mirrorDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	mirrorDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;

	mirrorDesc.StencilEnable = true;
	mirrorDesc.StencilReadMask = 0xFF;
	mirrorDesc.StencilWriteMask = 0xFF;

	mirrorDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	mirrorDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	mirrorDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	mirrorDesc.FrontFace.StencilFunc = D3D11_COMPARISON_EQUAL;

	mirrorDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	mirrorDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	mirrorDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	mirrorDesc.BackFace.StencilFunc = D3D11_COMPARISON_EQUAL;

	result = m_device->CreateDepthStencilState(&mirrorDesc, &m_mirrorState);
	if (FAILED(result))
	{
		return false;
	}
}


두 스텐실 설정을 각각

거울 그릴때랑 반사 공간을 그릴때 전환하면됨


거울이랑 모델 렌더링 하는 부분

{
	XMMATRIX modelWorld, view, proj;
	
	m_CameraClass->Render();
	m_Direct3D->GetProjectionMatrix(proj);
	m_CameraClass->GetViewMatrix(view);
	modelWorld = XMMatrixIdentity();

	//오리지널 모델 그리기
	m_ShaderManager->GetTextureShader()->Render(m_Direct3D->GetDeviceContext(), modelWorld, view, proj);
	m_rectangle->Render(m_Direct3D->GetDeviceContext());

	//마스킹 영역을 생성하기 위한 스텐실 설정으로 전환
	m_Direct3D->TurnMask();

	//거울 위치&회전 월드 매트릭스
	XMMATRIX mirrorWorld;

	//적당한 위치로 설정
	mirrorWorld = XMMatrixIdentity() * XMMatrixRotationX(XM_PI/2) * XMMatrixTranslation(0.0f, -0.7f, 0.0f) * XMMatrixScaling(2,2,2);

	//거울 렌더링
	m_ShaderManager->GetColorShader()->Render(m_Direct3D->GetDeviceContext(), mirrorWorld, view, proj);
	m_mirror->Render(m_Direct3D->GetDeviceContext());

	//거울의 정점 3개
	XMVECTOR pos1, pos2, pos3;

	pos1 = XMVectorSet(-1.0f, -1.0f, 0.0f, 0);
	pos2 = XMVectorSet(-1.0f, 1.0f, 0.0f, 0);
	pos3 = XMVectorSet(1.0f, -1.0f, 0.0f, 0);

	//거울의 위치&회전을 정점에 적용
	pos1 = XMVector3Transform(pos1, mirrorWorld);
	pos2 = XMVector3Transform(pos2, mirrorWorld);
	pos3 = XMVector3Transform(pos3, mirrorWorld);

	//정점을 토대로 면 방정식을 생성
	XMVECTOR plane = XMPlaneFromPoints(
		pos1,
		pos2,
		pos3
	);

	//반사 행렬을 이용하여 모델이 반사되는 위치를 계산
	XMMATRIX reflectMat = modelWorld * XMMatrixReflect(plane);
	
	//마스킹 영역으로 잘라낼 화면을 렌더링하기 위해 다시 설정 전환
	m_Direct3D->TurnMirror();

	//반사된 위치&회전으로 거울 공간에서의 모델을 렌더링
	m_ShaderManager->GetTextureShader()->Render(m_Direct3D->GetDeviceContext(), reflectMat, view, proj);
	m_rectangle->Render(m_Direct3D->GetDeviceContext());

	//다시 원래 스텐실 설정으로 되돌림
	m_Direct3D->ResetDepthStencilState();
}

거울 그릴때는 마스킹 설정으로 바꾸고 

반사면을 한번 렌더링 해준다.


거울의 정점을 빌려와서 거울의 위치 및 회전을 반영한 정점으로

면 방정식을 계산해주는데

XMMatrixReflect 함수로 반사행렬을 생성해준다.

마지막으로 원본 모델의 월드 행렬을 곱하면 반사된 위치가 나옴


참고로 스텐실도 초기화 해줘야 함, 깊이는 ㄴㄴ




결과



궁금해서 깊이도 같이 초기화 해봤는데 거울이 원본 모델을 가림

c++ thread.h

 c++에서 쓰레드 돌릴려면 thread.h 헤더를 쓰면 되는데 이 친구는 쓰레드가 아직 실행 중인지, 아니면 강제 종료하거나 하는 함수가 없어서 조금 아쉬운 애다. std::thread 는 로컬 변수로 선언하든 new 동적 할당을 하든 start 함...