평생 공부하는 빠타박스 블로그 : Learning is Happiness
article thumbnail
SMALL

ImGui 활용한 DirectX 11 3D를 이용한 2D를 만드는 내용입니다.
본 내용은 똑같이 사용할 수 없음을 알립니다. (참고및 공부자료로 만들어진내용임을 밝힙니다.)
이전 과정에 대해 이해를 해야 다음 이 부분에 대한 이해를 할 수 있음을 밝힙니

이전자료) https://ppatabox.tistory.com/42

 

 

진행 내용 (중요 각주 포함) - 맨 하단 글 하단이동[각주:1]

정점, 동적할당 , 생성자 호출, 버텍스 버퍼 , hlsl , states ,  비트마스크 

 

 

정리한번 해나갈 것 


 

const상수 붙은 것은 카멜 표기법 말고 관례상 파스칼 표기법을 사용한다. 

const UINT VertextCount = 6;

 

 

항상 new 같은 거 하면 delete해줘야 한다고 했는데

우리가 여지까지 

delte vertices;

이런식으로 지워왔는데.

 

지금 아래를 보면 배열로 동적할당 되었다. 

vertices = new Vertex[VertextCount];

 

저런 방식으로 그래서 delete하면 안된다.

 delete [] vertices; 이런식이 되야 하는데 

 

stdafx에서 매크로로 만들어주자 

#define SAFE_DELETE_ARRAY(p) { if(p != NULL){ delete [] p; p = NULL; } }

안에 보면 NULL이 아니라면 delete [ ] 로 해줬다. 

 

 

Rect::Rect()
{
	vertices = new Vertex[VertextCount];
}
Rect::~Rect()
{
	SAFE_DELETE_ARRAY(vertices);
}// 항상 new를 할당하고 나면 지우는 거 부터 넣어주자

항상 new를 할당하고 나면 지우는 것 부터 넣어주자 

 

나머지는 배열 다루는 것과 똑같을 것이다. 

 

항상 인터페이스 만들때 description이 붙는다. 

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

평소에 이걸 만들때 저런식으로 자료형을 sizeof에 넣는데 (이 자료형 크기만큼 메모리를 0으로 초기화 해 달라는게

ZeroMemory의 역할이다. 

 

그런데 가끔 

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

이런식으로 변수를 넣어 놓는 경우가 있다. 

똑같이 잘 되긴 한다. 

이 변수의 크기랑 자료형의 크기랑 똑같으니까. 

 

그런데 

D3D11_BUFFER_DESC desc[3];//배열
ZeroMemory(&desc, sizeof(desc)); //4byte 주소니까

이게 배열이면

sizeof에 변수가 4byte가 나온다.

왜? = 주소 니까. 

배열일때 

 

desc의 배열일때는 배열의 시작주소 였는데

그러니까 sizeof(desc) 쪽은 4byte밖에 안나온다. 

그래서 &desc  4byte만 필요하다고 

 

그래서 그런 실수를 미리 방지를 위해서 

자료형을 넣어주는 것이다. 

그럼 배열일 경우 * 3을 해준다. 

D3D11_BUFFER_DESC desc[3];//배열
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC) * 3);

이런식으로 해준다.  여기까지 예시 

 

VertexBuffer 만들어 줘서 여기부분 필요없음(통수주의) 

 


private:
	Vertex* vertices;
	VertexBuffer* vertextBuffer;
vertextBuffer = new VertexBuffer(vertices, VertexCount, sizeof(Vertex));

