프로그래밍 공부

전체 글 700

카테고리 설명
프로그래밍 공부하는 블로그
  • 진행중인 작업 UI 3. 핸드, 상점, 전장 UI 생성 진행 예정 작업 객체 진영 생성시 객체 위치 전투 생성시 객체 위치 전투 AI 1. 전투로직 2. 스킬로직 그외 투사체 마우스 위치에 따른 카메라 이동 전투시 자동카메라 이동 설정 적 난이도 생성 상점 카드 생성 완료된 작업 UI 텍스트 출력엔진 생성 텍스트 출력엔진의 외곽선 생성 쉐이더 UI 1. 팝업바 생성 2. 상태창 생성 버튼 기본 생성 기본 마우스 포인터 연동 캐릭터 사망시 삭제처리 연동 HP 표시 [ HP바 재처리 ] 데미지 연산중복 처리 데미지 연산 ( 객체질량 * 운동량 ) OBB충돌처리 각 객체간 부모자식관계 재처리 객체 공격 딜레이 공격시 오브젝트 회전처리 객체 공격 객체 이동 애니메이션 재생 객체 생성 문자 출력 까지는 좋으나, ..

  • 진행중인 작업 UI 3. 핸드, 상점, 전장 UI 생성 진행 예정 작업 객체 진영 생성시 객체 위치 전투 생성시 객체 위치 전투 AI 1. 전투로직 2. 스킬로직 그외 투사체 마우스 위치에 따른 카메라 이동 전투시 자동카메라 이동 설정 적 난이도 생성 상점 카드 생성 완료된 작업 UI 텍스트 출력엔진 생성 텍스트 출력엔진의 외곽선 생성 쉐이더 UI 1. 팝업바 생성 2. 상태창 생성 버튼 기본 생성 기본 마우스 포인터 연동 캐릭터 사망시 삭제처리 연동 HP 표시 [ HP바 재처리 ] 데미지 연산중복 처리 데미지 연산 ( 객체질량 * 운동량 ) OBB충돌처리 각 객체간 부모자식관계 재처리 객체 공격 딜레이 공격시 오브젝트 회전처리 객체 공격 객체 이동 애니메이션 재생 객체 생성 텍스트 출력시 hlsl의 이..

  • 진행중인 작업 UI 3. 핸드, 상점, 전장 UI 생성 진행 예정 작업 객체 진영 생성시 객체 위치 전투 생성시 객체 위치 전투 AI 1. 전투로직 2. 스킬로직 그외 투사체 마우스 위치에 따른 카메라 이동 전투시 자동카메라 이동 설정 적 난이도 생성 상점 카드 생성 완료된 작업 UI 텍스트 출력엔진 생성 UI 1. 팝업바 생성 2. 상태창 생성 버튼 기본 생성 기본 마우스 포인터 연동 캐릭터 사망시 삭제처리 연동 HP 표시 [ HP바 재처리 ] 데미지 연산중복 처리 데미지 연산 ( 객체질량 * 운동량 ) OBB충돌처리 각 객체간 부모자식관계 재처리 객체 공격 딜레이 공격시 오브젝트 회전처리 객체 공격 객체 이동 애니메이션 재생 객체 생성 UI 의 텍스트를 출력하기 위해 텍스트 출력 엔진을 구축하였다. ..

  • 진행중인 작업 UI 텍스트 출력엔진 생성 진행 예정 작업 객체 진영 생성시 객체 위치 전투 생성시 객체 위치 전투 AI 1. 전투로직 2. 스킬로직 UI 3. 핸드, 상점, 전장 UI 생성 그외 투사체 마우스 위치에 따른 카메라 이동 전투시 자동카메라 이동 설정 적 난이도 생성 상점 카드 생성 완료된 작업 UI 1. 팝업바 생성 2. 상태창 생성 버튼 기본 생성 기본 마우스 포인터 연동 캐릭터 사망시 삭제처리 연동 HP 표시 [ HP바 재처리 ] 데미지 연산중복 처리 데미지 연산 ( 객체질량 * 운동량 ) OBB충돌처리 각 객체간 부모자식관계 재처리 객체 공격 딜레이 공격시 오브젝트 회전처리 객체 공격 객체 이동 애니메이션 재생 객체 생성 UI의 충돌오브젝트 작업과 객체 처리과정을 획일화하여, 모든 객체..

  • 진행중인 작업 UI 2. 상태창 생성 진행 예정 작업 객체 진영 생성시 객체 위치 전투 생성시 객체 위치 전투 AI 1. 전투로직 2. 스킬로직 UI 3. 핸드, 상점, 전장 UI 생성 그외 투사체 마우스 위치에 따른 카메라 이동 전투시 자동카메라 이동 설정 적 난이도 생성 상점 카드 생성 완료된 작업 UI 1. 팝업바 생성 버튼 기본 생성 기본 마우스 포인터 연동 캐릭터 사망시 삭제처리 연동 HP 표시 [ HP바 재처리 ] 데미지 연산중복 처리 데미지 연산 ( 객체질량 * 운동량 ) OBB충돌처리 각 객체간 부모자식관계 재처리 객체 공격 딜레이 공격시 오브젝트 회전처리 객체 공격 객체 이동 애니메이션 재생 객체 생성 UI에 부시버튼과 UI의 자세히보기 창을 구성하고 렌더를 분리하려고 했는데, 헤더파일이..

  • TextureRect::TextureRect(Vector3 position, Vector3 size, float rotation) : position(position), size(size), rotation(rotation) { // vertices { vertices.assign(4, VertexTexture()); vertices[0].position = verticesLocalPosition[0] = Vector3(-0.5f, -0.5f, 0.0f); vertices[1].position = verticesLocalPosition[1] = Vector3(0.5f, 0.5f, 0.0f); vertices[2].position = verticesLocalPosition[2] = Vector3(0.5f,..

작성일
2023. 8. 22. 23:53
작성자
WDmil
728x90

 

D2DGame 2023-08-22 23-43-21.mp4
1.91MB

 

진행중인 작업

UI

3. 핸드, 상점, 전장 UI 생성

 

진행 예정 작업

 

객체

진영 생성시 객체 위치

전투 생성시 객체 위치

 

전투 AI

1. 전투로직

2. 스킬로직

 

그외

투사체

마우스 위치에 따른 카메라 이동

전투시 자동카메라 이동 설정

적 난이도 생성

상점 카드 생성

 

완료된 작업

 

UI

텍스트 출력엔진 생성

텍스트 출력엔진의 외곽선 생성 쉐이더

 

UI

1. 팝업바 생성

2. 상태창 생성

 

버튼 기본 생성

기본 마우스 포인터 연동

캐릭터 사망시 삭제처리 연동

HP 표시 [ HP바 재처리 ]

데미지 연산중복 처리

데미지 연산 ( 객체질량 * 운동량 )

OBB충돌처리

각 객체간 부모자식관계 재처리

객체 공격 딜레이

공격시 오브젝트 회전처리

객체 공격

객체 이동

애니메이션 재생

객체 생성

 

문자 출력 까지는 좋으나, 문자 내부의 숫자값을 계속 변경해주어야할 일이 발생할경우,

이미 만들어져있는 문자의 string값의 uv좌표를 수정하기가 매우 힘들다.

그래서 수정할 수 있는 value를 가진, 숫자출력용 엔진을 만들어야한다.

 

그래서 숫자를 받아왔을 때, 그 숫자를 문자로 변환 -> 문자로 변환된 배열을 미리 만들어놓은 Numberpad TextureRect -123456789 값들중 정해진 값으로 TextureRect로 변환해주는 처리를 해야함.

 

이유는 모르겠지만, TextureRect를 Safe_Delete하게되면, srv까지 같이 날아가서, 정해진 한개의 srv를 사용하는 문자출력엔진에는 알맞이 않았음. 그래서 Safe_Delete를 안하고 할당된 TextureRect만 새롭게 생성한 TextureRect로 변경해주면, 메모리 누수가 심하게 발생함.

 

위 방안을 해결하기 위해서, 문자출력이 아닌, 숫자출력용 텍스트엔진을 따로 제작하여야 했음.

 

현재 출력용 텍스트 엔진을 만들었으나. 좌표기입값을 수정중

struct D3DXNUMBER
{
	D3DXVECTOR3 Startposition;			// 숫자판
	D3DXVECTOR3 Endposition;			// 숫자판 종료 포지션
	Color color;						// 숫자 색상
	Vector3 size;						// 숫자 크기
	int nvectorsize;					// 번호판 사이즈 ( 구조상 넘어가면 표시불가 )
	int sortType;						// 정렬기준이 좌측 중앙 우측인지
	int num;							// 들어있는 숫자
	std::vector<TextureRect*> numstring;	// 숫자 벡터
	std::map<wchar_t, TextureRect*>* numberpad;// 넘버페드 벡터

public:
	void Update() { for (auto def : numstring) def->Update(); } // 숫자 위치좌표 갱신
	void Render() { for (auto def : numstring) def->Render(); } // 숫자 출력

	void Changer_Number(int num) {
		std::wstring numdef = std::to_wstring(num);
		for (int i = 0; i < numstring.size(); i++)
		{
			while (true) {
				if (numstring.size() <= numdef.size()) { // 사이즈가 크거나 같으면 뒤로 빼버린다.
					Endposition.x -= (*numstring.end())->GetSize().x;	//Endposition을 계산해준다.
					numstring.pop_back();
				}
				break;
			}
			
			if(i >= numdef.size()) { // 사이즈 위치에 포지션 가져와서 박아줌.
				TextureRect* numberdef = new TextureRect(*numberpad->find(numdef[i])->second);
				numberdef->SetPosition(numstring[i]->GetPosition());
				numstring[i] = numberdef;
			}
			else {					// 포지션 빼줌.
				TextureRect* numberdef = new TextureRect(*numberpad->find(numdef[i])->second);
				numberdef->SetPosition(Endposition + Vector3(size.x,0,0));
				numstring.push_back(numberdef);
				Endposition += Vector3(size.x,0,0);
			}
		}
	}
private:
	template<typename T>
	D3DXNUMBER operator+ (T x) {
		num += x;
		Changer_Number(num);
	}

	template<typename T>
	D3DXNUMBER operator- (T x) {
		num -= x;
		Changer_Number(num);
	}

	template<typename T>
	D3DXNUMBER operator* (T x) {
		num *= x;
		Changer_Number(num);
	}

	template<typename T>
	D3DXNUMBER operator/ (T x) {
		num /= x;
		Changer_Number(num);
	}
};
D3DXNUMBER FontClass::Makenumberbord(const int number, const Vector3 position, const Color color, const Vector3 stringsize, const int sorting, const int outline)
{
	D3DXNUMBER* result = new D3DXNUMBER;
	std::wstring wsnumber = std::to_wstring(number);

	// 오류체크, 만약 Fontpng가 실행되지 않았을 경우, 폰트 를 다시 잡아준다.
	if (Fontpng == nullptr)
		SetFont("..\\Framework\\GameAsset\\Fontfile\\Base_Font.fnt");

	// 반환값에 문장의 전반 데이터를 기입.
	result->Startposition = result->Endposition = position;
	result->size = stringsize;
	result->color = color;

	// 넘버패드를 안말들었을 경우, 만듬
	if(numberpad.empty()) {
		for (int i = 0; i <10; i++) {
			std::wstring def = std::to_wstring(i);
				// map배열에서 해당되는 숫자의 유니 코드를 찾아온다. 
			auto value = charators.find((int)def[0]);

			// uv의 기준값. 문자의 x위치에 전체 이미지를 나눠주어 전체이미지가 1일경우 x의 값을 구한다. 가로세로길이, y도 같은 방식으로 도출
			std::vector<Vector2>* uv =
				uvInit(value->second->x / fontImagesize.x, value->second->y / fontImagesize.y,
					value->second->width / fontImagesize.x, value->second->height / fontImagesize.y);

			// 문자 사이즈를 백분율하여, 일정한 사이즈로 키워줄 수 있게 한다.
			float Charsizex = value->second->width * 2 / fontsinglesize;
			Vector3 Offset;
			// y를 음수처리하는 이유는 uv 좌표상, y가 반대이기 때문, BMFont 프로그램이 구형이라 offset 좌표가 0,0이 좌상단임.
			Offset = Vector3(value->second->xoffset / 2, -value->second->yoffset / 2, 0);

			Vector3 fontsize = Vector3(value->second->width / fontsinglesize * result->size.x,
				value->second->height / fontsinglesize * result->size.y, 0);
			TextureRect* numpaddef = new TextureRect(Offset, uv, fontsize, 0.0f, result->color, Fontpng);

			numberpad.insert(std::make_pair(def[0], numpaddef));
			// 넘버페드에 숫자를 입력함.
		}

		std::wstring def = L"-";
		// map배열에서 해당되는 숫자의 유니 코드를 찾아온다. 
		auto value = charators.find((int)def[0]);

		// uv의 기준값. 문자의 x위치에 전체 이미지를 나눠주어 전체이미지가 1일경우 x의 값을 구한다. 가로세로길이, y도 같은 방식으로 도출
		std::vector<Vector2>* uv =
			uvInit(value->second->x / fontImagesize.x, value->second->y / fontImagesize.y,
				value->second->width / fontImagesize.x, value->second->height / fontImagesize.y);

		// 문자 사이즈를 백분율하여, 일정한 사이즈로 키워줄 수 있게 한다.
		float Charsizex = value->second->width * 2 / fontsinglesize;
		Vector3 Offset;
		// y를 음수처리하는 이유는 uv 좌표상, y가 반대이기 때문, BMFont 프로그램이 구형이라 offset 좌표가 0,0이 좌상단임.
		Offset = Vector3(value->second->xoffset / 2, -value->second->yoffset / 2, 0);

		Vector3 fontsize = Vector3(value->second->width / fontsinglesize * result->size.x,
			value->second->height / fontsinglesize * result->size.y, 0);
		TextureRect* numpaddef = new TextureRect(Offset, uv, fontsize, 0.0f, result->color, Fontpng);

		numberpad.insert(std::make_pair(def[0], numpaddef));
		// 넘버페드에 -를 입력함.
	}

	// 입력받은 숫자를 확인함.
	for (int i = 0; i < wsnumber.size(); i++)
	{
		TextureRect* numberdef = new TextureRect(*numberpad.find(wsnumber[i])->second);
		numberdef->SetPosition(numberdef->GetPosition() + result->Endposition);
		numberdef->Update();

		Vector3 Offset;
		// y를 음수처리하는 이유는 uv 좌표상, y가 반대이기 때문, BMFont 프로그램이 구형이라 offset 좌표가 0,0이 좌상단임.

		result->numstring.push_back(numberdef);
		result->Endposition.x += result->size.x;
	}

	switch (sorting)
	{
	case RIGHT: // 이 문장은 시작위치 기준 왼쪽으로 발산합니다.
	{
		float sortvectorsizex = (result->Endposition.x - result->Startposition.x); // 전체 문장 길이
		Vector3 sortvector = { sortvectorsizex, 0, 0 };
		for (auto def : result->numstring) {
			if (def->GetPosition().y < result->Startposition.y) // 엔터가 입력되었을 경우,
				sortvector.x = sortvectorsizex; // x를 문장길이 기본 으로 초기화

			Vector3 charX = Vector3(def->GetRect().x / 3.8, 0, 0);

			def->SetPosition(def->GetPosition() - sortvector); // 현재 위치의 단어 길이만큼을 쭉 밀어버림.
			sortvector -= charX;
			// 다음에 왼쪽으로 미는 값은 방금 민 글자의 x사이즈 만큼 줄어들어야 한다.
		}
		break;
	}
	case MIDDLE: 	// 이 문장은 시작위치 가 문장의 중앙입니다.
	{
		float sortvectorsizex = (result->Endposition.x - result->Startposition.x) / 2; // 전체 문장 길이의 반
		Vector3 sortvector = { sortvectorsizex, 0, 0 };
		for (auto def : result->numstring) {
			if (def->GetPosition().y < result->Startposition.y) // 엔터가 입력되었을 경우,
				sortvector.x = sortvectorsizex; // x를 문장길이의 기본의 반절 로 초기화

			Vector3 charX = Vector3(def->GetRect().x / 3.8, 0, 0);

			def->SetPosition(def->GetPosition() - sortvector); // 현재 위치의 단어 길이만큼을 쭉 밀어버림.
			sortvector -= charX;
			// 다음에 왼쪽으로 미는 값은 방금 민 글자의 x사이즈 만큼 줄어들어야 한다.
		}
		break;
	}
	default: // 이 문장은 시작위치 기준 오른쪽으로 발산합니다.
		break;
	}

	return *result;
}

일단 대충만든 숫자출력용 엔진.

실시간으로 출력된 데이터의 숫자값을 바꿀 수 있도록 했음.

728x90
작성일
2023. 8. 21. 03:18
작성자
WDmil
728x90

 

 

진행중인 작업

UI

3. 핸드, 상점, 전장 UI 생성

 

진행 예정 작업

 

객체

진영 생성시 객체 위치

전투 생성시 객체 위치

 

전투 AI

1. 전투로직

2. 스킬로직

 

그외

투사체

마우스 위치에 따른 카메라 이동

전투시 자동카메라 이동 설정

적 난이도 생성

상점 카드 생성

 

완료된 작업

 

UI

텍스트 출력엔진 생성

텍스트 출력엔진의 외곽선 생성 쉐이더

 

UI

1. 팝업바 생성

2. 상태창 생성

 

버튼 기본 생성

기본 마우스 포인터 연동

캐릭터 사망시 삭제처리 연동

HP 표시 [ HP바 재처리 ]

데미지 연산중복 처리

데미지 연산 ( 객체질량 * 운동량 )

OBB충돌처리

각 객체간 부모자식관계 재처리

객체 공격 딜레이

공격시 오브젝트 회전처리

객체 공격

객체 이동

애니메이션 재생

객체 생성

 

 

텍스트 출력시 hlsl의 이해를 잘 못해서 매우 오랫동안 다시 공부해야했다.

그래도 hlsl을 사용하여 그래픽카드와 cpu간의 buffer 전송을 하는방법을 알 수 있었다.

BMFont의 프로그램이 오래되서, Directx11의 기준, 좌표와 offset이 약간 맞지 않는 큰 버그가 있었으나,

텍스트의 기준사이즈와 offset의 값을 노가다를 통해 찾아내서 보정치를 주었다.

 

영문이 출력된 후 한글이 출력되면 문자가 서로 겹치는 버그또한 발생해서 바로 다음문자가 유니코드상 한글일 경우, 자신의 문자 사이즈의 4배만큼 offset을 주도록 처리하니까 해결되었다.

 

문자의 외곽선은 hlsl을 통해, 텍스트의 color처리 과정에서 동시에 처리하게 만들었다.

hlsl의 쉐이더 처리과정을 그 이후에 처리하려고 했는데, 그런 과정을 거치니까 이유를 모르겠지만 엄청난 랙이 유발되서, 피치못하게 한번에 처리할 수 밖에 없었다.

 

외곽선은 문자의 색상이 어두운쪽이면 흰색 밝은쪽이면 검정색이 나타나게 hlsl에서 처리하였다.

 

외곽선의 두께는, 두께값만큼 for문으로 순환하여, 현재 color의 위치좌표기준 상하좌우 대각선의 위치에 이미지 사이즈 보정값 * 원하는 두께의 굵기 만큼의 위치를 전부 순환하여 검사하고. 만약, 샘플링하여서, uv값이 0.8이상인 pixel이 검사 되었을 경우, 설정된 외곽선 color로 설정하게 만들었다.

 

또한, 색상검사시 찾은 color값이 이미 처리했던 외곽선 color와 같을경우 를 확인해야만 했다.

위 검사를 안넣으면, 모든 이미지가 검정색 또는 흰색으로 덮어씌워져 버린다.

 

어차피 문자의 색이 흰색이면 외곽선은 검정이고 검정이면 외곽선은 흰색이기 때문에 문자색을 흰색으로 못하거나 검정으로 못하거나 하지는 않는다.

 

728x90
작성일
2023. 8. 18. 03:21
작성자
WDmil
728x90

 

진행중인 작업

UI

3. 핸드, 상점, 전장 UI 생성

 

진행 예정 작업

 

객체

진영 생성시 객체 위치

전투 생성시 객체 위치

 

전투 AI

1. 전투로직

2. 스킬로직

 

그외

투사체

마우스 위치에 따른 카메라 이동

전투시 자동카메라 이동 설정

적 난이도 생성

상점 카드 생성

 

완료된 작업

 

UI

텍스트 출력엔진 생성

 

UI

1. 팝업바 생성

2. 상태창 생성

 

버튼 기본 생성

기본 마우스 포인터 연동

캐릭터 사망시 삭제처리 연동

HP 표시 [ HP바 재처리 ]

데미지 연산중복 처리

데미지 연산 ( 객체질량 * 운동량 )

OBB충돌처리

각 객체간 부모자식관계 재처리

객체 공격 딜레이

공격시 오브젝트 회전처리

객체 공격

객체 이동

애니메이션 재생

객체 생성

 

 

UI 의 텍스트를 출력하기 위해 텍스트 출력 엔진을 구축하였다.

기존에 있었던 Render 코드를 재활용하여 텍스트 출력이 가능한 생성자 를 추가하고,

출력용 class객체를 추가하였다.

텍스트 엔진에 주석 추가중.

 

텍스트 엔진은 Tinyxml2 와 Bmfont를 사용하여 출력하게 만들었다.

 

hlsl파일에서 color와 uv를 조합하여 uv는 a값만, color는 rgb값만 받아오게 처리하였다.

 

 

728x90
작성일
2023. 8. 15. 23:01
작성자
WDmil
728x90

 

 

진행중인 작업

UI

텍스트 출력엔진 생성

 

진행 예정 작업

 

객체

진영 생성시 객체 위치

전투 생성시 객체 위치

 

전투 AI

1. 전투로직

2. 스킬로직

 

UI

3. 핸드, 상점, 전장 UI 생성

 

그외

투사체

마우스 위치에 따른 카메라 이동

전투시 자동카메라 이동 설정

적 난이도 생성

상점 카드 생성

 

완료된 작업

UI

1. 팝업바 생성

2. 상태창 생성

 

버튼 기본 생성

기본 마우스 포인터 연동

캐릭터 사망시 삭제처리 연동

HP 표시 [ HP바 재처리 ]

데미지 연산중복 처리

데미지 연산 ( 객체질량 * 운동량 )

OBB충돌처리

각 객체간 부모자식관계 재처리

객체 공격 딜레이

공격시 오브젝트 회전처리

객체 공격

객체 이동

애니메이션 재생

객체 생성

 

 

UI의 충돌오브젝트 작업과 객체 처리과정을 획일화하여, 모든 객체의 오브젝트를 GAMEMASTER에서 처리하게 만들었다.

그리하여 헤더의 꼬임없이 정상적으로 데이터 입출력 처리를 할 수 있게 되었다.

그러나, Text출력을 위해 출력엔진을 하나 다시 구축해야한다.

728x90
작성일
2023. 8. 14. 00:09
작성자
WDmil
728x90

 

진행중인 작업

UI

2. 상태창 생성

 

진행 예정 작업

 

객체

진영 생성시 객체 위치

전투 생성시 객체 위치

 

전투 AI

1. 전투로직

2. 스킬로직

 

UI

3. 핸드, 상점, 전장 UI 생성

 

그외

투사체

마우스 위치에 따른 카메라 이동

전투시 자동카메라 이동 설정

적 난이도 생성

상점 카드 생성

 

완료된 작업

UI

1. 팝업바 생성

 

버튼 기본 생성

기본 마우스 포인터 연동

캐릭터 사망시 삭제처리 연동

HP 표시 [ HP바 재처리 ]

데미지 연산중복 처리

데미지 연산 ( 객체질량 * 운동량 )

OBB충돌처리

각 객체간 부모자식관계 재처리

객체 공격 딜레이

공격시 오브젝트 회전처리

객체 공격

객체 이동

애니메이션 재생

객체 생성

 

 

UI에 부시버튼과 UI의 자세히보기 창을 구성하고 렌더를 분리하려고 했는데, 헤더파일이 인식되지 않는 오류가 발생 해결중.

아마 헤더파일을 컴파일 중, 내부에서 객체관계가 위로 올라가는 부분이 있어 무한순환하는 오류가 발생하는걸로 예상

 

728x90
작성일
2023. 8. 11. 17:33
작성자
WDmil
728x90
	TextureRect::TextureRect(Vector3 position, Vector3 size, float rotation)
	: position(position), size(size), rotation(rotation)
{

    // vertices
	{
		vertices.assign(4, VertexTexture());

		vertices[0].position = verticesLocalPosition[0] = Vector3(-0.5f, -0.5f, 0.0f);
		vertices[1].position = verticesLocalPosition[1] = Vector3(0.5f, 0.5f, 0.0f);
		vertices[2].position = verticesLocalPosition[2] = Vector3(0.5f, -0.5f, 0.0f);
		vertices[3].position = verticesLocalPosition[3] = Vector3(-0.5f, 0.5f, 0.0f);

		vertices[0].uv = Vector2(0, 1);
		vertices[1].uv = Vector2(1, 0);
		vertices[2].uv = Vector2(1, 1);
		vertices[3].uv = Vector2(0, 0);
	}

	// Vertex Buffer
	{
		vb = new VertexBuffer();
		vb->Create(vertices, D3D11_USAGE_DYNAMIC);
	}

	// Index Buffer
	{
		indices = { 0,1,2,0,3,1 };

		ib = new IndexBuffer();
		ib->Create(indices, D3D11_USAGE_IMMUTABLE);
	}

	// Vertex Shader
	{
		vs = new VertexShader();
		vs->Create(ShaderPath + L"VertexTexture.hlsl", "VS");
	}

	// Pixel Shader
	{
		ps = new PixelShader();
		ps->Create(ShaderPath + L"VertexTexture.hlsl", "PS");
	}

	// InputLayout
	{
		il = new InputLayout();
		il->Create(VertexTexture::descs, VertexTexture::count, vs->GetBlob());
	}

	// World Buffer
	{
		wb = new WorldBuffer();
	}
}

Vertex Buffer

각 버텍스의 정점을 Buffer로 뭉쳐놓아서 그래픽카드로 전달하기 위한 데이터 뭉치

 

Index Buffer

각 버텍스의 정점간 이어지는 선을 Buffer로 뭉쳐놓아서 그래픽카드로 전달하기 위한 데이터 뭉치

 

Vertex Shader

각 버텍스의 정점을 카메라에 이어주는 쉐이더. 카메라의 위치 기준값의 앞에다가 가져다 놓는 역할을 한다.

 

Pixel Shader

각 버텍스의 픽셀 Color값을 설정해주는 쉐이더. Blob에 각 버텍스의 색정보를 대입하여 설정할 수 있다.

 

Input Layout

버텍스 쉐이더에서 생성한 Blob의 위치좌표를 가져다가 월드버퍼에 대입시켜주는 레이아웃.

 

World Buffer

각 원점정보를 SRT를 사용하여 원하는 위치값에다가 대입시켜주는 버퍼

 

SRV

AddSRV를 사용하여 wstring값의 path를 가져와. 설정하려는 이미지 픽셀이 위치한 png파일을 가지게 되는 역할

 

SETIA

생성된 버퍼를 레지스터에 옮겨주는 역할


Vertex Buffer

class VertexBuffer
{
public:
	~VertexBuffer();

	// 정점 자료형으로 어떤게 들어올지 모르기 때문에 템플릿 사용
	template<typename T>
	void Create(const vector<T>& vertices, const D3D11_USAGE& usage = D3D11_USAGE_DEFAULT);

	ID3D11Buffer* GetResource() { return buffer; }

	uint GetStride() { return stride; }
	uint GetOffset() { return offset; }
	uint GetCount()  { return count;  }

	void SetIA();

private:
	ID3D11Buffer* buffer = nullptr;

	uint stride = 0;		// 정점 버퍼에서 한 정점의 크기를 나타내는 값
	uint offset = 0;		// 버퍼에서 읽기 시작할 위치
	uint count = 0;			// 정점 버퍼에서 읽을 정점 개수
};
template<typename T>
inline void VertexBuffer::Create(const vector<T>& vertices, const D3D11_USAGE& usage)
{
	stride = sizeof(T);		// 정점 크기 저장
	count = vertices.size();	// 정점 개수 저장

	D3D11_BUFFER_DESC desc;							// 버퍼 생성을 위한 구조체 선언
	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));	// 구조체 초기화

	// desc 설정
	{
		desc.Usage = usage;							// 버퍼의 사용 용도 설정
		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;	// 정점 버퍼로 사용함을 정의
		desc.ByteWidth = stride * count;			// 버퍼 크기

		// CPU 접근 설정
		switch (usage)
		{
			case D3D11_USAGE_DEFAULT:
			case D3D11_USAGE_IMMUTABLE:
				break;

			case D3D11_USAGE_DYNAMIC:
				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
				break;

			// CPU에서 접근 가능, GPU에서 사용할 수 있는 형태로 변환 가능한 버퍼
			case D3D11_USAGE_STAGING:
				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
				break;
		}
	}

	// Buffer 생성
	{
		D3D11_SUBRESOURCE_DATA subData;									// 정점 데이터를 담을 구조체
		ZeroMemory(&subData, sizeof(D3D11_SUBRESOURCE_DATA));			// 구조체 초기화

		subData.pSysMem = vertices.data();								// 정점 데이터를 할당한 메모리에 복사

		HRESULT hr = DEVICE->CreateBuffer(&desc, &subData, &buffer);	// 정점 버퍼 생성
		CHECK(hr);	// 생성 실패 시 펑
	}
}

