neocogi 0.2.0

neocogi rendering lib
Documentation
//
// Copyright 2021-Present (c) Raja Lehtihet & Wael El Oraiby
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
extern crate neocogi;

use neocogi::glfw;
use neocogi::glfw::{Action, Context, Key};

use neocogi::rs_math3d::*;
use neocogi::*;

use neocogi::renderer::*;

use std::sync::*;

static VERTEX_SHADER: &'static str = "
#version 300 es
in  highp   vec4        position;
in  highp   vec4        color;
out highp   vec4        v_color;
void main() {
    gl_Position = position;
    v_color     = color;
}";

static PIXEL_SHADER: &'static str = "
#version 300 es
precision mediump float;
        in highp    vec4        v_color;
layout(location = 0) out lowp  vec4     color_buffer;
void main() {
    highp vec4 col  = v_color;
    color_buffer    = col;
}";

render_data! {
    vertex Vertex {
        position: Vec4f,
        color   : Vec4f,
    }
}

fn init_render_objects(driver: &mut DriverPtr) -> PipelinePtr {
    let mut model_attribs = Vec::new();
    model_attribs.push(Vertex::get_attribute_names());

    let model_shader_desc = ShaderDesc {
        vertex_shader: String::from(VERTEX_SHADER),
        pixel_shader: String::from(PIXEL_SHADER),

        vertex_attributes: model_attribs,
        vertex_uniforms: Vec::new(),
        vertex_surfaces: Vec::new(),

        pixel_uniforms: Vec::new(),
        pixel_surfaces: Vec::new(),
    };

    let model_program = driver.create_shader(model_shader_desc).unwrap();

    let vertex_layout = VertexBufferLayout {
        buffer_id: 0,
        vertex_attributes: Vertex::get_attribute_descriptors(),
        stride: Vertex::stride(),
        divisor: 0,
    };

    let tri_pipeline_desc = PipelineDesc {
        primitive_type: PrimitiveType::Triangles,
        shader: model_program.clone(),
        buffer_layouts: vec![vertex_layout.clone()],
        uniform_descs: Vec::new(),
        index_type: IndexType::None,
        face_winding: FaceWinding::CCW,
        cull_mode: CullMode::None,
        depth_write: true,
        depth_test: true,
        blend: BlendOp::None,
        polygon_offset: PolygonOffset::None,
    };

    driver.create_pipeline(tri_pipeline_desc).unwrap()
}

fn main() {
    // initialize GLFW3 with OpenGL ES 3.0
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextCreationApi(
        glfw::ContextCreationApi::Egl,
    ));
    glfw.window_hint(glfw::WindowHint::ClientApi(glfw::ClientApiHint::OpenGlEs));
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 0));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(
        glfw::OpenGlProfileHint::Core,
    ));
    glfw.window_hint(glfw::WindowHint::DoubleBuffer(true));
    glfw.window_hint(glfw::WindowHint::Resizable(true));
    glfw.window_hint(glfw::WindowHint::Floating(true));

    let (mut window, events) = glfw
        .create_window(1024, 900, "Triangle", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.set_char_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_key_polling(true);
    window.set_mouse_button_polling(true);
    window.make_current();
    glfw.set_swap_interval(glfw::SwapInterval::Sync(1));

    let mut driver = renderer::get_driver();

    let vertices = vec![
        Vertex {
            position: Vec4f::new(-0.5, -0.5, 0.0, 1.0),
            color: Vec4f::new(1.0, 0.0, 0.0, 1.0),
        },
        Vertex {
            position: Vec4f::new(0.5, -0.5, 0.0, 1.0),
            color: Vec4f::new(0.0, 0.0, 1.0, 1.0),
        },
        Vertex {
            position: Vec4f::new(0.0, 0.5, 0.0, 1.0),
            color: Vec4f::new(0.0, 1.0, 0.0, 1.0),
        },
    ];

    let mut vertex_buffer = driver
        .create_device_buffer(DeviceBufferDesc::Vertex(Usage::Dynamic(
            3 * std::mem::size_of::<Vertex>(),
        )))
        .unwrap();
    let pipeline = init_render_objects(&mut driver);

    let mut quit = false;
    while !window.should_close() {
        let (width, height) = window.get_framebuffer_size();

        let mut pass = Pass::new(
            width as usize,
            height as usize,
            None,
            [
                ColorPassAction::Clear(color4b(0x00, 0x00, 0x00, 0x00)),
                ColorPassAction::Previous,
                ColorPassAction::Previous,
                ColorPassAction::Previous,
            ],
            DepthPassAction::Clear(1.0),
        );

        let bindings = Bindings {
            vertex_buffers: vec![vertex_buffer.clone()],
            index_buffer: None,

            vertex_images: Vec::new(),
            pixel_images: Vec::new(),
        };

        pass.update_device_buffer(&mut vertex_buffer, 0, Arc::new(vertices.to_vec()));
        pass.draw(&pipeline, &bindings, Arc::new(Vec::<Vec3f>::new()), 1, 1);
        driver.render_pass(&mut pass);
        window.swap_buffers();

        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::WindowEvent::Key(glfw::Key::Escape, _, _, _) | glfw::WindowEvent::Close => {
                    quit = true
                }
                _ => (),
            }
        }

        if quit {
            window.set_should_close(true)
        }
    }
}