vertices , 갯수 (vertxCount) , sizeof( stride , 이것은 CPU right? ,GPUright? 할 필요 없음기본 값 false;  

 

 

 

 

보통 쉐이더는 shader 는 맨 위에 할당 한다. 

나중에 쉐이더로 응용이 많아서 

 

Rect::Rect()
{
	shader = new Shader(L"effect.hlsl"); //wstring 사용  이것도 new했으니까 지워주자 

	vertices = new Vertex[VertexCount];
	vertices[0] = Vertex(D3DXVECTOR3(-0.5f, -0.5f, 0.0f));
	vertices[1] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0.0f)); //좌상단
	vertices[2] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0.0f)); //우하단
	vertices[3] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0.0f)); //2,3 같음
	vertices[4] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0.0f)); //1,4 같음 
	vertices[5] = Vertex(D3DXVECTOR3(+0.5f, +0.5f, 0.0f)); //우상단

	vertexBuffer = new VertexBuffer(vertices, VertexCount, sizeof(Vertex));
}

 

 

 

이곳 INPUT_ELEMENT를 정의 할때는  일단 배열로 만들어 준 상태에서 

 

D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
{
	"POSITION"
};

suggests

Effect.hlsl쉐이더에 있는 

이것과 이름이 일치해야함

쉐이더에 있는 이름과 일치 해야 한다. 

이걸 시멘틱이라고 한다. 

 

뒤에 , 하고 들어가는데 0 시멘틱 번호 POSITION(시멘틱)0(시멘틱번호) 

 

시맨틱(Semantic)[각주:2]

 

	D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
	{
		"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0,
	};

그다음 자료형 

저기 어디? FLOAT3인데 여기만 FLOAT4 로 받는다 POSITION만큼 갖게 

이외로 ROM RAM등등 

"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0(slot번호), 0(0byte부터 쓰겠음), D3D11_INPUT_PER_VERTEX_DATA(정점데이터로 들어갈꺼니까), 0

 

 

 

ARRAYSIZE[각주:3]

sizeof[각주:4]

colorBuffer_PS = new ConstantBuffer(&colorBufferData/*데이터*/, sizeof(ColorBufferDesc)/*컬러버퍼크기*/, 0/*slot*/, true/*픽셀쉐이더용*/);
wvpBuffer_VS = new ConstantBuffer(&wvpBufferData, sizeof(WvpBufferDesc));

 

 

 

D3DXVECTOR3 eye(0, 0, -1); [각주:5]
D3DXVECTOR3 lookAt(0, 0, 0);[각주:6]
D3DXVECTOR3 up(0, 1, 0); [각주:7]

 

private:
	struct WvpBufferDesc
	{
		D3DXMATRIX World;
		D3DXMATRIX View;
		D3DXMATRIX Projection;
		
		WvpBufferDesc()//생성자 받아옴 
		{
			D3DXMatrixIdentity(&World);

			D3DXVECTOR3 eye(0, 0, -1); //눈의 위치 살짝 뒤로 떨어져서
			D3DXVECTOR3 lookAt(0, 0, 0); //어디를 바라볼 것인가 바라볼 지점
			D3DXVECTOR3 up(0, 1, 0); // 머리 회전 방향 2D는 위 

			D3DXMatrixLookAtLH/*LH왼손좌표계*/(&View, &eye, &lookAt, &up);
			D3DXMatrixTranspose(&View, &View); //전치 해주기 열우선을 사용하기 때문 
		}
	}wvpBufferData;

	ConstantBuffer* wvpBuffer_VS;
};

전치해줘야 하는데 

우리는 행우선을 쓰지만 쉐이더에선 열우선 을 쓴다.

View를 다시 전치 해주고 

 

 

 

D3DXMATRIX World; //사용할 것 
D3DXMATRIX View; //안변하게 
D3DXMATRIX Projection;

이러한 값은 한번만 건들이면 못 건들일 것인데 

이런 경우 private를 외부 접근 못하니까. 

	public:
		D3DXMATRIX World;

	private:
		D3DXMATRIX View;
		D3DXMATRIX Projection; //값이 바뀔 이유가 없음

값이 못바뀌게 못건들이게 private처리 해준다 

 

 

지금까지 쓴 내용 코드 주석 참고

 

Rect.h

#pragma once