버텍스의 위치좌표와 정점 사이즈를 계산하여 정점 크기를 stride에 저장해놓고,

count 에 정점 개수를 저장한다.

 

그후, 데이터를 삽입할 구조체를 선언한 뒤, 구조체를 zeroMemory로 초기화한다.

 

desc 에 대한 설정값은, 데이터 버퍼의 사이즈, 사용가능 여부, 이게 어떤 버퍼인지 의 값을 대입하게 된다.

 

switch를 사용하여, CPU가 접근이 가능한지, GPU가 접근이 가능한지에 대해 설정해준다.

 

그후, 정점 데이터를 담을 D3D11_SUBRESOURCE_DATA 구조체를 생성해준다음, 초기화 해준다.

 

정점 데이터를 할당된 메모리에 복사한 다음,

DEVICE->CreateBuffer(...)를 통하여, 기입된 데이터의 메모리를 전부 Buffer에 담아 hlsl에 보내준다.

 

즉, 위에 생성한 desc는 버퍼 자체의 헤더에 해당하고, 밑에서 생성한 subData는 실질적인 데이터의 모음이라고 생각하면 된다.


IndexBuffer

// 정점의 인덱스를 저장하는 버퍼

#pragma once

class IndexBuffer
{
public:
	~IndexBuffer();

