// Initialize demo
	// 이전에 다룬 Blank 클래스 대신 Triangle 클래스를 생성하는것만 다름.
    CDemoTriangleGreen demo;
    if (!demo.Initialize(g_hWnd, g_hInst))
        return -1;

 

bool CDx11Base::CompileShader(LPCWSTR szFilePath, LPCSTR szFunc, LPCSTR szShaderModel, ID3DBlob** buffer)
{
    // Set flags
    DWORD flags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
    flags |= D3DCOMPILE_DEBUG;
#endif
    
    // Compile shader
    HRESULT hr;
    ID3DBlob* errBuffer = 0;

	//쉐이더 기반 코드를 컴파일하고 그래픽카드에 업로드한다.
    hr = ::D3DX11CompileFromFile(
        szFilePath,				//파일 경로
		0,
		0,
		szFunc,
		szShaderModel,
        flags,
		0, 
		0,
		buffer,
		&errBuffer,
		0);

    // Check for errors
    if (FAILED(hr)) {
        if (errBuffer != NULL) {
            ::OutputDebugStringA((char*)errBuffer->GetBufferPointer());
            errBuffer->Release();
        }
        return false;
    }
    
    // Cleanup
    if (errBuffer != NULL)
        errBuffer->Release( );
    return true;
}

 

// ShaderGreenColor.fx : Implements the shader.
//
// By Geelix School of Serious Games and Edutainment.
//

//.fx는 cpu에서 실행되지 않고 그래픽카드에서 실행됨.
//VS: VertexShader, pos: 정점의 위치, 
float4 VS_Main(float4 pos : POSITION) : SV_POSITION
{
    return pos;
}

//PS: PixelShader 색상을 출력하도록 한다.
float4 PS_Main(float4 pos : SV_POSITION) : SV_TARGET
{
	//R G B A
    return float4(0.0f, 0.75f, 0.0f, 1.0f);
}

 

bool CDemoTriangleGreen::LoadContent()
{
    // Compile vertex shader

	//부모의  ComplieShader으로 파일을 읽어서 코드를 컴파일한다.
    ID3DBlob* pVSBuffer = NULL;
    bool res = CompileShader(L"ShaderGreenColor.fx", "VS_Main", "vs_4_0", &pVSBuffer);
    if (res == false) {
        ::MessageBox(m_hWnd, L"Unable to load vertex shader", L"ERROR", MB_OK);
        return false;
    }

    // Create vertex shader
    HRESULT hr;
    hr = m_pD3DDevice->CreateVertexShader(
        pVSBuffer->GetBufferPointer(),
        pVSBuffer->GetBufferSize(),
        0, &m_pVSGreenColor);
    if (FAILED(hr)) {
        if (pVSBuffer)
            pVSBuffer->Release();
        return false;
    }

    // Define input layout
	//쉐이더 입력 레이아웃 구조를 정의하고 전달할것을 정의함.

	/*
	GPU에게 버텍스정보를 보관한 버텍스버퍼를 전송할때는 보통 메모리덩어리로 전송한다. 따라서 GPU에서 버퍼의 정확한 속성을 추출해내기 위해서는 버텍스 레이아웃을 알아야 한다. 이것을 위해서 input layout을 사용할 필요가 있다.
즉 input layout이란 GPU에다가 버텍스 구조체의 레이아웃을 설명하는 D3D 오브젝트이다. 각각의 버텍스 속성은 D3D11_INPUT_ELEMENT_DESC 구조체로 설명할 수 있다. 여러개의 D3D11_INPUT_ELEMENT_DESC 구조체를 배열로 정의해서 버텍스전체에 대한 input layout 오브젝트를 만든다. 
D3D11_INPUT_ELEMENT_DESC 구조체는 다음 필드를 가진다.
 SemanticName
 시맨틱이름은 이 요소의 본질 또는 목적을 설명하는 단어를 포함하는 물자열이다. 단어는 C 식별자의 어떤 한 형태일수 있고, 우리가 선택한 어떤것이라도 될 수 있다. 예를 들어 버텍스 위치를 위한 좋은 시맨틱 이름은 POSITION이다. 시맨틱이름은 대소문자를 구분하지 않는다.
 SemanticIndex
 시맨틱인덱스는 시맨틱이름을 보충한다. 버텍스는 동일 본질 속성을 여러개 가질 수 있다. 예를 들어 2개의 텍스쳐 세트 또는 2개의 칼라가 그렇다. 시맨틱이름에 숫자를 "COLOR0", "COLOR1"처럼 추가하는 대신, 2개는 동일한 시맨틱 이름인 "COLOR"를 사용하고, 서로다른 시맨틱 인덱스인 0, 1을 가진다.
 Format
 포맷은 이 요소에 사용하는 데이타타입을 정의한다. 예를 들어 DXGI_FORMAT_R32G32B32_FLOAT 은 3개의 32비트 부동소수점을 가진다. 이 요소는 총 12바이트 길이이다. DXGI_FORMAT_R16G16B16A16_UINT는 4개의 16비트 unsignend int를 가지고 요소는 총 8바이트 길이이다.
 InputSlot
 이전에 말했듯이, D3D11 애플리케이션은 버텍스데이터를 버텍스버퍼를 통해서 GPU로 넘긴다. D3D11에서는 동시에 여러개의 버텍스버퍼가 GPU로 전송될 수 있다. 정확히는 16개이다. 각각의 버텍스 버퍼는 0~15개 까지의 입력슬롯 넘버에 바인드된다. InputSlot 필드는 GPU에게 이요소를 어떤 버텍스버퍼로부터 가져와야 하는지를 말한다. 쉽게말해 InputAssembler에게 설정하는 스트림인덱스라고 생각하면 된다. d3d9에서는 여러개의 버텍스버퍼를 각각 정의하는 구조체를 가졌지만, d3d10부터는 여러개의 버텍스버퍼를 하나의 배열에다가 정의한다. 따라서 각각의 버텍스버퍼 입력슬롯을 구분해야 한다. 그러기 위한 값이다.
 AlignedByteOffset
 버텍스는 버텍스버퍼에 저장된다. 이것은 단순히 메모리 덩어리이다. AlignedByteOffset 값은 GPU에게 이 요소가 메모리덩어리 시작지점부터 얼마나 떨어진 위치에 있는가를 알려준다.
 InputSlotClass
 이 필드는 보통 D3D11_INPUT_PER_VERTEX_DATA 값을 가진다. 애플리케이션이 인스턴싱을 사용한다면, 이 값은 D3D11_INPUT_PER_INSTANCE_DATA로 설정해서 버텍스버퍼가 인스턴스데이타를 포함한다고 알려줄수 있다. 인스턴싱은 고급 D3D 주제로 여기서는 말하지 않을것이다.
 InstanceDataStepRate
 이 필드 역시 인스턴싱을 위해 사용된다. 여기서는 인스턴싱을 사용하지 않을것이므로, 이 필드는 0으로 설정되어야 한다.

	*/
    D3D11_INPUT_ELEMENT_DESC shaderInputLayout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
    };
    UINT numLayoutElements = ARRAYSIZE( shaderInputLayout );

    // Create input layout
    hr = m_pD3DDevice->CreateInputLayout(
        shaderInputLayout, numLayoutElements,
        pVSBuffer->GetBufferPointer(), 
        pVSBuffer->GetBufferSize(), 
        &m_pInputLayout);
    if (FAILED(hr)) {
        return false;
    }

    // Release VS buffer
    pVSBuffer->Release();
    pVSBuffer = NULL;

    // Compile pixel shader
    ID3DBlob* pPSBuffer = NULL;
    res = CompileShader(L"ShaderGreenColor.fx", "PS_Main", "ps_4_0", &pPSBuffer);
    if (res == false) {
        ::MessageBox(m_hWnd, L"Unable to load pixel shader", L"ERROR", MB_OK);
        return false;
    }

    // Create pixel shader
    hr = m_pD3DDevice->CreatePixelShader(
        pPSBuffer->GetBufferPointer(),
        pPSBuffer->GetBufferSize(), 
        0, &m_pPSGreenColor);
    if (FAILED(hr)) {
        return false;
    }

    // Cleanup PS buffer
    pPSBuffer->Release();
    pPSBuffer = NULL;

    // Define triangle

	//삼각형의 정점 좌표를 지정한다.
    Vertex vertices[] =
    {
        XMFLOAT3(  0.0f,  0.5f, 0.5f ),
        XMFLOAT3(  0.5f, -0.5f, 0.5f ),
        XMFLOAT3( -0.5f, -0.5f, 0.5f )
    };

    // Vertex description
    D3D11_BUFFER_DESC vertexDesc;
    ::ZeroMemory(&vertexDesc, sizeof(vertexDesc));
    vertexDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexDesc.ByteWidth = sizeof(Vertex) * 3;

    // Resource data
    D3D11_SUBRESOURCE_DATA resourceData;
    ZeroMemory(&resourceData, sizeof(resourceData));
    resourceData.pSysMem = vertices;

    // Create vertex buffer
    hr = m_pD3DDevice->CreateBuffer(&vertexDesc, &resourceData, &m_pVertexBuffer);
    if (FAILED(hr)) {
        return false;
    }

    return true;
}

