본문 바로가기

그래픽스

[그래픽스] 쉐이더(Shader) 개념

쉐이더는 픽셀의 색을 결정할 때 필요한 것 정도로 알고 있었다.

좁은 의미에서는 가상 공간에서 물체들을 현실처럼 음영처리를 하고 색을 표현할 수 있게 해주는 것을 쉐이더라고 한다.

하지만 현대 그래픽스에서는 그 의미가 확장되어 GPU에서 작동하는 여러 프로그램들을 일반적으로 쉐이더라고  한다.

 

DirectX에서는 Vertex Shader와 Pixel Shader가 있다.

 

  for (size_t i = 0; i < mesh->vertexBuffer.size(); i++) {

            VSInput vsInput;
            vsInput.position = mesh->vertexBuffer[i];
            vsInput.color = mesh->colorBuffer[i];
            vsInput.uv = mesh->uvBuffer[i];

            auto vsOutput = MyVertexShader(vsInput);

            this->vertexBuffer[i] = vsOutput.position;
            this->colorBuffer[i] = vsOutput.color;
            this->uvBuffer[i] = vsOutput.uv;
        }

 

mesh의 vertexBuffer의 position, color, uv를 VSInput에 넣어주고 Vertex Shader을 돌리면 vsOutput에 출력값이 저장되고 이것을 rasterization의 vertexBuffer, colorBuffer, uvBuffer에 저장한다. 이렇게 Input을 넣으면 Output이 출력되기 때문에

쉐이더를 일종의 프로그램이라고 하는 것이다.

 

 for (size_t j = yMin; j <= yMax; j++) {
        for (size_t i = xMin; i <= xMax; i++) {

            const vec2 point = vec2(float(i), float(j));
            const float alpha0 = EdgeFunction(v1, v2, point);
            const float alpha1 = EdgeFunction(v2, v0, point);
            const float alpha2 = EdgeFunction(v0, v1, point);

            if (alpha0 >= 0.0f && alpha1 >= 0.0f && alpha2 >= 0.0f) {

                const float area = alpha0 + alpha1 + alpha2;
                const vec3 color =
                    (alpha0 * c0 + alpha1 * c1 + alpha2 * c2) / area;

                // UV 좌표(텍스춰 좌표)도 Bary-centric coordinates를 이용해서
                // interpolation
                const vec2 uv =
                    (alpha0 * uv0 + alpha1 * uv1 + alpha2 * uv2) / area;

                // 정투영(orthographic projection)에서만 정확합니다.
                // 뒤에서 Perspective Correct Interpolation으로 보정
                const float depth = (alpha0 * this->vertexBuffer[i0].z +
                                     alpha1 * this->vertexBuffer[i1].z +
                                     alpha2 * this->vertexBuffer[i2].z) /
                                    area;

                if (depth < depthBuffer[i + width * j]) {
                    depthBuffer[i + width * j] = depth;

                    PSInput psInput;
                    psInput.color = color;
                    psInput.uv = uv;

                    pixels[i + width * j] = MyPixelShader(psInput);
                }
            }
        }
    }

 

Pixel Shader을 할 때는 먼저 Input의 uv좌표를 color 정했던 것과 마찬가지로 무게중심 좌표계를 이용해 정한다.

그리고 PixelShader의 출력값을 픽셀에 저장한다. Vertex Shader은 정점에 대하여 계산을 하고 pixel은 모든 픽셀에 

대해서 계산을 한다.