	void Create(const vector<uint>& indices, const D3D11_USAGE& usage = D3D11_USAGE_DEFAULT);

	ID3D11Buffer* Getresource() { return buffer; }
	uint GetStride() { return stride; }
	uint GetOffset() { return offset; }
	uint GetCount() { return count; }

	void SetIA();

private:
	ID3D11Buffer* buffer = nullptr;

	uint stride = 0;
	uint offset = 0;
	uint count = 0;
};
void IndexBuffer::Create(const vector<uint>& indices, const D3D11_USAGE& usage)
{
	stride = sizeof(uint);
	count  = indices.size();

	D3D11_BUFFER_DESC desc;
	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));

	// desc
	{
		desc.Usage = usage;
		desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
		desc.ByteWidth = stride * count;

		// CPU 접근 설정
		switch (usage)
		{
			case D3D11_USAGE_DEFAULT:
			case D3D11_USAGE_IMMUTABLE:
				break;

			case D3D11_USAGE_DYNAMIC:
				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
				break;

			case D3D11_USAGE_STAGING:
				desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
				break;
		}
	}

	// Buffer 생성
	{
		D3D11_SUBRESOURCE_DATA subData;
		ZeroMemory(&subData, sizeof(D3D11_SUBRESOURCE_DATA));

		subData.pSysMem = indices.data();

		HRESULT hr = DEVICE->CreateBuffer(&desc, &subData, &buffer);
		CHECK(hr);	// 생성 실패 시 펑
	}
}