class Rect
{
public:
	Rect();
	~Rect();
	
	void Position(float x, float y);
	void Position(D3DXVECTOR2 vec);

	void Scale(float x, float y);
	void Scale(D3DXVECTOR2 vec);

	void Color(float r, float g, float b, float a = 1.0f);
	void Color(D3DXCOLOR color);


public:
	void Update(); //이동 처리 Update에서 할 것임 
	void Render();

private:
	D3DXVECTOR2 position;
	D3DXVECTOR2 scale;

private:
	Shader* shader;


private:
	struct Vertex
	{
		Vertex() : Position(0, 0, 0)
		{

		}
		Vertex(D3DXVECTOR3 position) : Position(position)
		{

		}
		D3DXVECTOR3 Position;
	};

private:
	Vertex* vertices;
	VertexBuffer* vertexBuffer;
	
	const UINT VertexCount = 6; //정점 갯수는 안바뀜 
	//버퍼 

private:
	struct ColorBufferDesc
	{
		ColorBufferDesc() : Color(0, 0, 0, 1)
		{

		}
		ColorBufferDesc(D3DXCOLOR color) : Color(0, 0, 0, 1)
		{

		}
		D3DXCOLOR Color;
	} colorBufferData;

	ConstantBuffer* colorBuffer_PS; //픽셀쉐이더에 들어감

private:
	struct WvpBufferDesc
	{
	public:
		D3DXMATRIX World;

	private:
		D3DXMATRIX View;
		D3DXMATRIX Projection;
		
	public: 
		WvpBufferDesc()//생성자 받아옴 
		{
			D3DXMatrixIdentity(&World);

			D3DXVECTOR3 eye(0, 0, -1); //눈의 위치 살짝 뒤로 떨어져서
			D3DXVECTOR3 lookAt(0, 0, 0); //어디를 바라볼 것인가 바라볼 지점
			D3DXVECTOR3 up(0, 1, 0); // 머리 회전 방향 2D는 위 

			D3DXMatrixLookAtLH/*LH왼손좌표계*/(&View, &eye, &lookAt, &up);
			D3DXMatrixTranspose(&View, &View); //한번만 만들면 되는 애들 생성자에 넣어버린것

			D3DXMatrixOrthoOffCenterLH(&Projection, 0, (float)Width, 0, (float)Height, -1, +1);
			D3DXMatrixTranspose(&Projection, &Projection);//한번만 만들면 되는 애들 생성자에 넣어버린것 
		}
	}wvpBufferData;

	ConstantBuffer* wvpBuffer_VS;
};

Rect.cpp

#include "stdafx.h"
#include "Rect.h"


Rect::Rect()
{
	shader = new Shader(L"effect.hlsl");

	D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
	{
		"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0,
	};
	shader->CreateInputLayout(layoutDesc, ARRAYSIZE(layoutDesc));



	vertices = new Vertex[VertexCount];
	vertices[0] = Vertex(D3DXVECTOR3(-0.5f, -0.5f, 0.0f));
	vertices[1] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0.0f)); //좌상단
	vertices[2] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0.0f)); //우하단
	vertices[3] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0.0f)); //2,3 같음
	vertices[4] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0.0f)); //1,4 같음 
	vertices[5] = Vertex(D3DXVECTOR3(+0.5f, +0.5f, 0.0f)); //우상단

	vertexBuffer = new VertexBuffer(vertices, VertexCount, sizeof(Vertex));

	colorBuffer_PS = new ConstantBuffer(&colorBufferData/*데이터*/, sizeof(ColorBufferDesc)/*컬러버퍼크기*/, 0/*slot*/, true/*픽셀쉐이더용*/);
	wvpBuffer_VS = new ConstantBuffer(&wvpBufferData, sizeof(WvpBufferDesc));

}

