Depth Testing

https://github.com/glium/glium/blob/master/book/tuto-09-depth.md

이전 내용은 모델의 뒤쪽에 있는 면이 모델의 앞쪽에 있는 면 위에 표시되는 문제가 있음

삼각형이 지정된 순서대로 다른 삼각형 위에 그려짐
index 배열의 마지막이 항상 맨 앞에 그려짐

깊이값 사용

GPU는 각 fragment의 깊이 값(주변 정점의 깊이에서 보간됨)을 가져와 이미 화면에 있는 픽셀의 깊이와 비교
깊이가 기존 값보다 가까운 경우 픽셀이 기록되고 깊이 값이 업데이트
이 방법에 의해 여러 픽셀이 겹칠 때 깊이 값이 가장 작은 픽셀만 남게됨
이것은 그리는 순서에 신경 쓰지 않고도 여러 개체(예: 여러 찻주전자)를 그릴 수 있음을 의미

Code

세 가지를 변경해야 함

  • 초기화 시 각 픽셀의 깊이 값을 포함할 깊이 버퍼를 생성하도록 glutin에 요청
let cb = glutin::ContextBuilder::new().with_depth_buffer(24);
  • 각 프레임 전에 깊이 버퍼의 내용을 1.0(최대값)으로 재설정
target.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);
  • GPU에 이 깊이 테스트를 수행하도록 요청하려면 그릴 때 추가 매개변수를 전달
let params = glium::DrawParameters {
    depth: glium::Depth {
        test: glium::draw_parameters::DepthTest::IfLess,
        write: true,
        .. Default::default()
    },
    .. Default::default()
};

target.draw((&positions, &normals), &indices, &program,
            &uniform! { matrix: matrix, u_light: light }, &params).unwrap();

전체 코드

#[macro_use]
extern crate glium;

mod teapot;

fn main() {
    #[allow(unused_imports)]
    use glium::{glutin, Surface};

    let mut event_loop = glutin::event_loop::EventLoop::new();
    let wb = glutin::window::WindowBuilder::new();
    let cb = glutin::ContextBuilder::new().with_depth_buffer(24);
    let display = glium::Display::new(wb, cb, &event_loop).unwrap();

    let positions = glium::VertexBuffer::new(&display, &teapot::VERTICES).unwrap();
    let normals = glium::VertexBuffer::new(&display, &teapot::NORMALS).unwrap();
    let indices = glium::IndexBuffer::new(
        &display,
        glium::index::PrimitiveType::TrianglesList,
        &teapot::INDICES,
    )
    .unwrap();

    let light = [-1.0, 0.4, 0.9f32];

    let vertex_shader_src = r#"
    #version 150      // updated

    in vec3 position;
    in vec3 normal;

    out vec3 v_normal;      // new

    uniform mat4 matrix;

    void main() {
        v_normal = transpose(inverse(mat3(matrix))) * normal;       // new
        gl_Position = matrix * vec4(position, 1.0);
    }
"#;

    let fragment_shader_src = r#"
    #version 140

    in vec3 v_normal;
    out vec4 color;
    uniform vec3 u_light;

    void main() {
        float brightness = dot(normalize(v_normal), normalize(u_light));
        vec3 dark_color = vec3(0.6, 0.0, 0.0);
        vec3 regular_color = vec3(1.0, 0.0, 0.0);
        color = vec4(mix(dark_color, regular_color, brightness), 1.0);
    }
"#;

    let program =
        glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None)
            .unwrap();

    let params = glium::DrawParameters {
        depth: glium::Depth {
            test: glium::draw_parameters::DepthTest::IfLess,
            write: true,
            .. Default::default()
        },
        .. Default::default()
    };
            
    let mut t: f32 = -0.5;
    event_loop.run(move |event, _, control_flow| {
        match event {
            glutin::event::Event::WindowEvent { event, .. } => match event {
                glutin::event::WindowEvent::CloseRequested => {
                    *control_flow = glutin::event_loop::ControlFlow::Exit;
                    return;
                }
                _ => return,
            },
            glutin::event::Event::NewEvents(cause) => match cause {
                glutin::event::StartCause::ResumeTimeReached { .. } => (),
                glutin::event::StartCause::Init => (),
                _ => return,
            },
            _ => return,
        }

        let next_frame_time =
            std::time::Instant::now() + std::time::Duration::from_nanos(16_666_667);
        *control_flow = glutin::event_loop::ControlFlow::WaitUntil(next_frame_time);

        t += 0.002;
        if t > 0.5 {
            t = -0.5;
        }

        let uniforms = uniform! {
            // matrix: [
            //     [ t.cos(), t.sin(), 0.0, 0.0],
            //     [-t.sin(), t.cos(), 0.0, 0.0],
            //     [0.0, 0.0, 1.0, 0.0],
            //     [0.0, 0.0, 0.0, 1.0f32],
            // ]
            matrix: [
                [0.01, 0.0, 0.0, 0.0],
                [0.0, 0.01, 0.0, 0.0],
                [0.0, 0.0, 0.01, 0.0],
                [0.0, 0.0, 0.0, 1.0f32]
            ],
            u_light: light
        };

        let mut target = display.draw();
        target.clear_color_and_depth((0.3, 0.5, 0.7, 1.0), 1.0);
        target
            .draw(
                (&positions, &normals),
                &indices,
                &program,
                &uniforms,
                &params,
            )
            .unwrap();
        target.finish().unwrap();
    });
}

좋은 웹페이지 즐겨찾기