Skip to content

Commit

Permalink
Add a simple render function implementing a minimal pipeline
Browse files Browse the repository at this point in the history
The `render` function takes in a list of triangles and a list of vertices,
a shader, and a render target. It passes the vertices through the vertex
shader, clips the resulting clip-space triangles, and rasterizes them into
the target using the fragment shader.
  • Loading branch information
jdahlstrom committed Oct 14, 2023
1 parent dd6a783 commit e469a7e
Showing 1 changed file with 71 additions and 1 deletion.
72 changes: 71 additions & 1 deletion core/src/render.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
//! Turning 3D geometry into raster images.
//!
//! This module constitutes the core 3D rendering pipeline of `retrofire`.
//! It contains code for [clipping][clip], [transforming, shading][shader],
//! [texturing][tex], [rasterizing][raster], and [outputting][target] basic
//! geometric shapes such as triangles.
use alloc::{vec, vec::Vec};
use core::fmt::Debug;

use clip::{view_frustum, Clip, ClipVec};
use raster::{tri_fill, Frag};
use shader::{FragmentShader, VertexShader};
use target::{Config, Target};

use crate::geom::{Tri, Vertex};
use crate::math::mat::{RealToProjective, RealToReal};
use crate::math::{Linear, Mat4x4, Vec3};

pub mod clip;
pub mod ctx;
pub mod raster;
pub mod shader;
pub mod target;
Expand All @@ -18,7 +36,7 @@ pub struct World;
#[derive(Copy, Clone, Debug, Default)]
pub struct View;

/// NDC (normalized device coordinates) space coordinate basis.
/// NDC space coordinate basis (normalized device coordinates).
#[derive(Copy, Clone, Debug, Default)]
pub struct Ndc;

Expand All @@ -37,3 +55,55 @@ pub type ViewToProjective = RealToProjective<View>;

/// Mapping from NDC space to screen space.
pub type NdcToScreen = RealToReal<3, Ndc, Screen>;

/// Renders the given triangles into `target`.
pub fn render<A, B, Sh, Uni, Tgt>(
tris: &[Tri<usize>],
verts: &[Vertex<Vec3, A>],
shader: &Sh,
uni: Uni,
vport_tf: Mat4x4<NdcToScreen>,
target: &mut Tgt,
) where
A: Clone + Debug,
B: Linear<Scalar = f32> + Clone + Debug,
Sh: VertexShader<Vertex<Vec3, A>, Uni, Output = Vertex<ClipVec, B>>
+ FragmentShader<Frag<B>>,
Uni: Copy,
Tgt: Target,
{
// Vertex shader
let verts: Vec<_> = verts
.iter()
// TODO Pass vertex as ref to shader
.cloned()
.map(|v| shader.shade_vertex(v, uni))
.collect();

let tris: Vec<_> = tris
.iter()
.map(|tri| Tri(tri.0.map(|i| verts[i].clone())))
.collect();

let mut clipped = vec![];
tris.clip(&view_frustum::PLANES, &mut clipped);

// TODO Optional depth sorting

for tri in clipped {
// TODO Backface culling

let vs = tri.0.clone().map(|v| Vertex {
pos: {
// Perspective divide
let pos = v.pos.project_to_real();
// Viewport transform
vport_tf.apply(&pos.to())
},
attrib: v.attrib,
});

// Fragment shader and rasterization
tri_fill(vs, |s| target.rasterize(s, shader, Config::default()))
}
}

0 comments on commit e469a7e

Please sign in to comment.