각 버텍스가 연결되는 선을 만들어주는 역할을 한다.

위의 버텍스 버퍼와 큰 차이점이 없이 Buffer를 생성하는 모습을 확인할 수 있다.

 

Buffer에 들어가는 데이터 포멧들은 전부 uint형임을 확인할 수 있는데,

이는, 각 배열의 숫자가 버텍스의 연결되는 숫자이기 때문이다.

 

어차피 버텍스 정보는 다른 레지스터에 존재하기 때문에 IndexBuffer에는 해당되는 버텍스가 어떤식으로 연결되는지만 나타내주면 되기 때문,


Vertex Shader

// 정점들의 위치, 색상, uv좌표 등의 속성을 계산

#pragma once
#include "IShader.h"

class VertexShader : public IShader
{
public:
	~VertexShader();

	virtual void Create(const wstring path, const string entryName) override;
	virtual void Clear() override;
	virtual void SetShader() override;

	ID3DBlob* GetBlob() { return blob; }
	ID3D11VertexShader* GetResource() { return shader; }

private:
	ID3D11VertexShader* shader = nullptr;
	ID3DBlob* blob = nullptr;
};
void VertexShader::Create(const wstring path, const string entryName)
{
	// 쉐이더 경로와 엔트리 이름을 저장
	this->path = path;
	this->entryName = entryName;

	// 쉐이더 컴파일
	CompileShader(path, entryName, "vs_5_0", &blob);

	// 버텍스 쉐이더 생성
	HRESULT hr = DEVICE->CreateVertexShader
	(
		blob->GetBufferPointer(),
		blob->GetBufferSize(),
		nullptr,
		&shader
	);
	CHECK(hr);
}