void CDemoTriangleGreen::UnloadContent()
{
    // Cleanup
    if (m_pVSGreenColor)
        m_pVSGreenColor->Release();
    m_pVSGreenColor = NULL;
    if (m_pPSGreenColor)
        m_pPSGreenColor->Release();
    m_pPSGreenColor = NULL;
    if (m_pInputLayout)
        m_pInputLayout->Release();
    m_pInputLayout = NULL;
    if (m_pVertexBuffer)
        m_pVertexBuffer->Release();
    m_pVertexBuffer = NULL;
}

void CDemoTriangleGreen::Update()
{
}

void CDemoTriangleGreen::Render()
{
    // Check if D3D is ready
    if (m_pD3DContext == NULL)
        return;

    // Clear back buffer
    float color[4] = { 0.0f, 0.0f, 0.5f, 1.0f };
    m_pD3DContext->ClearRenderTargetView(m_pD3DRenderTargetView, color);


    // Stride and offset
    UINT stride = sizeof(Vertex);
    UINT offset = 0;

    // Set vertex buffer
    m_pD3DContext->IASetInputLayout(m_pInputLayout);
    m_pD3DContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);
    m_pD3DContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // Set shaders
    m_pD3DContext->VSSetShader(m_pVSGreenColor, 0, 0);
    m_pD3DContext->PSSetShader(m_pPSGreenColor, 0, 0);

    // Draw triangle
    m_pD3DContext->Draw(3, 0);


    // Present back buffer to display
    m_pSwapChain->Present(0, 0);
}

https://blog.daum.net/tjdgmlrnsk/11

 

DIRECTX11 다이렉트x 기초

다이렉트 x 11 프레임워크의 기초 삼각형을 그리기 위해선 이 3개의 점을 GPU로 보내야한다. D3D11에서 위치같은 버텍스정보는 버퍼리소스에 저장된다. 버텍스정보를 저장하는데 사용되는 버퍼는

blog.daum.net

'기타 > directX' 카테고리의 다른 글

[DirectX11] 렌더링  (0) 2022.02.26
[DirectX11] sprite 그리기  (0) 2022.02.26
[DirectX11] 텍스쳐 그리기  (0) 2022.02.22
bonnate