more materials

This commit is contained in:
Robin Appelman 2023-12-19 16:59:01 +01:00
commit 40ffcb41de
9 changed files with 262 additions and 16 deletions

View file

@ -6,7 +6,7 @@ pub use texture_transform::TextureTransform;
#[derive(Debug, Serialize, Deserialize, Copy, Clone)] #[derive(Debug, Serialize, Deserialize, Copy, Clone)]
#[serde(from = "Vec2OrSingle<f32>")] #[serde(from = "Vec2OrSingle<f32>")]
pub struct Vec2([f32; 2]); pub struct Vec2(pub [f32; 2]);
impl From<Vec2OrSingle<f32>> for Vec2 { impl From<Vec2OrSingle<f32>> for Vec2 {
fn from(value: Vec2OrSingle<f32>) -> Self { fn from(value: Vec2OrSingle<f32>) -> Self {
@ -19,7 +19,7 @@ impl From<Vec2OrSingle<f32>> for Vec2 {
#[derive(Debug, Serialize, Deserialize, Copy, Clone)] #[derive(Debug, Serialize, Deserialize, Copy, Clone)]
#[serde(from = "Vec3OrSingle<f32>")] #[serde(from = "Vec3OrSingle<f32>")]
pub struct Vec3([f32; 3]); pub struct Vec3(pub [f32; 3]);
impl From<Vec3OrSingle<f32>> for Vec3 { impl From<Vec3OrSingle<f32>> for Vec3 {
fn from(value: Vec3OrSingle<f32>) -> Self { fn from(value: Vec3OrSingle<f32>) -> Self {

View file

@ -1,10 +0,0 @@
use miette::Diagnostic;
use thiserror::Error;
use vdf_reader::VdfError;
#[derive(Debug, Error, Diagnostic)]
pub enum VmtError {
#[error(transparent)]
#[diagnostic(transparent)]
Vdf(#[from] VdfError),
}

View file

@ -1,14 +1,14 @@
mod data; mod data;
mod error;
pub mod material; pub mod material;
use crate::material::Material; use crate::material::Material;
pub use data::*; pub use data::*;
pub use error::VmtError;
pub type Result<T, E = VmtError> = std::result::Result<T, E>; pub type Result<T, E = VdfError> = std::result::Result<T, E>;
pub fn from_str(input: &str) -> Result<Material> { pub fn from_str(input: &str) -> Result<Material> {
let input = input.to_ascii_lowercase(); let input = input.to_ascii_lowercase();
vdf_reader::from_str(&input).map_err(VmtError::from) vdf_reader::from_str(&input)
} }
pub use vdf_reader::VdfError;

View file

@ -0,0 +1,66 @@
use crate::{default_scale, Vec3};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EyeRefractMaterial {
/// Usually referred to as a "sludge-layer", acts as a layer on top of the surface of the $AboveWater Material.
#[serde(rename = "$iris")]
pub iris: String,
/// A texture to specify the shape of the cornea, similar to a normal map. Influences lighting and dilation. The red and green channels are used for the normal mapping, the blue channel is a mask for parallax mapping (straight multiply), and the alpha channel seems to be a multiplier for lighting. Because the $iris is warped in various ways the normals will not match 1-to-1 with the base texture.
#[serde(rename = "$corneatexture")]
pub cornea_texture: String,
/// Strength of the $corneatexture.
#[serde(rename = "$corneabumpstrength", default = "default_scale")]
pub cornea_bump_strength: f32,
/// How much the viewing angle should influence the positioning of the eye
#[serde(rename = "$parallaxstrength", default = "default_parallax_strength")]
pub parallax_strength: f32,
/// Dilates the pupil using the cornea texture to determine the shape of dilation. Default 0.5.
#[serde(rename = "$dilation", default = "default_dilation")]
pub dilation: f32,
/// 1-dimensional texture which remaps lighting colors.
#[serde(rename = "$lightwarptexture")]
pub light_warp_texture: String,
/// Enables cubemap reflections. This shader has a specific cubemap made for it, engine/eye-reflection-cubemap-.vtf, but others can be used, including env_cubemap.
#[serde(rename = "$envmap")]
pub env_map: String,
/// The opacity of the cubemap reflection. Does not affect the eye glint. Default 0.5.
#[serde(rename = "$glossiness", default = "default_dilation")]
pub glossiness: f32,
/// An ambient occlusion texture overlaid onto the entire eye
#[serde(rename = "$ambientoccltexture")]
pub ambient_occlusion_texture: String,
/// Tints the $ambientoccltexture
#[serde(rename = "$ambientocclcolor", default = "default_occl_color")]
pub ambient_occlusion_color: Vec3,
/// Strength of the dynamic ambient occlusion.
#[serde(rename = "$ambientocclusion", default = "default_scale")]
pub ambiento_cclusion: f32,
/// Enables half-lambertian lighting
#[serde(rename = "$halflambert", default)]
pub half_lambert: bool,
/// Enables sphere raytracing. Each pixel is raytraced to allow sharper angles to look more accurate.
#[serde(rename = "$raytracesphere", default)]
pub ray_trace_sphere: bool,
/// Requires $raytracesphere 1. Causes pixels which don't hit the raytraced sphere to be transparent, instead of rendering the "non-raytraced" eye behind it.
#[serde(rename = "$spheretexkillcombo", default)]
pub sphere_tex_kill_combo: bool,
/// Requires $raytracesphere 1. Radius of the eyeball. Should be the diameter of the eyeball divided by 2
#[serde(rename = "$eyeballradius", default = "default_dilation")]
pub eye_ball_radius: f32,
}
fn default_parallax_strength() -> f32 {
0.25
}
fn default_dilation() -> f32 {
0.5
}
fn default_occl_color() -> Vec3 {
Vec3([0.33; 3])
}

View file

@ -52,6 +52,9 @@ pub struct LightMappedGenericMaterial {
/// Specifies a mask to use to determine binary opacity. /// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatest", default)] #[serde(rename = "$alphatest", default)]
pub alpha_test: bool, pub alpha_test: bool,
/// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatestreference", default = "default_scale")]
pub alpha_test_reference: f32,
/// Vector-like edge filtering. /// Vector-like edge filtering.
#[serde(rename = "$distancealpha", default)] #[serde(rename = "$distancealpha", default)]
pub distance_alpha: bool, pub distance_alpha: bool,

View file

@ -1,14 +1,18 @@
mod eyerefract;
mod lightmappedgeneric; mod lightmappedgeneric;
mod unlitgeneric; mod unlitgeneric;
mod vertexlitgeneric;
mod water; mod water;
mod worldvertextransition; mod worldvertextransition;
pub use eyerefract::EyeRefractMaterial;
pub use lightmappedgeneric::LightMappedGenericMaterial; pub use lightmappedgeneric::LightMappedGenericMaterial;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub use unlitgeneric::UnlitGenericMaterial; pub use unlitgeneric::UnlitGenericMaterial;
use vdf_reader::entry::{Entry, Table}; use vdf_reader::entry::{Entry, Table};
use vdf_reader::error::UnknownError; use vdf_reader::error::UnknownError;
use vdf_reader::{from_entry, VdfError}; use vdf_reader::{from_entry, VdfError};
pub use vertexlitgeneric::VertexLitGenericMaterial;
pub use water::WaterMaterial; pub use water::WaterMaterial;
pub use worldvertextransition::WorldVertexTransitionMaterial; pub use worldvertextransition::WorldVertexTransitionMaterial;
@ -16,12 +20,16 @@ pub use worldvertextransition::WorldVertexTransitionMaterial;
pub enum Material { pub enum Material {
#[serde(rename = "lightmappedgeneric")] #[serde(rename = "lightmappedgeneric")]
LightMappedGeneric(LightMappedGenericMaterial), LightMappedGeneric(LightMappedGenericMaterial),
#[serde(rename = "vertexlitgeneric")]
VertexLitGeneric(VertexLitGenericMaterial),
#[serde(rename = "unlitgeneric")] #[serde(rename = "unlitgeneric")]
UnlitGeneric(UnlitGenericMaterial), UnlitGeneric(UnlitGenericMaterial),
#[serde(rename = "water")] #[serde(rename = "water")]
Water(WaterMaterial), Water(WaterMaterial),
#[serde(rename = "worldvertextransition")] #[serde(rename = "worldvertextransition")]
WorldVertexTransition(WorldVertexTransitionMaterial), WorldVertexTransition(WorldVertexTransitionMaterial),
#[serde(rename = "eyerefract")]
EyeRefract(EyeRefractMaterial),
#[serde(rename = "patch")] #[serde(rename = "patch")]
Patch(PatchMaterial), Patch(PatchMaterial),
} }
@ -38,6 +46,83 @@ impl Material {
mat => Ok(mat), mat => Ok(mat),
} }
} }
pub fn translucent(&self) -> bool {
match self {
Material::LightMappedGeneric(mat) => mat.translucent,
Material::VertexLitGeneric(mat) => mat.translucent,
Material::UnlitGeneric(mat) => mat.translucent,
Material::WorldVertexTransition(mat) => mat.translucent,
Material::Water(_) => true,
_ => false,
}
}
pub fn no_cull(&self) -> bool {
match self {
Material::LightMappedGeneric(mat) => mat.no_cull,
Material::VertexLitGeneric(mat) => mat.no_cull,
Material::UnlitGeneric(mat) => mat.no_cull,
Material::WorldVertexTransition(mat) => mat.no_cull,
Material::Water(_) => true,
_ => false,
}
}
pub fn alpha_test(&self) -> Option<f32> {
match self {
Material::LightMappedGeneric(mat) => mat.alpha_test.then_some(mat.alpha_test_reference),
Material::VertexLitGeneric(mat) => mat.alpha_test.then_some(mat.alpha_test_reference),
Material::UnlitGeneric(mat) => mat.alpha_test.then_some(mat.alpha_test_reference),
Material::WorldVertexTransition(mat) => {
mat.alpha_test.then_some(mat.alpha_test_reference)
}
Material::Water(_) => None,
_ => None,
}
}
pub fn base_texture(&self) -> &str {
match self {
Material::LightMappedGeneric(mat) => &mat.base_texture,
Material::VertexLitGeneric(mat) => &mat.base_texture,
Material::UnlitGeneric(mat) => &mat.base_texture,
Material::WorldVertexTransition(mat) => &mat.base_texture,
Material::Water(mat) => &mat.base_texture,
Material::EyeRefract(mat) => &mat.iris,
_ => "",
}
}
pub fn bump_map(&self) -> Option<&str> {
match self {
Material::LightMappedGeneric(mat) => mat.bump_map.as_deref(),
Material::VertexLitGeneric(mat) => mat.bump_map.as_deref(),
Material::UnlitGeneric(mat) => mat.bump_map.as_deref(),
Material::WorldVertexTransition(mat) => mat.bump_map.as_deref(),
Material::Water(mat) => mat.bump_map.as_deref(),
_ => None,
}
}
pub fn surface_prop(&self) -> Option<&str> {
match self {
Material::LightMappedGeneric(mat) => mat.surface_prop.as_deref(),
Material::UnlitGeneric(mat) => mat.surface_prop.as_deref(),
Material::WorldVertexTransition(mat) => mat.surface_prop.as_deref(),
_ => None,
}
}
pub fn alpha(&self) -> f32 {
match self {
Material::LightMappedGeneric(mat) => mat.alpha,
Material::VertexLitGeneric(mat) => mat.alpha,
Material::UnlitGeneric(mat) => mat.alpha,
Material::WorldVertexTransition(mat) => mat.alpha,
_ => 1.0,
}
}
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]

View file

@ -23,6 +23,9 @@ pub struct UnlitGenericMaterial {
/// Specifies a mask to use to determine binary opacity. /// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatest", default)] #[serde(rename = "$alphatest", default)]
pub alpha_test: bool, pub alpha_test: bool,
/// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatestreference", default = "default_scale")]
pub alpha_test_reference: f32,
/// Disables backface culling. /// Disables backface culling.
#[serde(rename = "$nocull", default)] #[serde(rename = "$nocull", default)]
pub no_cull: bool, pub no_cull: bool,
@ -30,6 +33,10 @@ pub struct UnlitGenericMaterial {
#[serde(rename = "$translucent", default)] #[serde(rename = "$translucent", default)]
pub translucent: bool, pub translucent: bool,
/// Specifies a texture that will provide three-dimensional lighting information for a material.
#[serde(rename = "$bumpmap")]
pub bump_map: Option<String>,
/// Ignore z filtering /// Ignore z filtering
#[serde(rename = "$ignorez", default)] #[serde(rename = "$ignorez", default)]
pub ignore_z: bool, pub ignore_z: bool,

View file

@ -0,0 +1,92 @@
use crate::{
default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VertexLitGenericMaterial {
/// Defines an albedo texture.
#[serde(rename = "$basetexture")]
pub base_texture: String,
/// Detail texturing.
#[serde(rename = "$detail")]
pub detail: Option<String>,
/// Use a 2nd UV channel for high-resolution decal support.
#[serde(rename = "$decaltexture")]
pub decal_texture: Option<String>,
/// Color tinting
#[serde(rename = "$color2", default = "default_scale3")]
pub color2: Vec3,
/// Transforms the texture before use in the material. This does not affect lightmaps on the surface.
#[serde(rename = "$basetexturetransform", default)]
pub base_texture_transform: TextureTransform,
/// Independently scales the red, green and blue channels of an albedo.
#[serde(rename = "$color", default = "default_scale3")]
pub color: Vec3,
#[serde(rename = "$decalscale", default = "default_detail_scale")]
/// Fits the detail texture onto the material the given number of times
pub detail_scale: Vec2,
/// Controls the amount that the detail texture affects the base texture. The precise use of this depends on the blend factor; in most cases it acts similarly to $alpha. A value of 0 usually makes the detail texture have no effect, whilst a value of 1 applies the full effect.
#[serde(rename = "$detailblendfactor", default = "default_scale")]
pub detail_blend_factor: f32,
/// How to combine the detail material with the albedo.
#[serde(rename = "$detailblendmode", default)]
pub detail_blend_mode: BlendMode,
/// A separate VertexLitGeneric material to that will replace this one if the decal hits a model.
#[serde(rename = "$modelmaterial", default)]
pub model_material: Option<String>,
/// Disables texture filtering.
#[serde(rename = "$pointsamplemagfilter", default)]
pub point_sample_mag_filter: bool,
/// Mitigation for displacement texture stretching.
#[serde(rename = "$seamless_scale", default = "default_scale")]
pub seamless_scale: f32,
/// Scales the opacity of an entire material.
#[serde(rename = "$alpha", default = "default_scale")]
pub alpha: f32,
/// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatest", default)]
pub alpha_test: bool,
/// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatestreference", default = "default_scale")]
pub alpha_test_reference: f32,
/// Vector-like edge filtering.
#[serde(rename = "$distancealpha", default)]
pub distance_alpha: bool,
/// Disables backface culling.
#[serde(rename = "$nocull", default)]
pub no_cull: bool,
/// Specifies that the material should be partially see-through.
#[serde(rename = "$translucent", default)]
pub translucent: bool,
/// Specifies a texture that will provide three-dimensional lighting information for a material.
#[serde(rename = "$bumpmap")]
pub bump_map: Option<String>,
/// Per-texel color modification via a warp texture.
#[serde(rename = "$lightwarptexture")]
pub light_wrap_texture: Option<String>,
/// Determines whether the surface is self-illuminated independent of environment lighting.
#[serde(rename = "$selfillum", default)]
pub self_illum: bool,
/// Flags the $bumpmap as being a self-shadowing bumpmap.
#[serde(rename = "$ssbump", default)]
pub ss_bump: bool,
/// Specular reflections.
#[serde(rename = "$envmap")]
pub env_map: Option<String>,
/// Diffuse reflections.
#[serde(rename = "$phong", default)]
pub phong: bool,
/// Prevents fog from overdrawing a material.
#[serde(rename = "$nofog", default)]
pub no_fog: bool,
/// Ignore z filtering
#[serde(rename = "$ignorez", default)]
pub ignore_z: bool,
}

View file

@ -58,6 +58,9 @@ pub struct WorldVertexTransitionMaterial {
/// Specifies a mask to use to determine binary opacity. /// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatest", default)] #[serde(rename = "$alphatest", default)]
pub alpha_test: bool, pub alpha_test: bool,
/// Specifies a mask to use to determine binary opacity.
#[serde(rename = "$alphatestreference", default = "default_scale")]
pub alpha_test_reference: f32,
/// Vector-like edge filtering. /// Vector-like edge filtering.
#[serde(rename = "$distancealpha", default)] #[serde(rename = "$distancealpha", default)]
pub distance_alpha: bool, pub distance_alpha: bool,