쉐이더는 버퍼와 다르게 설정된 hlsl로 이동하여 픽셀데이터를 수정하게 되는데,

그래서 생성자 역할을 하는 Create에서는 해당되는 경로와 해당 hlsl에서 사용하게되는 펑션의 이름을 작성하게 된다.

 

쉐이더 컴파일 시. 경로, 함수이름, 그리고 어떤 버전의 vs로 컴파일하게 되는지. 또한 컴파일된 결과물을 어디에 저장하게 되는지를 작성하게 된다.

 

컴파일된 쉐이더는 shader에 들어가게 되는데,

 

DEVICE->CreateVertexShader에 인수값으로 삽입되어, blob에 들어가게된 위치값과 사이즈를 담게된다.

nullptr에 들어가는것은 ID3D11ClassLinkage 인데, 현재 쉐이더에 쉐이더를 그리기 전에 hlsl의 코드함수 정의부를 자세하게 나누는 알고리즘을 사용할 것인지 여부이다. 만약 해당되는 알고리즘이 존재하는 포인터 객체가 존재한다면 기입하면 된다.

 


PixelShader

 

// 렌더 타겟에 그려진 픽셀들의 최종 색상을 계산하는 역할

#pragma once
#include "IShader.h"

class PixelShader : public IShader
{
public:
	~PixelShader();