Rect::~Rect()
{
	SAFE_DELETE(shader);

	SAFE_DELETE_ARRAY(vertices);
	SAFE_DELETE(vertexBuffer); //new로 할당해서 지워주자 

	SAFE_DELETE(colorBuffer_PS);
	SAFE_DELETE(wvpBuffer_VS);
}

void Rect::Position(float x, float y)
{
	Position(D3DXVECTOR2(x, y));
}

void Rect::Position(D3DXVECTOR2 vec)
{
	position = vec;//행렬계산으로 따로 저장해둔 것 
}

void Rect::Scale(float x, float y)
{
	Scale(D3DXVECTOR2(x, y));
}

void Rect::Scale(D3DXVECTOR2 vec)
{
	scale = vec; //행렬계산으로 따로 저장해둔 것 
}

void Rect::Color(float r, float g, float b, float a)
{
	Color(D3DXCOLOR(r, g, b, a)); //컬러 콜
}

void Rect::Color(D3DXCOLOR color)
{
	colorBufferData.Color = color; //D3DXCOLOR Color; 이컬러에 들어갈 것 
}

void Rect::Update() //월드를 만들 것이다. 월드를 만들기 위해서 크기하고 이동이 다 있다. 
{
	D3DXMATRIX S, T;
	D3DXMatrixScaling(&S, scale.x, scale.y, 1/*Position크기*/); //아이덴티티 되기때문에 행렬곱으로 
	D3DXMatrixTranslation(&T, position.x, position.y, 0);

	wvpBufferData.World = S * T;
	D3DXMatrixTranspose(&wvpBufferData.World, &wvpBufferData.World);

}

void Rect::Render() //위가 되었으면 Rendering
{
	shader->Render();
	vertexBuffer->Render();
	colorBuffer_PS->Render();
	wvpBuffer_VS->Render();

	DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);//삼각형 자리 그림  
	DeviceContext->Draw(6, 0); //draw렌더링 
}

 

main.cpp

#include "stdafx.h"

Rect* rect = NULL;
void InitScene()
{
	rect = new Rect();
	rect->Position(200, 200);
	rect->Scale(100, 100);
	rect->Color(0, 0, 1);
}

void DestroyScene()
{
	SAFE_DELETE(rect);
}

void Update()
{
	rect->Update();
}

void Render()
{	
	rect->Render();
}

 

Effect.hlsl( shader )

struct VertexInput
{
    float4 Position : POSITION0;
};

struct PixelInput
{
    float4 Position : SV_POSITION;
};


cbuffer VS_Wvp : register(b0)
{
    matrix World;
    matrix View;
    matrix Projection;
}

PixelInput VS(VertexInput input)
{
    PixelInput output;
    
    output.Position = mul(input.Position, World);
    output.Position = mul(output.Position, View);
    output.Position = mul(output.Position, Projection);
  
    return output;
}
cbuffer PS_Color : register(b0)
{
    float4 Color;
}

float4 PS(PixelInput input) : SV_TARGET
{
    return Color;
}

이번에는 텍스쳐를 그릴 클래스를 하나 만들 것인데. 

이번 네이밍을 Rect_sprite 로 이름 짓겠다.

 

위 Rect와 유사함 

Sprite.cpp / h를 만들고 Rect.hlsl을 sprite.h와 분리해놓았다. 

 

Rect&sprite

2D Texture를 Sprite라고 부름 

 

Rect.cpp => Sprite.cpp(변경된 부분) 

