mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-09 10:39:46 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33c7315b8b |
No files matched your search
@@ -690,7 +690,7 @@ pub struct PackPost {
|
||||
/// `depthtex0` at the screen's centre, read back for `centerDepthSmooth`.
|
||||
center_depth: Option<super::pack_center_depth::CenterDepth>,
|
||||
/// `shaders.properties`' custom uniforms, after the frame's in `uniforms.values`.
|
||||
custom: horizon_shaders::Custom,
|
||||
custom: Box<dyn horizon_render_pipeline::CustomUniforms>,
|
||||
atlas: Option<wgpu::TextureView>,
|
||||
material_maps: Option<[wgpu::TextureView; 2]>,
|
||||
/// The shared atlas's normal and specular paged maps (`set_paged_maps`).
|
||||
@@ -2528,17 +2528,15 @@ impl PackPost {
|
||||
}
|
||||
// shadowcolor2 to 7 only for a pack that names `HIGHER_SHADOWCOLOR`.
|
||||
let shadow_colors = (1u16 << post.shadow_colors) - 1;
|
||||
let mut custom = post.custom;
|
||||
let custom_names: Vec<(String, String)> = (custom.uniforms())
|
||||
.map(|(name, ty)| (name.to_owned(), ty.to_owned()))
|
||||
.collect();
|
||||
let mut custom: Box<dyn horizon_render_pipeline::CustomUniforms> = Box::new(post.custom);
|
||||
let custom_names = custom.names();
|
||||
// A first run finds the names neither the frame nor the pack defines.
|
||||
custom.eval(0.0, &pack_uniforms::zero);
|
||||
// Its zeros are no start for `smooth`: the first frame's values are, as in Iris.
|
||||
custom.restart_smoothing();
|
||||
if !custom.notes.is_empty() {
|
||||
notes.push(format!("custom uniforms: {}", custom.notes.join("; ")));
|
||||
custom.notes.clear();
|
||||
let custom_notes = custom.take_notes();
|
||||
if !custom_notes.is_empty() {
|
||||
notes.push(format!("custom uniforms: {}", custom_notes.join("; ")));
|
||||
}
|
||||
let mask =
|
||||
|flips: &[(u32, bool)]| flips.iter().filter(|f| f.1).fold(0u16, |m, f| m | 1 << f.0);
|
||||
@@ -5394,7 +5392,7 @@ impl PackPost {
|
||||
self.uniforms.update(frame, inputs, size);
|
||||
// `smooth` starts on the first frame that knows the camera's biome.
|
||||
self.custom.world_frame(inputs.biome_known);
|
||||
self.uniforms.eval_custom(&mut self.custom);
|
||||
self.uniforms.eval_custom(self.custom.as_mut());
|
||||
if self.targets.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
//! [-w, w], and the depth buffers packs read hold GL window depth.
|
||||
|
||||
use glam::{DMat4, DVec3, Mat4, Vec3, Vec4};
|
||||
use horizon_render_pipeline::Shadow;
|
||||
use horizon_render_pipeline::{CustomUniforms, Shadow, Val};
|
||||
|
||||
use super::Frame;
|
||||
|
||||
@@ -1050,8 +1050,8 @@ impl FrameUniforms {
|
||||
|
||||
impl FrameUniforms {
|
||||
/// Evaluates the pack's custom uniforms with this frame's values and puts them after
|
||||
/// `NAMES`' values, in `custom.uniforms()` order.
|
||||
pub fn eval_custom(&mut self, custom: &mut horizon_shaders::Custom) {
|
||||
/// `NAMES`' values, in `custom.names()` order.
|
||||
pub fn eval_custom(&mut self, custom: &mut dyn CustomUniforms) {
|
||||
if let Some(tick) = self.custom_restart {
|
||||
custom.restart_at(tick);
|
||||
}
|
||||
@@ -1061,8 +1061,8 @@ impl FrameUniforms {
|
||||
let v = values.get(index(name)?)?;
|
||||
let n = components(name);
|
||||
Some(match *v {
|
||||
Value::F(f) => horizon_shaders::Val::vector(&f.map(f64::from)[..n]),
|
||||
Value::I(i) => horizon_shaders::Val::vector(&i.map(f64::from)[..n.min(3)]),
|
||||
Value::F(f) => Val::vector(&f.map(f64::from)[..n]),
|
||||
Value::I(i) => Val::vector(&i.map(f64::from)[..n.min(3)]),
|
||||
})
|
||||
};
|
||||
let dt = match index("frameTime").and_then(|i| values.get(i)) {
|
||||
@@ -1144,9 +1144,9 @@ fn components(name: &str) -> usize {
|
||||
|
||||
/// What `name` gives custom uniforms before the first frame: zeros, at its size, so their
|
||||
/// shapes check out as on a frame (#9086).
|
||||
pub fn zero(name: &str) -> Option<horizon_shaders::Val> {
|
||||
pub fn zero(name: &str) -> Option<Val> {
|
||||
index(name)?;
|
||||
Some(horizon_shaders::Val::vector(&[0.0; 16][..components(name)]))
|
||||
Some(Val::vector(&[0.0; 16][..components(name)]))
|
||||
}
|
||||
|
||||
/// The position of `name` in [`NAMES`].
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//! A pack's custom uniforms: values the pack computes on the CPU each frame from the game's own
|
||||
//! uniforms, which the renderer then hands its programs after the frame's. The renderer only
|
||||
//! drives the evaluator ([`CustomUniforms`]); the pack format supplies it (`horizon-shaders`'
|
||||
//! `Custom` reads `shaders.properties`' expressions).
|
||||
|
||||
/// A value: up to 16 components (matrices only as names, for `m.column.row`).
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Val {
|
||||
pub v: [f64; 16],
|
||||
/// Components: 1 for a scalar.
|
||||
pub n: usize,
|
||||
}
|
||||
|
||||
impl Val {
|
||||
pub fn scalar(x: f64) -> Self {
|
||||
let mut v = [0.0; 16];
|
||||
v[0] = x;
|
||||
Self { v, n: 1 }
|
||||
}
|
||||
pub fn vector(c: &[f64]) -> Self {
|
||||
let mut v = [0.0; 16];
|
||||
v[..c.len()].copy_from_slice(c);
|
||||
Self { v, n: c.len() }
|
||||
}
|
||||
}
|
||||
|
||||
/// What the renderer asks of a pack's custom uniforms. Called once per frame of a pack, never on
|
||||
/// vanilla's path.
|
||||
pub trait CustomUniforms: Send + Sync {
|
||||
/// The uniforms' names and declared types, in the order [`CustomUniforms::eval`] returns
|
||||
/// their values.
|
||||
fn names(&self) -> Vec<(String, String)>;
|
||||
|
||||
/// Evaluates everything for a frame `dt` seconds after the last; `builtin` gives the values
|
||||
/// of the game's uniforms and constants. Returns the uniforms' values, in `names` order.
|
||||
fn eval(&mut self, dt: f64, builtin: &dyn Fn(&str) -> Option<Val>) -> Vec<Val>;
|
||||
|
||||
/// Forgets what smoothing keeps: each smoothed value starts again from its next value.
|
||||
fn restart_smoothing(&mut self);
|
||||
|
||||
/// Called before each frame's `eval`, with whether the camera's biome is known.
|
||||
fn world_frame(&mut self, biome_known: bool);
|
||||
|
||||
/// Forgets the world's frames, as a pack just loaded has seen none.
|
||||
fn forget_world(&mut self);
|
||||
|
||||
/// Restarts smoothing and randomness for a frame of the world's tick `tick`, so a frame
|
||||
/// drawn again at that tick evaluates the same.
|
||||
fn restart_at(&mut self, tick: u64);
|
||||
|
||||
/// The problems found so far (expressions that did not parse, unknown names), emptied.
|
||||
fn take_notes(&mut self) -> Vec<String>;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
//! `shaders/` packs). No wgpu and no pack file here.
|
||||
//!
|
||||
//! - [`config`]: the colortex buffers and the shadow map: formats, clearing, mipmaps, settings.
|
||||
//! - [`custom`]: the pack's custom uniforms, which the renderer evaluates each frame.
|
||||
//! - [`program`]: a translated program (naga modules and their interface) and the vertex
|
||||
//! inputs the renderer offers it.
|
||||
//! - [`textures`]: the custom textures the programs read; [`RENDER_STAGES`]: the stages they draw in.
|
||||
@@ -14,6 +15,7 @@
|
||||
|
||||
mod api;
|
||||
pub mod config;
|
||||
pub mod custom;
|
||||
pub mod inputs;
|
||||
pub mod program;
|
||||
mod render_stage;
|
||||
@@ -25,6 +27,7 @@ pub use config::{
|
||||
BUFFERS, Buffer, Config, Format, HALF_LIVES, Kind, SHADOW_COLORS, Shadow, buffer_index,
|
||||
shadow_color,
|
||||
};
|
||||
pub use custom::{CustomUniforms, Val};
|
||||
pub use inputs::Frame;
|
||||
pub use program::{
|
||||
AlphaTest, ComputeProgram, GbuffersInputs, GeometryInputs, Interface, Program, WATER_MASK,
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use horizon_render_pipeline::custom::CustomUniforms;
|
||||
|
||||
use crate::Properties;
|
||||
|
||||
/// The seconds one unit of a `smooth` fade time lasts. Fitted to Iris 1.11.7 with a probe pack of
|
||||
@@ -36,25 +38,17 @@ use crate::Properties;
|
||||
/// unit (`pack_uniforms.rs` `SECONDS_A_TICK`).
|
||||
const FADE_UNIT: f64 = 0.1;
|
||||
|
||||
/// A value: up to 16 components (matrices only as names, for `m.column.row`).
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Val {
|
||||
pub v: [f64; 16],
|
||||
/// Components: 1 for a scalar.
|
||||
pub n: usize,
|
||||
pub use horizon_render_pipeline::custom::Val;
|
||||
|
||||
/// The evaluator's arithmetic on [`Val`].
|
||||
trait ValOps {
|
||||
fn x(&self) -> f64;
|
||||
fn truth(&self) -> bool;
|
||||
fn zip(self, o: Val, f: impl Fn(f64, f64) -> f64) -> Val;
|
||||
fn map(self, f: impl Fn(f64) -> f64) -> Val;
|
||||
}
|
||||
|
||||
impl Val {
|
||||
pub fn scalar(x: f64) -> Self {
|
||||
let mut v = [0.0; 16];
|
||||
v[0] = x;
|
||||
Self { v, n: 1 }
|
||||
}
|
||||
pub fn vector(c: &[f64]) -> Self {
|
||||
let mut v = [0.0; 16];
|
||||
v[..c.len()].copy_from_slice(c);
|
||||
Self { v, n: c.len() }
|
||||
}
|
||||
impl ValOps for Val {
|
||||
fn x(&self) -> f64 {
|
||||
self.v[0]
|
||||
}
|
||||
@@ -588,6 +582,32 @@ impl Custom {
|
||||
}
|
||||
}
|
||||
|
||||
impl CustomUniforms for Custom {
|
||||
fn names(&self) -> Vec<(String, String)> {
|
||||
(self.uniforms())
|
||||
.map(|(name, ty)| (name.to_owned(), ty.to_owned()))
|
||||
.collect()
|
||||
}
|
||||
fn eval(&mut self, dt: f64, builtin: &dyn Fn(&str) -> Option<Val>) -> Vec<Val> {
|
||||
Custom::eval(self, dt, builtin)
|
||||
}
|
||||
fn restart_smoothing(&mut self) {
|
||||
Custom::restart_smoothing(self);
|
||||
}
|
||||
fn world_frame(&mut self, biome_known: bool) {
|
||||
Custom::world_frame(self, biome_known);
|
||||
}
|
||||
fn forget_world(&mut self) {
|
||||
Custom::forget_world(self);
|
||||
}
|
||||
fn restart_at(&mut self, tick: u64) {
|
||||
Custom::restart_at(self, tick);
|
||||
}
|
||||
fn take_notes(&mut self) -> Vec<String> {
|
||||
std::mem::take(&mut self.notes)
|
||||
}
|
||||
}
|
||||
|
||||
struct Parser<'a> {
|
||||
tokens: Vec<String>,
|
||||
at: usize,
|
||||
|
||||
Reference in new issue
Block a user