	virtual void Create(const wstring path, const string entryName) override;
	virtual void Clear() override;
	virtual void SetShader() override;

	ID3DBlob* GetBlob() { return blob; }
	ID3D11PixelShader* GetResource() { return shader; }

private:
	ID3D11PixelShader* shader = nullptr;
	ID3DBlob* blob = nullptr;
};
void PixelShader::Create(const wstring path, const string entryName)
{
	// 쉐이더 경로와 엔트리 이름을 저장
	this->path = path;
	this->entryName = entryName;

	// 쉐이더 컴파일
	CompileShader(path, entryName, "ps_5_0", &blob);

	// 버텍스 쉐이더 생성
	HRESULT hr = DEVICE->CreatePixelShader
	(
		blob->GetBufferPointer(),
		blob->GetBufferSize(),
		nullptr,
		&shader
	);
	CHECK(hr);
}

위의 버텍스 쉐이더와 비슷한 코드구조를 가지는데,

버텍스 쉐이더 생성시, ps_5.0 을 사용하여 컴파일하게 되며, 해당되는 쉐이더의 함수부를 지정하고, hlsl의 경로를 지정하는것 까지 전부 동일하게 진행한다.

 

어차피 정점데이터는 이미 레지스터에 존재함으로 정점데이터는 따로 수집하지 않는다.

 