Sprite::Sprite()
{
	shader = new Shader(L"Sprite.hlsl");

	D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
	{
		"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0,
		"UV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0,// 12바이트 부터 시작 
	};
	shader->CreateInputLayout(layoutDesc, ARRAYSIZE(layoutDesc));



	vertices = new Vertex[VertexCount];
	vertices[0] = Vertex(D3DXVECTOR3(-0.5f, -0.5f, 0.0f), D3DXVECTOR2(0, 1));
	vertices[1] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0.0f), D3DXVECTOR2(0, 0)); //기준 좌상단
	vertices[2] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0.0f), D3DXVECTOR2(1, 1)); //우하단
	vertices[3] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0.0f), D3DXVECTOR2(1, 1)); //2,3 같음
	vertices[4] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0.0f), D3DXVECTOR2(0, 0)); //1,4 같음 
	vertices[5] = Vertex(D3DXVECTOR3(+0.5f, +0.5f, 0.0f), D3DXVECTOR2(1, 0)); //우상단

	vertexBuffer = new VertexBuffer(vertices, VertexCount, sizeof(Vertex));

	colorBuffer_PS = new ConstantBuffer(&colorBufferData/*데이터*/, sizeof(ColorBufferDesc)/*컬러버퍼크기*/, 0/*slot*/, true/*픽셀쉐이더용*/);
	wvpBuffer_VS = new ConstantBuffer(&wvpBufferData, sizeof(WvpBufferDesc));
}

 

Sprite.h(변경된 부분) 

private:
	struct Vertex
	{
		Vertex() : Position(0, 0, 0)
			,Uv(0,0) //Vertex에 Uv추가됨 
		{

		}
		Vertex(D3DXVECTOR3 position, D3DXVECTOR2 uv) 
			: Position(position)
			,Uv(uv)
		{

		}
		D3DXVECTOR3 Position;
		D3DXVECTOR2 Uv;
	};

private:
	Vertex* vertices;
	VertexBuffer* vertexBuffer;
	
	const UINT VertexCount = 6; //정점 갯수는 안바뀜 
	//버퍼 

private:
	struct ColorBufferDesc  
	{
		ColorBufferDesc() : Color(1, 1, 1, 1)//Texture에 색상을 곱하는게 되서 0이 들어가면 안된다 그래서 1.
		{

		}
		ColorBufferDesc(D3DXCOLOR color) : Color(0, 0, 0, 1)
		{

		}
		D3DXCOLOR Color;
	} colorBufferData;

	ConstantBuffer* colorBuffer_PS; //픽셀쉐이더에 들어감

 

Sprite.h

struct VertexInput
{
    float4 Position : POSITION0;
    float2 Uv : UV0;
};

struct PixelInput
{
    float4 Position : SV_POSITION;
    float2 Uv : UV0;
  
};


cbuffer VS_Wvp : register(b0)
{
    matrix World;
    matrix View;
    matrix Projection;
}

PixelInput VS(VertexInput input)
{
    PixelInput output;
    
    output.Position = mul(input.Position, World);
    output.Position = mul(output.Position, View);
    output.Position = mul(output.Position, Projection);
  
    return output;
}
cbuffer PS_Color : register(b0)
{
    float4 Color;
}

float4 PS(PixelInput input) : SV_TARGET
{
    return Color;
}

 

 

sampler를 하나 만들어야한다.

samplerstate가 있어야 샘플링을 할 수 있다. 

샘플러도 쓰기 편하게 하기 위해 클래스를 하나 만들자 

네임명 : States.cpp/h

 

 

우리가 true / false말고 여러가지 중에 하나를 선택하는 것이 있는데

열거형을 쓴다 

 

 

들어가기 


비트연산(Bitwise operator)[각주:8]

비트 연산자 설명
& 대응되는 비트가 모두 1이면 1을 반환함 (비트 AND 연산)
| (역슬래쉬) 대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)
^ 대응되는 비트가 서로 다르면 1을 반환함 (비트 XOR 연산)
~ 비트를 1이면 0으로, 0이면 1로 반점시킴 (비트 NOT 연산)
<< 지정한 수만큼 비트들을 전부 왼쪽으로 이동시킴 (Left Shift 연산)
>> 부호를 유지하면서 지정한 비트를 전부 오른쪽으로 이동시킴 (RIght Shift 연산) 

 

 

예시 

#include <stdio.h>

