typeof 와 차이

  • typeofGCC 에서만 지원되는 비표준 기능
    • 이식성 문제가 발생할 수 있음
  • #define 를 사용한 매크로에서 type을 파악할 떄, 사용하면 좋음

decltype

  • C++11에서 도입된 표준 키워드
    • 이식성이 좋음
  • 컴파일 시점에 표현식의 타입을 추론
  • 특정 변수나 표현식의 타입을 추론하여 정확히 동일한 타입을 제공하는 데 사용
    • 참조 반환, 복잡한 표현식, 템플릿에서 정확한 리턴 타입을 유지
    • 값 복사가 필요할 떄는 사용 자제
  • 명확한 표현식을 팀에서 요구할 때, 여전히 후행 리턴타입 사용
    • -> decltype(t1 * t2) 와 같이 반환 타입이 t1 * t2 표현식의 결과라는 것을 명확히 보여주고 싶을 떄
  • 사용 예시
      int x = 10;
      decltype(x) y = 20; // y는 int 타입
  • auto 키워드와 결합하여 활용 (C++14 버전부터 지원)
      template<typename T1, typename T2>
      decltype(auto) add(const T1& t1, const T2& t2) {return t1 + t2;}
    • const string& 과 같이 기존 const auto&로 사용 해야 하는 타입을 편하게 유추 가능
    • C++11버전 구현
            template<typename T1, typename T2>
            auto add(const T1& t1, const T2& t2) -> decltype(t1+t2) {return t1 + t2;}

'공부 > C++' 카테고리의 다른 글

C++ IO스트림  (0) 2025.03.27
C++스트림  (0) 2025.03.26
추상 클래스  (0) 2025.03.15
문자열  (1) 2025.03.14
참조자(&)  (0) 2025.03.14

6.1 정점과 입력 배치

  • 원하는 자료(특성)를 가진 커스텀 정점 형식을 만들려면 그러한 자료를 담을 구조체 정의
    • 사용자 정의 정점 예시
        struct Vertex1
        {
            XMFLOAT3 Pos;
            XMFLOAT3 Color;
        };
        struct Vertex2
        {
        XMFLOAT3 Pos;
        XMFLOAT3 Normal;
        XMFLOAT2 Tex0;
        }
  • 입력 배치 서술(input layout descrpitino) :
    • 정점의 각 성분으로 무엇을 해야 하는지를 D3D에 알려주어야 함
    • D3D12_INPUT_LAYOUT_DESC 구조체로 대표
        typedef struct D3D12_INPUT_LAYOUT_DESC
        {
            const D3D12_INPUT_ELEMENT_DESC *pInputElementDesccs;
            UINT NumElements;
        } D3D12_INPUT_LAYOUT_DESC;
      • D3D12_INPUT_ELEMENT_DESC 형식 원소들을 담은 배열과 개수를 나타내는 구조체
      • 각 원소는 정점 구조체의 각 성분을 서술
      • 배열의 원소들과 정점 구조체의 성분들 은 일대일로 대응
    • D3D12_INPUT_ELEMENT_DESC 정의
        typedef struct D3D12_INPUT_ELEMENT_DESC
        {
            LPCSTR SemanticName;
            UINT SematicIndex;
            DXGI_FORMAT Format;
            UINT InputSlot;
            UINT AlignedByteOffset;
            D3D12_INPUT_CLASSIFICATION InputSlotClass;
            UINT InstanceDataStepRate;    
        } D3D12_INPUT_ELEMENT_DESC;
      • SemanticName
        • 성분에 부여된 문자열 이름
        • 정점 셰이더에서 의미소(semantic) 이름으로 쓰이므로, 반드시 유효한 변수이름이어야 함
        • 정점 구조체의 성분을 정점 셰이더 입력 서명과 대응시키는 역할
      • SematicIndex
        • 의미소 색인
        • 하나의 정점 구조체에 텍스처 좌표가 여러 개 있을 수 있는데, 각 텍스처 좌표에 개별적인 의미소 이름을 부여하는 대신 색인을 통해 구별
        • 셰이더 코드에서 색인이 지정되지 않은 의미소는 0인 의미소로 간주
      • Format
        • DXGI_FORMAT 열거형의 한 멤버
        • 4.1.3 텍스쳐 형식 참고
      • InputSlot
        • 성분의 자료를 가져올 정점 버퍼 슬롯 색인
        • 총 16개의 정점 버퍼 슬롯(0~15)를 통해서 정점 자료 공급 가능
      • AlignedByteOffset
        • 지정 입력 슬롯에서 정점 구조체의 시작 위치와 정점 성분의 시작 위치 사이의 거리를 나타내는 오프셋(바이트 단위)
        • Pos 성분 바이트 시작 ~ 12byte 이므로, 다음 성분인 Normal은 12byte가 시작위치이므로 offset 값 설정
      • InputSlotClass
        • 입력 슬롯의 데이터 클래스를 정의
        • 셰이더가 처리하는 데이터가 정점 데이터인지 아니면 인스턴스 데이터인지 구분하는 데 사용
          • D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA :
            • 슬롯이 정점 데이터를 포함
            • 각 정점에 대해 데이터가 셰이더로 전달
            • Instance 수 = 0
          • D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA :
            • 슬롯이 인스턴스 데이터를 포함
            • 각 인스턴스에 대해 데이터를 전달할 때 사용
            • 여러 오브젝트를 인스턴스 렌더링할 때, 각각의 인스턴스에 고유한 데이터가 필요
      • InstanceDataStepRate
        • 인스턴스 데이터의 전달 주기를 제어
        • 셰이더가 데이터를 몇 개의 인스턴스마다 업데이트해야 하는지를 결정
          • 1 : 모든 인스턴스에 대해 새로운 데이터를 제공
          • N : 값이 2라면 두 개의 인스턴스가 동일한 데이터를 공유
        • 인스턴스 데이터 사용 시만 적용(PER_INSTANCE_DATA)

