새소식

인기 검색어

게임 개발/그래픽스

깊이 버퍼 (Depth buffer / z-buffer)

  • -

여러 물체가 겹쳐 있을때 뭘 위에 그릴까?

depth buffer 라는 것을 만들어서 depth가 얕은것만 그리면 된다.

https://knowww.eu/nodes/59b8e93cd54a862e9d7e4165

 

Depth buffer (z-buffer)

Description The depth buffer is used to determine visibility, that is, which primitives in the scene are visible to the camera, and which are occluded by other primitives.  This is an example of hidden surface removal. The depth buffer, or z-buffer, is si

knowww.eu

depth buffer (z-buffer)

void Rasterization::DrawIndexedTriangle(const size_t &startIndex,
                                        vector<vec4> &pixels) {

    const size_t i0 = this->indexBuffer[startIndex];
    const size_t i1 = this->indexBuffer[startIndex + 1];
    const size_t i2 = this->indexBuffer[startIndex + 2];

    const auto v0 = ProjectWorldToRaster(this->vertexBuffer[i0]);
    const auto v1 = ProjectWorldToRaster(this->vertexBuffer[i1]);
    const auto v2 = ProjectWorldToRaster(this->vertexBuffer[i2]);

    const auto &c0 = this->colorBuffer[i0];
    const auto &c1 = this->colorBuffer[i1];
    const auto &c2 = this->colorBuffer[i2];

    const auto xMin = size_t(glm::clamp(
        glm::floor(std::min({v0.x, v1.x, v2.x})), 0.0f, float(width - 1)));
    const auto yMin = size_t(glm::clamp(
        glm::floor(std::min({v0.y, v1.y, v2.y})), 0.0f, float(height - 1)));
    const auto xMax = size_t(glm::clamp(glm::ceil(std::max({v0.x, v1.x, v2.x})),
                                        0.0f, float(width - 1)));
    const auto yMax = size_t(glm::clamp(glm::ceil(std::max({v0.y, v1.y, v2.y})),
                                        0.0f, float(height - 1)));

    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;

				// 정투영(orthographic projection)에서만 정확합니다.
				// 뒤에서 Perspective Correct Interpolation으로 보정
                //TODO: Bary-centric coordinates를 이용해서 z 좌표 찾기
                //const float depth = ...;
                const float z0 = this->vertexBuffer[i0].z;
                const float z1 = this->vertexBuffer[i1].z;
                const float z2 = this->vertexBuffer[i2].z;
                const float depth =
                    (alpha0 * z0 + alpha1 * z1 + alpha2 * z2) / area;

                //TODO: 조건 추가
                if (depth < depthBuffer[i + width * j]) {
                    //TODO: 깊이 버퍼 업데이트
                    pixels[i + width * j] = vec4(color, 1.0f);
                    depthBuffer[i + width * j] = depth;
                }
            }
        }
    }
}
void Rasterization::Render(vector<vec4> &pixels) {

	// 깊이 버퍼 초기화
	this->depthBuffer.resize(pixels.size());
    
    //TODO: 깊이 버퍼의 값도 초기화해줘야 합니다.
	// std::fill() 사용
    //this->depthBuffer.
    std::fill(this->depthBuffer.begin(), this->depthBuffer.end(), 1.0f);

    // 뒷쪽의 원을 나중에 그리기
    this->vertexBuffer.resize(circle1.vertexBuffer.size());
    for (size_t i = 0; i < circle1.vertexBuffer.size(); i++) {
        this->vertexBuffer[i] = circle1.vertexBuffer[i] + center1;
    }

    this->indexBuffer = circle1.indexBuffer;
    this->colorBuffer = circle1.colorBuffer;

    // 현재 버퍼로 삼각형 하나씩 그리기 (아래 for루프는 여러번 사용됨)
    for (size_t i = 0; i < this->indexBuffer.size(); i += 3) {
        DrawIndexedTriangle(i, pixels);
    }

    this->vertexBuffer.resize(circle2.vertexBuffer.size());
    for (size_t i = 0; i < circle2.vertexBuffer.size(); i++) {
        this->vertexBuffer[i] = circle2.vertexBuffer[i] + center2;
    }

    this->indexBuffer = circle2.indexBuffer;
    this->colorBuffer = circle2.colorBuffer;

    for (size_t i = 0; i < this->indexBuffer.size(); i += 3) {
        DrawIndexedTriangle(i, pixels);
    }

    this->vertexBuffer.resize(circle3.vertexBuffer.size());
    for (size_t i = 0; i < circle3.vertexBuffer.size(); i++) {
        this->vertexBuffer[i] = circle3.vertexBuffer[i] + center3;
    }

    this->indexBuffer = circle3.indexBuffer;
    this->colorBuffer = circle3.colorBuffer;

    for (size_t i = 0; i < this->indexBuffer.size(); i += 3) {
        DrawIndexedTriangle(i, pixels);
    }
}

'게임 개발 > 그래픽스' 카테고리의 다른 글

뒷면 제거 (backface culling)  (0) 2023.11.10
쉐이더 개념  (0) 2023.11.08
2차원 애니메이션  (0) 2023.11.07
2차원 변환  (0) 2023.11.07
원 그리기  (0) 2023.11.07
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.