xfitgd / xfit

vulkan based windows android cross platform game engine
0 stars 0 forks source link

Pixel Perfect Rendering #7

Closed xfitgd closed 2 weeks ago

xfitgd commented 3 weeks ago

특정 이미지를 100% 정확한 확대 상태로 렌더링을 쉽게 하기 위한 체계를 만듭니다. 백앤드 vulkan이 화면 좌표가 float실수라 거기에 맞춥니다. 그리고 특정 캔버스 크기를 정하고 그 상태에서 이미지를 렌더링 했을때 화면 크기를 변경해도 일정한 비율로 이미지가 나오게 합니다. 예를 들어 FHD 1920x1080으로 960x540 이미지를 렌더링 했을때 항상 화면의 1/4을 차지해야 합니다.

xfitgd commented 2 weeks ago
pub fn init_matrix_orthographic(self: *Self, _width: f32, _height: f32) matrix_error!void {
        const width = @as(f32, @floatFromInt(window.window_width()));
        const height = @as(f32, @floatFromInt(window.window_height()));
        const ratio = if (width / height > _width / _height) _height / height else _width / width;
        self.*.proj = try matrix.orthographicLhVulkan(
            width * ratio,
            height * ratio,
            0.1,
            100,
        );
    }

_width, _height는 기준 캔버스 사이즈입니다. 이렇게 하면 이미지 크기는 이미지 픽셀 width height 만큼 scale로 설정만 하면 되고 텍스트의 경우는 x,y scale 동일하게 적절한 크기로 맞추면 됩니다.

xfitgd commented 2 weeks ago
///회전 했을때 고려안함, img scale은 기본(이미지 크기) 비율일때 기준
    pub fn pixel_perfect_point(img: Self, _p: point, _canvas_w: f32, _canvas_h: f32, center: center_pt_pos) point {
        const width = @as(f32, @floatFromInt(window.window_width()));
        const height = @as(f32, @floatFromInt(window.window_height()));
        if (width / height > _canvas_w / _canvas_h) { //1배 비율이 아니면 적용할수 없다.
            if (_canvas_h != height) return _p;
        } else {
            if (_canvas_w != width) return _p;
        }
        _p = @floor(_p);
        if (window.window_width() % 2 != 0) _p.x -= 0.5;
        if (window.window_height() % 2 != 0) _p.y += 0.5;

        switch (center) {
            .center => {
                if (img.src.*.texture.width % 2 != 0) _p.x += 0.5;
                if (img.src.*.texture.height % 2 != 0) _p.y -= 0.5;
            },
            .right, .left => {
                if (img.src.*.texture.height % 2 != 0) _p.y -= 0.5;
            },
            .top, .bottom => {
                if (img.src.*.texture.width % 2 != 0) _p.x += 0.5;
            },
            else => {},
        }
        return _p;
    }

이렇게 만들어는 봤는데 다만 쓰임새는 많이 제한적입니다. https://github.com/xfitgd/zig-game-engine-project/commit/e90f50f7a49bd2ef4f54fed865993f65cbbe38a0