그리고 SetSHader()함수를 사용하여 레지스터에 값을 넘겨주게 된다.

 


InputLayout

// 정점 데이터의 레이아웃을 정의하고 설정하는 역할

#pragma once


class InputLayout
{
public:
	~InputLayout();

	void Create(D3D11_INPUT_ELEMENT_DESC* descs, uint count, ID3DBlob* blob);

	void SetIA();

private:
	ID3D11InputLayout* inputLayout = nullptr;
};

/*
InputLayout
- 정점 버퍼의 데이터 구조를 정의
- 정점 데이터의 각 요소(위치, 색상, 텍스처 좌표 등)의 형식, 크기, 순서 등을 지정
- IA 단계에서 정점 셰이더로 데이터를 전달하기 전에 정점 데이터를 올바르게 해석하는데 사용
*/
void InputLayout::Create(D3D11_INPUT_ELEMENT_DESC* descs, uint count, ID3DBlob* blob)
{
	// 하나라도 없으면 프로그램 종료
	if (!descs || !count || !blob)
		CHECK(false);

	HRESULT hr = DEVICE->CreateInputLayout
	(
		descs,						// InputLayout을 구성하는 각 선언들의 배열
		count,						// InputLayout을 구성하는 선언의 수
		blob->GetBufferPointer(),	// 셰이더 코드를 포함하는 블롭에 대한 포인터
		blob->GetBufferSize(),		// 셰이더 코드 블롭의 크기
		&inputLayout				// 리턴받을 변수
	);
	CHECK(hr);

	// blob = 메모리 블록
}