int main(void)
{
	int num01 = 15;
	int num02 = 8;

	printf(" ~ 연산자에 의한 결괏값은 %d입니다.\n", ~num01); 		// 1의 보수
	printf("<< 연산자에 의한 결괏값은 %d입니다.\n", num02 << 1);	// 곱하기 2
	printf(">> 연산자에 의한 결괏값은 %d입니다.\n", num02 >> 1);	// 나누기 2 
	return 0;
}

 

enum

이라고 정의한다. 

enum Type
{
	Linear/*0*/, Point/*1*/, Mag/*2*/ // 자동으로 기본값이 처음 0, 1, 2 순으로 지정된다.  
}; //이렇게 선언되어있는 변수 이름들이 전역에서 쓰인다 
//////////
enum class Type //이렇게 붙여줘야 타입내에 구역이 잡힌다. 
{
	Linear/*0*/, Point/*1*/, Mag/*2*/ 
};
////////////////////////////////////////////////////////////////////
Tyep a = Type::Point //이런식으로 쓰임

 

저번에 Linear, Point 등 했었는데 그게 그 이름들이 전부 열거형으로 정의 되어있다.

그러면 해당하는 숫자가 들어간다

만약에 필요하면 이런식으로 정의할 수 있다. 

enum class Type 
{
	Linear = 1, Point = 2, Mag = 4 // 이런형식으로 정의가능 
};
/////////////
Tyep a = Type::Mag //이러면 4가 나온다.

이거는 AND OR 연산 조합할 때 쓴다.

 

 

 

 

______&&______(조건연산) 둘다 참이여야 참 

그런데 이러한 것이 있다.

'&' 

아래 예제 처럼 되면 어떤 연산이 일어 날까?

/*'&'*/

a = 10;
b = 7; 
c = a & b;

 

 

 

 

 

예전에는 나누기 곱하기가 느렸다 (원래 느린 연산) 

지금은 PC가 발전해서 안하는데

 

서버는 하는 경우가 있다. 나누기 연산 안하고

쉬프트로 처리하는 (나누기 곱하기를 쉬프트로 처리한다는 말) 

 

이걸 이용해서 2의 보수 연산 이 있는데 이런 방식을 이용해서 사칙연산을 한다

(BITMASK)

이런걸 조합으로 쓰고 싶다고 할때 

예를 들어 

 

//조합을 하고 싶을때 
enum class Type  
{
	Linear = 1, Point = 2, Mag = 4 
};
/////////////
c = Linear | Point // 0001 | 0010  = 0011(3)
///////
switch(c)
{
	case 1;
    case 2;
    case 3;
    //옵션 조합일때 이런식으로 많이 쓴다.

switch 에서 이런식으로 처리한다. 

 

switch[각주:9]

 

색상이 실제로는 0~1까지 리니어 한 색상을 가져온다

실제로는 0~255까지 다 (이미지) 

 

0~255까지 픽셀을 표현할 려면 RGBA가 있는데

하나가 FF(R) FF(G) FF(B) FF(A)

 

 

우리가 원한건 256값 만큼 다뤄주고 싶다. 

그러면 이걸 밀어줘야 하는데

 

12 숫자를 빼오고 싶을때 

FF 는 0~256까지의 범위 

편한 단어로 바꾸면 1 바이트

1byte = 8비트 2^8  

 

>> : 비트 밀어주는 연산자 

<<

 

 

 

 

어떤 색상을 이안에 넣고 싶다.

RGBA가 전부 따로 있다. 

하나의 변수에 넣고 싶다. OR연산을 이용해서 왼쪽으로 밀어주자.

예를 들어 

R = 128

G = 10

B = 54

A = 255

 

이걸 하나의 변수에 묶고싶다

R은 맨 앞으로 가야하니까

24비트 만큼 밀어주자

128<<24 / 128 00 00 00

G를 넣으려면? 

10 << 16 밀어주자 00 10 00 00 

OR연산을 이용해서 | 하게되면 

 

128 10 00 00 이다 

 그럼 R G 의 조합이 일어난다. 

 

나머지 B를 섞고 싶다면 8비트 만큼 밀어주고

A는 그냥 OR 하면 된다 

옆 그림처럼 원리를 보여준다.

 

이런식으로 사용하는 방법은 자주 사용된다.

 


 

게임프로그래밍이란 일반프로그래밍이란 다른 기법을 사용하는이유가

 

일반 프로그래밍은 뭐 속도면에서 그렇게 신경을 많이 쓰지 않는다. (ATM기 돈 안나오면 1~5초 정도는 기다리지 않은가?)

게임프로그래밍은 실시간을 요한다. 속도가 정말 중요하다 늘 실시간(1~2초 지연 생기면 짜증나지 않는가?)

 

그래서 이러한 연산 방법이 정말 중요하다.

(디바이스와 친화적일 수록 속도가 더 빨라진다.) 

 

 

 

 

 

그외 참고링크) 

 

