Theme

alex/beta-minecraft-rust

Minecraft Beta 1.7.3 Rewrite

BRANCH main
main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
Download file

root / crates / client / src / render / mesher / plants.rs

//! `renderBlockReed` (crossed squares) and `renderBlockCactus`.

use common::world::Block;
use common::world::shape::SIDE_OFFSETS;
use glam::Vec3;

use super::block::{self, Bounds};
use super::{Builder, Cache, MeshInput, Shade, WHITE, tile};

/// `renderBlockReed` and `renderCrossedSquares`: two crossed, double-sided planes.
pub fn cross(
    input: &MeshInput,
    cache: &Cache,
    builder: &mut Builder,
    plant: Block,
    position: [i32; 3],
) {
    let [x, y, z] = position;
    let light = cache.light(x, y, z).with_emission(plant.light_emission());
    let rgb = block::color(input, cache, plant, position);
    let offset = if plant == Block::TALL_GRASS {
        let [wx, wy, wz] = cache.world(position);
        let mut hash = i64::from(wx.wrapping_mul(3_129_871))
            ^ i64::from(wz).wrapping_mul(116_129_781)
            ^ i64::from(wy);
        hash = hash
            .wrapping_mul(hash)
            .wrapping_mul(42_317_861)
            .wrapping_add(hash.wrapping_mul(11));
        let nibble = |shift: i64| f64::from((hash >> shift & 15) as f32 / 15.0);
        Vec3::new(
            ((nibble(16) - 0.5) * 0.5) as f32,
            ((nibble(20) - 1.0) * 0.2) as f32,
            ((nibble(24) - 0.5) * 0.5) as f32,
        )
    } else {
        Vec3::ZERO
    };

    let texture = block::texture(cache, plant, position, 0, input.fancy);
    let [u0, u1, v0, v1] = tile(texture);
    let (lo, hi) = (
        (0.5 - f64::from(0.45_f32)) as f32,
        (0.5 + f64::from(0.45_f32)) as f32,
    );
    let plane = |a: (f32, f32), b: (f32, f32)| {
        let p = |(x, z): (f32, f32), y: f32| offset + Vec3::new(x, y, z);
        [
            (p(a, 1.0), (u0, v0)),
            (p(a, 0.0), (u0, v1)),
            (p(b, 0.0), (u1, v1)),
            (p(b, 1.0), (u1, v0)),
        ]
    };
    for (a, b) in [
        ((lo, lo), (hi, hi)),
        ((hi, hi), (lo, lo)),
        ((lo, hi), (hi, lo)),
        ((hi, lo), (lo, hi)),
    ] {
        builder.quad(plane(a, b), light, Shade::Top, rgb);
    }
}

/// `renderBlockCactusImpl`: a cube whose sides are drawn 1/16 inside the block.
pub fn cactus(
    cache: &Cache,
    builder: &mut Builder,
    cactus: Block,
    position: [i32; 3],
    fancy: bool,
) {
    const INSET: f32 = 1.0 / 16.0;
    let [x, y, z] = position;
    let emission = cactus.light_emission();
    for (face, [dx, dy, dz]) in SIDE_OFFSETS.into_iter().enumerate() {
        if !block::side_visible(cache, cactus, position, face, &Bounds::UNIT, fancy) {
            continue;
        }
        let light = cache.light(x + dx, y + dy, z + dz).with_emission(emission);
        let shift = Vec3::new(-dx as f32, 0.0, -dz as f32) * INSET;
        let texture = block::texture(cache, cactus, position, face, fancy);
        let quad = block::face_quad(face, &Bounds::UNIT, texture).map(|(p, uv)| (p + shift, uv));
        builder.quad(quad, light, block::shade(face), WHITE);
    }
}