6.2 정점 버퍼

  • 정점버퍼 : 정점들을 저장하는 버퍼
    • GPU가 정점 배열에 접근하려면, 정점들을 버퍼라고 부르는 GPU자원 (ID3D12Resource)에 넣어 두어야 함
  • 버퍼는 텍스처보다 단순 자원
    • 다차원 X
    • 밉맵, 다중표본화 기능 X
  • 정점 같은 자료 원소들의 배열을 GPU에 제공할 떄, 항상 버퍼 사용
  • 버퍼 자원을 채우고, ID3D12Device::CreateCommittedResource 메서드를 호출해서
    ID3D12Resource 객체 생성
  • 버퍼 자원 서술 : D3D12_RESOURCE_DESC
    • D12에서 제공하는 해당 구조체를 상속해서 쓰는 편의용 생성자들과 메서드들을 추가한 C++ 래퍼 클래스 CD3DX12_RESOURCE_DESC 제공
        static inline CD3DX12_RESOURCE_DESC Buffer(
            UINT64 width,
            D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FALG_NONE,
            UINT64 alignment = 0 )
        {
            return CD3DX12_RESOURCE_DESC(
                D3D12_RESOURCE_DIMENSION_BUFFER,
                aligment, width, 1, 1, 1,
                DXGI_FORMAT_UNKNOWN, 1, 0,
                D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );
        }
      • width :
        • 버퍼의 바이트 개수를 나타냄
        • flaot 64개 담는 버퍼 => 64*sizeof(flaot)
      • D3D12_RESOURCE_DESC::D3D12_RESOURCE_DIMENSION 필드에 의해서 자원의 구체적인 종류 지정
      • CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(1024); // 1024바이트 버퍼 생성
  • 정적 기하구조(프레임마다 변하지는 않는 기하구조)를 그릴 떄, 최적 성능을 위해 정점 버퍼들을 기본 힙(D3D12_HEAP_TYPE_DEFAULT)에 넣음
    • 정점 버퍼를 초기화한 후에는 GPU만 버퍼의 정점들을 읽으므로(기하구조 그리기위해), 기본 힙에 넣는 것이 합당
    • CPU는 기본 힙에 있는 정점 버퍼 수정 불가