생성된 정점의 위치좌표를 카메라에 대입하여 카메라에 보이는대로의 위치좌표로 수정하는 역할을 한다.

 

2D객체 생성의 경우, Z값을 사용하지 않음으로 크게 의미가 없을 수 있다.

 

입력받는 각 항목에 대해, VectrxTexture에 해당하는 descs와 count를 가져와 대입하게 된다.

 

카메라의 position은 이미 레지스터에 기입이 되었기 때문에, 여기서는 다루지 않고 hlsl에서 연산을 진행하게 된다.


WorldBuffer

class WorldBuffer : public ShaderBuffer
{
public:
	WorldBuffer() : ShaderBuffer(&data, sizeof(Data))
	{
		D3DXMatrixIdentity(&data.world);
	}

	void SetWorld(Matrix world)
	{
		D3DXMatrixTranspose(&data.world, &world);
	}

	struct Data
	{
		Matrix world;
	};
private:
	Data data;
};

.WorldBuffer는 아주 간단하게 이루어지는데, 이미지 좌표연산이 float4*4의 행렬연산으로 이루어지기 때문에,

Matrix형태의 world를 한개 생성해주고, 해당되는 Data를 사용하여 비어있는 world를 한개 생성해주는게 다이다.


SRV

		SRV::Get()->AddSRV(String::ToString(path), srv);
#pragma once

class SRV : public SingletonBase<SRV>
{
public:
    friend SingletonBase<SRV>;

private:
    SRV();
    ~SRV();

public:
    void AddSRV(string path, ID3D11ShaderResourceView* srv);
    ID3D11ShaderResourceView* GetSRV(string path);

private:
    map<string, ID3D11ShaderResourceView*> srvs;
};
#include "Framework.h"
#include "SRV.h"

SRV::SRV()
{
}

SRV::~SRV()
{
    for (auto it = srvs.begin(); it != srvs.end(); ++it)
        SAFE_RELEASE(it->second);

    srvs.clear();

    cout << "SRV Manager : srvs clear complete" << endl;
}

void SRV::AddSRV(string path, ID3D11ShaderResourceView* srv)
{
    if (srv == nullptr || path == "")
    {
        cout << "SRV Manager : Add Error" << endl;
        return;
    }

    srvs.insert(make_pair(path, srv));
}

ID3D11ShaderResourceView* SRV::GetSRV(string path)
{
    if (srvs.find(path) != srvs.end())
        return srvs.find(path)->second;
    else
    {
        cout << "SRV Manager : Can't find path" << endl;
        return nullptr;
    }
}

SRV는 넣으려는 png파일의 경로를 받아서 srv에 대입하여 생성해주는 역할이다.

픽셀데이터를 가져와서 png파일을 float4 형태의 픽셀배열 형태로 저장하게 된다.


SetIA, SetShader

void TextureRect::Render()
{
	vb->SetIA();
	ib->SetIA();
	il->SetIA();
	DC->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	vs->SetShader();
	ps->SetShader();
	wb->SetVSBuffer(0);

	DC->PSSetShaderResources(0, 1, &srv);

	DC->DrawIndexed(ib->GetCount(), 0, 0);
}
void VertexBuffer::SetIA()
{
	// 입력 어셈블러에 정점 버퍼를 입력하는 함수
	DC->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
}
void VertexShader::SetShader()
{
	DC->VSSetShader(shader, nullptr, 0);
}
	void SetVSBuffer(uint slot)
	{
		MapData();
		DC->VSSetConstantBuffers(slot, 1, &buffer);
	}

SetIA를 통해 해당되는 레지스터로 레지스트 하게 된다. vb와 ib, il값이 전부 레지스터로 이동되어 데이터 처리과정을 준비한다.

 

hlsl에서 받은 데이터 버퍼를 분리하여 데이터를 가공하게 된다.

 

SetShader또한 마찬가지로 해당되는 레지에 값을 이동시키고, 이동된 정점데이터, 픽셀 데이터들을 전부 가공처리 하게된다.

 

위 항목들에서 들어가는 숫자0은 데이터가 들어가게될 레지스터 번호를 의미한다.

// cbuffer : 상수 버퍼 레지스터
// 상수 버퍼 레지스터 b0에 할당된 월드 행렬을 저장하는 상수 버퍼
cbuffer WorldBuffer : register(b0)  // 0 ~ 127
{
    matrix _world;
}

위와같이 hlsl에 등록되어 있을 경우, WorldBuffer 생성되면, 버퍼레지스터 b0에 matrix _world가 저장된다는 의미이다.

 

728x90