2018년 1월 16일 화요일

Vertex , 정점 정보의 확장

Vertex , 정점 정보의 확장

그동안의 설명에 있어서 우리는 VERTEX 정보에 대하여 3차원의 위치 정보만 사용하였다.

struct VERTEX{float x,y,z;};

이제 이를 확장하여 색상을 추가해 보자.
OpenGL 과 Direct3D 에서 같이 사용하도록 특정한 API에 종속되지 않는 형식으로 작성하도록 하는것이 좋다.

만약 D3DX 의 구조체를 사용한다면 아래와 같을 것이지만 이렇게 된다면 OpenGL에서는 사용하기 어렵기 때문에 이러한 방식은 사용하지 않을 것이다.
물론 매크로를 사용하여 선별적으로 사용할 수 있으나 매크로를 남발 하는 것보다 직관적으로 작성하는 것이 가장 합리적이다.

struct VERTEX{float x,y,z; D3DXCOLOR color;};

새로 작성된 VERTEX는 다음과 같다.
struct VERTEX{float x, y, z; float r,g,b,a;}

이제 다음과 같이 vertices 정보를 입력한다.
앞의 3개는 정점 좌표이고 뒤의 4개는 해당 정점의 색상을 rgba 로 입력한 것이다.
VERTEX vertices[] =
{
{0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},   // red
{0.45f, -0.5, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},  // green
{-0.45f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f} // blue
};


쉐이더 소스를 이제 다음과 같이 변경한다.

OpenGL GLSL
const GLchar* vertexSource = R"glsl(
#version 150 core
in vec3 position;
in vec4 color;
out vec4 out_color;
void main()
{
gl_Position = vec4(position.x,position.y, position.z, 1.0);
out_color = color;
}
)glsl";

const GLchar* fragmentSource = R"glsl(
#version 150 core
in vec4 out_color;
out vec4 pixel_color;
void main()
{
pixel_color = out_color;
}
)glsl";



Direct3D HLSL
struct VOut
{
   float4 position : SV_POSITION;
   float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
   VOut output;

   output.position = position;
   output.color = color;

   return output;
}


float4 PShader(float4 position : POSITION, float4 color : COLOR) : SV_Target
{
   return color;
}


버텍스 버퍼 데이터의 레이아웃이 변경 되었기 때문에 이를 다시 기술해 주어야 한다.

OpenGL

// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
GLint colorAttrib = glGetAttribLocation(shaderProgram, "color");

glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(VERTEX), (void *)0);

glEnableVertexAttribArray(colorAttrib);
glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(VERTEX), (void *)12);



Direct3D

D3D11_INPUT_ELEMENT_DESC ied[] =
{
  {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
  {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
};

dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
devcon->IASetInputLayout(pLayout);


다음 그림은 OpenGL에서의 데이터 연결도를 직관적으로 그려본 것이다.


이러한 변경을 수행하여 실행하면 다음과 같은 출력이 만들어 질 것이다.

이는 OpenGL 과 Direct3D 모두 같은 모습이 될 것이다.




위의 그림에서 color 에 대한 연결은 정확한 답은 아니다. 버텍스 쉐이더는 각 정점당 호출되게 되어 있지만 픽셀쉐이더(프레그먼트 쉐이더)는 정점당 호출되는 것이 아니라 정점들에 의하여 만들어지는 삼각형을 구성하는 모든 픽셀(점) 들에 대하여 호출되어 진다. 사실 엄청 많이 발생하겠지만 병렬로 처리되는 것이니 걱정하지 말기 바란다.

OpenGL(Direct3D) 은 면을 레스터라이징화 할때 내부의 픽셀들은 정점의 색상을 보간하여 계산한다.

이를 Color Interpolation이라 하는데 이에 대한 내용은 구글링에 맡기기로 하겠다.

즉 위와 같은 그림이 나온다는 것은 픽셀쉐이더가 입력된 정점수만큼 호출되는 것이 아니라는 것을 보여주고 있기도 하다. 생성된 모든 점에 대해 호출 된다는 것이다.

댓글 없음:

댓글 쓰기

Vertex , 정점 정보의 확장

Vertex , 정점 정보의 확장 그동안의 설명에 있어서 우리는 VERTEX 정보에 대하여 3 차원의 위치 정보만 사용하였다. struct VERTEX {float x,y,z;}; 이제 이를 확장하여 색상을...