6.2.2 기본 버퍼 생성 편의용 함수 작성

  • 기본 버퍼 생성성

      Microsoft::WRL::ComPtr<ID3D12Resource> d3dUtil::CreateDefaultBuffer(
          ID3D12Device* device,
          ID3D12GraphicsCommandList* cmdList,
          const void* initData,
          UINT64 byteSize,
          Microsoft::WRL::ComPtr<ID3D12Resource>& uploadBuffer)
      {
          ComPtr<ID3D12Resource> defaultBuffer;
    
          // 실제 기본 버퍼 자원 생성
          ThrowIfFailed(device->CreateCommittedResource(
              &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
              D3D12_HEAP_FLAG_NONE,
              &CD3DX12_RESOURCE_DESC::Buffer(byteSize),
              D3D12_RESOURCE_STATE_COMMON,
              nullptr,
              IID_PPV_ARGS(defaultBuffer.GetAddressOf())));
    
          // CPU 메모리를 기본 버퍼에 복사하기 위해, 임시 업로드 힙 생성
          ThrowIfFailed(device->CreateCommittedResource(
              &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
              D3D12_HEAP_FLAG_NONE,
              &CD3DX12_RESOURCE_DESC::Buffer(byteSize),
              D3D12_RESOURCE_STATE_GENERIC_READ,
              nullptr,
              IID_PPV_ARGS(uploadBuffer.GetAddressOf())));
    
    
    // 기본 버퍼에 복사할 자료 서술
    D3D12_SUBRESOURCE_DATA subResourceData = {};
    subResourceData.pData = initData;
    subResourceData.RowPitch = byteSize;
    subResourceData.SlicePitch = subResourceData.RowPitch;

    // 기본 버퍼 자원으로의 자료 복사 요청
    // 보조 함수 UpdateSubresources는 CPU 메모리를 임시 업로드 힙에 복사,
    // ID3D12CommandList::CopySubresourceRegion을 이용해서 임시 업로드 힘의 자료를
    // mBuffer에 복사
    cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(defaultBuffer.Get(), 
        D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
    UpdateSubresources<1>(cmdList, defaultBuffer.Get(), uploadBuffer.Get(), 0, 0, 1, &subResourceData);
    cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(defaultBuffer.Get(),
        D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));

    // 주의 : 위의 함수 호출 이후에도 uploadBuffer를 계속 유지
    // 실제로 복사를 수행하는 명령 목록이 아직 실행 X
    // 복사 완료되었음이 확실해진 후에 호출자가 UploadBuffer 해제

    return defaultBuffer;
}
```
  • D3D12_SUBRESOURCE_DATA 구조체

      typedef struct D3D12_SUBRESOURCE_DATA
          {
          const void *pData;
          LONG_PTR RowPitch;
          LONG_PTR SlicePitch;
          }     D3D12_SUBRESOURCE_DATA;
    • pData :
      • 버퍼 초기화용 자료를 담은 시스템 메모리 배열 가리키는 포인터
      • 버퍼에 n 개의 정점을 담을 수 있을 떄, 전체를 초기화 하려면 시스템 메모리 배열에 최소 n개의 정점 필요
    • RowPitch :
      • 버퍼의 경우, 복사할 자료이 크기(바이트 개수)
    • SlicePitch :
      • 버퍼의 경우, 복사할 자료이 크기(바이트 개수)
  • 정점 버퍼 기본 버퍼 예시

      Vertex vertices[] = {
          { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(COLORS::White)},
          ...    
      };
    
      const UINT vbByteSize = 8 * sizeof(Vertex); // 8개 정점
    
      ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
      ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;
    VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
          mCommandList.Get(), vertices, vbByteSize, VertexBufferUploader);
          // 사용자 정의 정점 버퍼 생성 메서드
      D3D12_VERTEX_BUFFER_VIEW vbv;
      vbv.BufferLocation = VertexBufferGPU->GetGPUVirtualAddress();
      vbv.StrideInBytes = sizeof(Vertex);
      vbv.SizeInByte = vbByteSize;
    
      D3D12_VERTEX_BUFFER_VIEW vertexBuffers[1] = { vbv };
      mCommandList->IASetVertexBuffers(0, 1, vertexBuffers);
    • RTV와 달리 정점 버퍼 뷰에는 서술자 힙이 필요x
  • 정점 버퍼 뷰 대표 형식 D3D12_VERTEX_BUFFER_VIEW_DESC 구조체

      typedef struct D3D12_VERTEX_BUFFER_VIEW
      {
          D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
          UINT SizeInBytes;
          UINT StrideInBytes;
      }     D3D12_VERTEX_BUFFER_VIEW;
    • BufferLocation :
      • 생성할 뷰의 대상이 되는 정점 버퍼 자원의 가상 주소
      • ID3D12Resource::GetGPUVirtualAddress 메서드로 얻을 수 있음
    • SizeInBytes:
      • BufferLocation에서 시작하는 정점 버퍼의 크기(바이트 개수)
    • StrideInBytes :
      • 버퍼에 담긴 한 정점의 원소의 크기 (바이트 개수)
  • 정점 버퍼를 IA 파이프라인에 묶는 메서드

      void ID3D12GraphicsCommandList::IASetVertexBuffers(
          UINT StartSlot,
          UINT NumBuffers,
          const D3D12_VERTEX_BUFFER_VIEW *pViews );
    • StartSlot :
      • 시작슬롯, 첫쨰 정점 버퍼를 묶을 입력 슬롯의 색인
      • 총 16개 (0~15)
    • NumBuffers :
      • 입력 슬롯들에 묶을 정점 버퍼 개수
    • pViews :
      • 정점 버퍼 뷰 배열의 첫 원소를 가리키는 포인터
  • 정점들을 이용해 기본도형을 그리려면 ID3D12GraphicsCommandList::DrawInstanced 메서드 사용

      void ID3D12GraphicsCommandList::DrawInstanced(
          UINT VertexCountPerInstance,
          UINT InstanceCount,
          UINT StartVertexLocation,
          UINT StartInstanceLocation);
    • VertexCountPerInstance : 그리기에 사용할 정점들의 개수 (인스턴스 당)
    • InstanceCount : 그릴 인스턴스 개수
    • StartVertexLocation :
      • 정점 버퍼의 시작 위치를 지정;
      • 정점 버퍼의 색인들 중 이 그리기 호출에서 사용할 첫 색인( 0 기반)
    • StartInstanceLocation :
      • 첫 번째 인스턴스의 시작 위치 지정
      • 특정 인스턴스부터 렌더링을 시작 가능
  • 위상구조 상태 결정은 5.5.2 참고

    • cmdList->IASetPrivitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST)

6.3 색인과 색인 버퍼

  • 색인 버퍼

    • GPU가 색인들의 배열에 접근 할 수 있을려면, 색인들을 GPU 자원에 넣어 두어야 함
  • 색인 버퍼 뷰 대표 형식

    • D3D12_INDEX_BUFFER_VIEW 구조체
        typedef struct D3D12_INDEX_BUFFER_VIEW
        {
            D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
            UINT SizeInBytes;
            DXGI_FORMAT Format;
        } D3D12_INDEX_BUFFER_VIEW;
      • BufferLoation
        • 뷰의 대상이 되는 정점 버퍼 자원의 가상 주소
        • ID3D12Resource::GetGPUVirtualAddress 메서드로 얻을 수 있음
      • SizeInBytes
        • BufferLocation에서 시작하는 색인 버퍼 크기 (바이트 개수)
      • Format
        • 색인 형식 (R16_INT, R32_UINT) 사용
        • 메모리와 대역폭을 절약할려면 16비트 사용
  • ID3D12CommandList::IASetIndexBuffer 메서드를 통해서 입력 조립기 단계에 묶음

  • 사각형 색인 버퍼 IA바인드 예시

      std::uint16_t indices[] = {
          // 앞면
          0, 1, 2,
          0, 2, 3,
          // 뒷면
          ...
      };
    
      const UINT ibByteSize = 36 * sizeof(std::uint_16_t); // 36개 정점
    
      ComPtr<ID3D12Resource> IndexBufferGPU = nullptr;
      ComPtr<ID3D12Resource> IndexBufferUploader = nullptr;
      IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
          mCommandList.Get(), indices, ibByteSize, IndexBufferUploader);
          // 사용자 정의 정점 버퍼 생성 메서드
      D3D12_INDEX_BUFFER_VIEW ibv;
      ibv.BufferLocation = IndexBufferGPU->GetGPUVirtualAddress();
      ibv.Foramt = DXGI_FORMAT_R16_UINT;
      ibv.SizeInBytes = ibByteSize;
    
      mCommandList->IASetIndexBuffer(&ibv);
  • 색인들을 이용해 기본도형을 그리려면 ID3D12GraphicsCommandList::DrawIndexedInstanced 메서드 사용

      void ID3D12GraphicsCommandList::DrawIndexedInstanced(
          UINT IndexCountPerInstance,
          UINT InstanceCount,
          UINT StartIndexLocation,
          INT BaseVertexLocation,
          UINT StartInstanceLocation);
    • IndexCountPerInstance : 그리기에 사용할 색인들의 개수 (인스턴스 당)
    • InstanceCount : 그릴 인스턴스 개수
    • StartIndexLocation :
      • 인덱스 버퍼의 시작 위치를 지정
      • 색인 버퍼의 색인들 중 이 그리기 호출에서 사용할 첫 색인( 0 기반)
    • BaseVertexLocation :
      • 정점 버퍼에서의 기준 오프셋 지정
      • 호출에 쓰이는 색인들에 더할 정수 값, 더한 결과를 최종 색인으로사용해서 정점 버퍼에서 정점 가져옴, 음수 값 허용
    • StartInstanceLocation :
      • 첫 번째 인스턴스의 시작 위치 지정
      • 특정 인스턴스부터 렌더링을 시작 가능

6.4 예제 정점 셰이더

  • 셰이더는 HLSL(High Level Shading Language)로 작성
  • 정점 셰이더는 하나의 함수
  • 매개 변수 4 개 중 앞의 2개는 입력 매개변수, 뒤의 2개는 출력 매개변수
    • 입력 매개변수는 입력 서명(input signature)을 형성
      • 현재의 그리기 작업에 쓰이는 커스텀 정점 구조체의 멤버들에 대응
    • 출력 매개변수
      • 정점 셰이더의 출력을 파이프라인 다음 단계(기하셰이더, 픽셀셰이더)의 해당 입력에 대응 시키는 역할
      • SV_POSITION
        • SV는 SystemValue 라는 의미를 담고 있음
        • GPU는 SV_POSITION으로 명시된 데이터를 하드웨어 수준에서 특별히 처리
        • 렌더링 엔진과 DirectX가 정점의 위치 데이터를 명확히 처리할 수 있도록 보장
      • COLOR
        • D3D12_INPUT_ELEMENT_DESC 배열을 통해 지정한 이름
        • HLSL의 유효 식별자이기만 하면, 아무 이름이나 상관 x
  • HLSL에는 참조나 포인터가 없어, 함수가 여러개의 값을 돌려주려면 구조체 사용 or out이 지정된 출력 매개변수 사용
  • HLSL에서 함수는 항상 인라인화
      void VS(
          float iPosL : POSITION,
          float iColor : COLOR,
          out float4 oPOSH : SV_POSTIION,   // SV는 SystemValue 라는 의미를 담고 있음
          out float4 oColor : COLOR)
      {
          // 동차 절단 공간 변환
          oPosH = mul(float4(iPosL, 1.0f), gWorldViewProj);
          // 정점 색상을 그대로 픽셀 셰이더에 전달
          oColor = iColor;
      }
    • mul 함수 :
      • HLSL 내장 함수
      • 벡터 대 행렬 곱셈 수행
    • gWorldViewProj :
      • 상수 버퍼라고 부르는 버퍼에 들어 있는 것
  • 기하 셰이더 사용 시, 동차 절단 공간 위치의 출력을 기하 셰이더에 미룰 수 있음
  • 원근 나누기는 나중에 하드웨어가 수행하기에, 투영 핼렬 곱하는 부분만 책임

6.4.1 입력 배치 서술과 입력 서명 연결

  • 입력 배치 서술
    • 파이프라인에 공급되는 정점들의 특성들과 정점 셰이더의 매개변수들 사이의 연관 관계 정의
    • 정점 셰이더가 기대하는 모든 입력을 제공하지못하면 오류 발생
      • 추가 공급은 되지만, 적은 건 용납 x
      • D3D에서 입력 레지스터 비트들의 재해석을 허용하기에 float -> int 의 공급을 허용하지만 VC++의 디버그 출력 창은 경고 메시지
        //--------------
        // C++ app code
        //--------------
        struct Vertex
        {
        XMFLOAT3 Pos;
        XMFLOAT4 Color;
        XMFLOAT3 Normal;
        };
        D3D12_INPUT_ELEMENT_DESC desc[] =
        {
        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0};
           D3D12_INPUT_PER_VERTEX_DATA, 0 },
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
          D3D12_INPUT_PER_VERTEX_DATA, 0 },
        { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 28,
          D3D12_INPUT_PER_VERTEX_DATA, 0 }
        //--------------
        // Vertex shader
        //--------------
        struct VertexIn
        {
        float3 PosL : POSITION;
        float4 Color : COLOR;
        };
        struct VertexOut
        {
        float4 PosH : SV_POSITION;
        float4 Color : COLOR;
        };

'프레임워크 > DirectX' 카테고리의 다른 글

06.그리기_연산01_2  (7) 2025.04.08
06.그리기_연산01_1  (0) 2025.04.05
05. 렌더링파이프 개념문제 개인제작  (1) 2025.03.15
05. 렌더링 파이프라인  (7) 2025.03.11
04.Direct3D의_초기화03_요약그림  (0) 2025.03.07

Revert

  • 해당 커밋의 변경 사항으로 되돌림
    • git revert <commit hash>
  • 여러 커밋 한 번에 돌리기
    • git revert <시작 커밋 해시>..<끝 커밋 해시>
  • 중간에 충돌 발생 시, 해결하고 파일 추가하고 계속 진행
      git add <파일명>
      git revert --continue
  • revert 작업 중단
    • git revert --abort

Reset

  • Git에서 특정 커밋 시점으로 브랜치를 이동시키는 명령어
  • reset --soft <commit hash> : 히스토리 유지 및 변경 사항 스테이지 상태로 되돌림
    • 스테이지 상태의 변경사항을 재수정해서 commit 시, 새로운 commit으로 판단하여 충돌 x
  • reset --mixed <commit hash> : 히스토리 유지 및 변경 사항은 제거
  • reset --hard <commit hash> : 히스토리 및 변경 사항 제거

Create bracnh from commit 이용

  • Revert가 안될 떄, 해결방안으로 사용 가능
  • 해당 commit 시점으로 새로 branch를 팔 수 있음
      git checkout abc123
      git checkout -b feature/new-branch

'프레임워크 > Git' 카테고리의 다른 글

Git PR 전에 하면 좋은 사항  (1) 2025.03.22
GPG key 등록  (0) 2025.03.22

현재 branch에 Merge 후, PR

  • 장점

    • 현재 branch에 최신 main branch가 반영되므로 PR 충돌 가능성이 줄어들고, 개인이 충돌을 해결한 뒤 PR 생성이 가능.
    • 별도의 병합 관리자가 없거나 소규모 프로젝트에서 유용.
    • 각자의 개별 commit이 타임라인대로 병합되어 전체 작업 히스토리 확인이 용이.
  • 단점

    • main branch에 문제가 있을 경우, 병합을 통해 현재 branch도 오염 가능.
    • 병합 과정에서 덮어쓴 정보나 충돌 해결 과정에 대한 추적이 어려움.
    • 병합 커밋 자체는 revert가 간단하지만, 특정 부분만 되돌리는 작업이 복잡해질 수 있음.

현재 branch에 Rebase 후, PR

  • 장점

    • 현재 branch에 최신 main branch가 반영되므로 PR 충돌 가능성이 줄어들고, 개인이 충돌을 해결한 뒤 PR 생성이 가능.
    • 별도의 병합 관리자가 있을 때, 유용.
    • 각자의 개별 commit이 선형으로 연결되어 병합 관리자가 리뷰하기 용이.
  • 단점

    • 히스토리가 재작성되기 때문에, 공유 브랜치에서 사용 금지.
    • 병합 과정에서 덮어쓴 정보나 충돌 해결 과정에 대한 기록이 히스토리에 남지 않아 추적이 어려움.
    • 병합 커밋이 생성되지 않으므로, 전체 병합 작업을 되돌리기보다는 특정 커밋 단위로 revert가 용이.

전체적인 사용루틴

  • 병합 관리자가 main 브랜치를 오염없이 관리 해 줄 수 있을 떄,
    • rebase를 통해 개인 PR 히스토리를 깔금하게 선형으로 전달
  • 병합 관리가 없어 main 브랜치 오염이 걱정 될 때,
    • merge먼저 해서 오염 대비 및 rebasePR 히스토리 정리해서 전달
  • 타임 라인 히스토리가 중요할 때,
    • merge로 최신 반영 후, PR 전달

'프레임워크 > Git' 카테고리의 다른 글

이전 시점으로 되돌리기  (0) 2025.03.22
GPG key 등록  (0) 2025.03.22

Gpg4Win 설치

  • GPG 키 생성 및 관리
  • 디지털 서명 생성
  • 서명 검증

GPG 키 생성

  • 키 생성 : gpg --full-generate-keygpg --full-generate-key
      - 키 종류 선택 (보통 1번, RSA 및 RSA 선택).
      - 키 크기 입력 (권장: 4096).
      - 키 만료 날짜 설정 (원한다면 0(만료 없음)).
      - 이름, 이메일 주소 및 비밀번호를 입력합니다.
  • GPG 키 목록 확인: gpg --list-secret-keys --keyid-format=long

GPG 키를 Git에 등록

  • GPG 키를 등록하여 Git 커밋에 서명을 추가하도록 설정합니다.
    • 키 등록 : git config --global user.signingkey <GPG 키 ID>
    • 커밋 서명 자동 설정 : git config --global commit.gpgsign true
    • 키 삭제 : git config --global --unset user.signingkey <GPG 키 ID>

GPG 공개 키를 GitHub에 등록

  • GitHub에 GPG 공개 키를 등록하여 서명된 커밋을 "Verified"로 표시하게 만듭니다.
  • ASCII 형식 출력 : gpg --armor --export <GPG 키 ID>
  • Github에 등록 : GitHub 웹사이트에서 Settings → SSH and GPG keys → New GPG Key

GitHub Desktop에서 GPG 서명 반영 확인

  • GitHub Desktop은 로컬 Git 설정을 기반으로 작동하므로, Git에서 GPG 서명 설정이 완료되었다면 자동으로 반영됩니다.

'프레임워크 > Git' 카테고리의 다른 글

이전 시점으로 되돌리기  (0) 2025.03.22
Git PR 전에 하면 좋은 사항  (1) 2025.03.22
  1. 일반적으로 "Direct3D"에서 고형(solid)물체를 "_____"로 근사해서 표현 한다.
    1. 삼각형메시
  2. 색상 벡터들의 내적 및 외적 연산은 색상을 변화(시킨다 / 시키지 않는다)
    1. 시키지 않는다
  3. 128 비트는 [_, _] 구간이고 ________형식을 사용하고, 32 비트는 [_,_] 구간에 _______ 형식을 사용한다.
    1. [0,1]
    2. XMVector
    3. [0,255]
    4. XMColor
  4. 출력 병합기(OM)단계에서는 ___를 연결하기도 한다.
    1. CommandList의 __________________ 메서드를 사용
      1. 서술자
      2. OMSetRenderTargets
  5. 정점 버퍼는 기본 도형을 어떻게 형성 해야하는 지에 대한 정보가 담겨져 (있다 / 없다)
    1. 없다
  6. 위상구조를 설정하는데 쓰이는 구조체에서 "LIST"가 붙은 타입은 인접한 도형과 정점을 (공유 / 비공유) 하고 ''STRIP"이 붙은 타입은 인접한 도형과 정점을 (공유 / 비공유)한다
    1. 비공유
    2. 공유
  7. Vertex Shader(정점 셰이더)단계에서 GPU의 다른 자원에 접근이 (가능 / 불가능)하다
    1. 가능
  8. 세계 행렬은 W = ___ 를 통해서, 구하는 게 가능하다
    1. SRT
  9. view matrix(시야 행렬)을 구하기 위해 ________________ 를 사용할 수 있다
    1. XMMatrixLookAtLH
  10. 카메라의 up vector(상향 벡터)는 기본적으로 (x, y, z) 축이고, 시야 공간의 __에 놓여 양의 (x, y, z)축을 바라본다
    1. y, 원점, z
  11. x 축에 투영한 좌표 x' 이 다음과 같을 때, 이를 정규화된 장치 좌표로 변환하면? (종횡비는 r)
    $$x' = \frac{xd}{z} = \frac{x}{z \tan{(\alpha/2)}}$$
    1. x/rztan(a/2) 
  12. 깊이 성분의 정규화 구간은 [_, _] 이다
    1. 0, 1
  13. 가까운 평면거리 n, 먼 평면거리 f 일 때, [n, f]를 [0, 1]로 사상하는 함수는 순서를 보존할 필요가 (있다, 없다)
    1. 있다
  14. LOD(Level-Of_Detail)은 _____을 통해서 구현 가능하다
    1. 테셀레이션
  15. 렌더링 파이프라인의 단계들 중 선택적 수행 가능한 단계들은?
    1. 입력 조립기(IA)
    2. 정점 셰이더(VS)
    3. 테셀레이션 단계
    4. 기하 셰이더 단계(GS)
    5. 레스터화 단계(RS)
    6. 픽셀 셰이더 단계(PS)
    7. 출력 병합기 단계(OM)
      1. 3, 4, 6
  16. 원근 투영에서 사용되는 두 개의 평행한 평면으로 잘린 피라미드 모양의 공간을 ___라고 한다
    1. 절두체
  17. 뷰포트 변환 시 'z' 성분은 (변한다 / 변하지 않는다)
    1. 변하지 않음 <- 왜곡되지 않았다는 뜻(실제 값 변경은 변함)
  18. 정점 v0, v1, v2을 {v1, v2, v3} 순서로 연결된 삼각형의 법선 벡터는? (e0 = v1 - v0; e1 = v2 - v0)
    1. (e0 x e1) / (e0 x e1)
  19. 후면 삼각형을 폐기하는 것을 ____이라고 한다
    1. 후면선별
  20. 3차원 선분에서 균등하게 나누어진 구간들이 화면공간의 2차원 선분이 되어도 균등하게 (유지된다 / 유지되지 않는다)
    1. 유지되지 않는다
  21. 색상을 출력하는 단계는 _____단계
    1. 픽셀셰이더
  22. 기하 자료를 읽어 기본 도형을 만드는 단계는 _____단계
    1. 입력조립기
  23. 각 정점의 위치와 속성을 처리하여 3D 공간에서 화면 공간으로 변환하는 단계는 _____단계
    1. 정점셰이더
  24. 혼합(blending)이 일어나는 단계는 _____단계
    1. 출력병합기

추상 클래스(abstract class)

  • 순수 가상 메서드(pure virtaul method)가 하나라도 선언된 클래스
    • 사실상 c++에서는 c#과 달리 abstract class라는 별도의 지정 키워드 존재x
  • 순수 가상 메서드는 선언 뒤에 = 0 을 붙여서 표현; (구현 x)
      class SpreadsheetCell
      {
      public:
          virtaul void set(int value) = 0;
          virtaul std::string getString() const = 0;
      }
  • 파생 클래스가 상속 받은 순수 가상 메서드 중 구현하지 않은게 있다면, 파생 클래스도 추상 클래스가 된다.

인터페이스(Interface)

  • 순수 가상 메서드로만 선언된 클래스
  • 추상 클래스에서 더욱 가상화된 형태
  • 마찬가지로 파생 클래스가 상속 받은 순수 가상 메서드 중 구현하지 않은게 있으면 추상 클래스가 된다

'공부 > C++' 카테고리의 다른 글

C++스트림  (0) 2025.03.26
decltype  (0) 2025.03.26
문자열  (1) 2025.03.14
참조자(&)  (0) 2025.03.14
템플릿(Template)  (0) 2025.03.08
  • WinAPI (Windows Application Programming Interface)
    • 운영체제가 응용프로그램 개발을 위해 제공하는 함수의 집합
    • 속성 -> 링커-> 시스템 -> 하위 시스템 -> Window
  • 핸들(Handle) : 윈도우 각 객체를 구분하는 인덱스 번호(정수)
  • 메시지(Message) : 윈도우에서 발생하는 이벤트를 운영체제가 윈도우에 전달하는 데이터 모음
  • HINSTANCE : 메모리상 객체를 다루는 핸들
  • HWND : 윈도우 핸들
  • APIENTRY : 진입점 (WINAPI)와 동일
  • WNDCLASS : 윈도우 데이터 셋팅 구조체
      typedef struct _WNDCLASS {
          UINT        style;          // 클래스 스타일
          WNDPROC     lpfnWndProc;    // 윈도우 프로시저
          int         cbClsExtra;     // 클래스 추가 메모리
          int         cbWndExtra;     // 윈도우 추가 메모리
          HINSTANCE   hInstance;      // 인스턴스 핸들
          HICON       hIcon;          // 아이콘 핸들
          HCURSOR     hCursor;        // 커서 핸들
          HBRUSH      hbrBackground;  // 백그라운드 브러시 핸들
          LPCWSTR     lpszMenuName;   // 메뉴 이름
          LPCWSTR     lpszClassName;  // 클래스 이름
      } WNDCLASS, *PWNDCLASS;
    • WNDCLASS를 전역 변수로 저장하고 사용하면, 창이 여러개 되었을 떄, 같은 윈도우 셋팅에 사용가능 (아니면, 나중에 팝업창 등이랑 섞여서 문제 생길 수도 있음 )
  • RegisterClass({WNDCLASS}) : 윈도우 데이터 셋팅 등록
  • ShowWindow({WNDCLASS}, {int:창표시상태}) : 초기 표시 상태를 지정
  • MSG; : 윈도우 이벤트를 구조체
  • GetMessage(&message, 0, 0, 0) : 메시지 입력 받기
  • PostQuitMessage(0); : 프로그램 종료 메시지
  • BOOL InvalidateRect(HWND hWnd, const RECT* lpRect, BOOL bErase);
    • 영역 지우고 다시 보내기 요청
  • TranslateMessage(&{MSG}) : 메시지 변환; 키보드 입력 관련 메시지 처리;
  • DispatchMessage(&{MSG}) : 메시지를 올바른 윈도우 프로시저로 보내는 역할

그리기 메서드

  • BeginPaint({HWMD},{PAINTSTRUCT}) : 그리기 시작 알림
  • EndPaint({HWMD},{PAINTSTRUCT}) : 그리기 종료 알림
  • Rectangle({HDC},{LEFT},{TOP},{RIGHT},{BOTTOM}) : 사각형 그리기
  • Ellipse : Rectangle과 동일
  • CreatePen({선타입},{두께},{RGB}) : HPEN 생성; 생성된 HPEN 핸들 반환
  • SelectObject(hdc, {대상}) : 대상 선택; 교체된 대상 반환 (이전 대상)
  • DeleteObject({대상}) : 대상 삭제

  • AdjustWindowRect(RECT&, WINDOW_STYLE, bool {MENU}) :
    • 창크기 조절, 안하면 하단과 우측 짤림 현상

'프레임워크 > WinAPI' 카테고리의 다른 글

디버그 출력  (0) 2025.03.14
애니메이션  (0) 2025.03.14

+ Recent posts

let textNodes = document.querySelectorAll("div.tt_article_useless_p_margin.contents_style > *:not(figure):not(pre)"); textNodes.forEach(function(a) { a.innerHTML = a.innerHTML.replace(/`(.*?)`/g, '$1'); });