[C++] 비트연산자, 비트플래그(Bitflag), 비트마스크(Bitmask)

# 비트 플래그 (Bit flag)- 게임 안에 캐릭터가 많은 양의 아이템을 가져야 한다고 가정을 해보자. 그때 ...

blog.naver.com

 

 

 

 

다음시간)

 

[C++] DirectX Rect&Sprite 2편

ImGui 활용한 DirectX 11 3D를 이용한 2D를 만드는 내용입니다. 본 내용은 똑같이 사용할 수 없음을 알립니다. (참고및 공부자료로 만들어진내용임을 밝힙니다.) 이전 과정에 대해 이해를 해야 다음

ppatabox.tistory.com

 

 

 

 

 

 

 


각주)

 

  1. . [본문으로]
  2. 시맨틱은 시맨틱이름과 시맨틱인덱스 그외로 더 있다,

    1)시맨틱 이름 : 요소의 본질 또는 목적을 설명하는 단어를 포함하는 문자열, 선택한 어떤 것이라도 될 수 있다. 예를 들어 버텍스 위치를 위한 좋은 시맨틱 이름은 POSITION이다. 시맨틱이름은 대소문자를 구분하지 않는다.

    2)시맨틱인덱스 : 시맨틱 이름을 봉충한다, 버텍스는 동일 본질 속성을 여러개 가질 수 있다. 예를 들어, 2개의 텍스쳐 세트 또는 2개의 갈라가 그렇다. 시맨틱이름에 숫자를 "COLOR0", "COLOR1"처럼 추가하는 대신, 2개는 동일한 시맨틱 이름인 "COLOR"를 사용하고, 서로다른 시맨틱 인덱스 0, 1 을 가진다. [본문으로]

  3. 배열의 크기를 알려준다, 배열일때 사용하면 됨 ,전체 사이즈가 나온다 [본문으로]
  4. 배열의 시작주소 4byte 만 나온다. [본문으로]
  5. 눈의 위치 살짝 뒤로 떨어져서 [본문으로]
  6. 어디를 바라볼 것인가 바라볼 지점 [본문으로]
  7. 머리 회전 방향 2D는 위 [본문으로]
  8. 비트(bit) 단위로 논리 연산을 할때 사용하는 연산자, 비트단위로 전체 비트를 왼쪽이나 오른쪽으로 이동시킬때도 사용, RGBA색상을 조합하여 실시간으로 필요로하는 곳에서 사용되기도함 [본문으로]
  9. 조건부문)_표현식이 값을 평가하고, 각 Case 레이블의 값과 '같은'지 테스트, 레이블의 값과 같다면 레이블 뒤의 명령문을 실행, 같지 않다면 default뒤의 명령문을 실행 [본문으로]
728x90
728x90
LIST
profile

평생 공부하는 빠타박스 블로그 : Learning is Happiness

@공부하는 PPATABOX

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!