From 4e1b3619f4bf149b272baa0b5ece4edebe1a0b9f Mon Sep 17 00:00:00 2001 From: Wito Wiala Date: Sat, 6 Jun 2026 18:34:29 +0100 Subject: [PATCH] Major overhaul to Texture handling --- shared/src/core/image.rs | 48 ++++++++- shared/src/core/interaction.rs | 4 +- shared/src/core/material.rs | 6 +- shared/src/core/pbrt.rs | 2 +- shared/src/core/primitive.rs | 4 +- shared/src/core/texture.rs | 104 +++++++++---------- shared/src/lights/diffuse.rs | 4 +- shared/src/materials/coated.rs | 78 +++++++-------- shared/src/materials/complex.rs | 58 +++++------ shared/src/materials/conductor.rs | 28 +++--- shared/src/materials/dielectric.rs | 14 +-- shared/src/materials/diffuse.rs | 16 +-- shared/src/materials/mix.rs | 6 +- shared/src/textures/checkerboard.rs | 6 +- shared/src/textures/dots.rs | 10 +- shared/src/textures/image.rs | 150 +++++++++++++++------------- shared/src/textures/mix.rs | 38 +++---- shared/src/textures/scaled.rs | 18 ++-- src/core/material.rs | 4 +- src/core/primitive.rs | 4 +- src/core/texture.rs | 16 +-- src/lights/diffuse.rs | 8 +- src/utils/upload.rs | 136 ++++++++++++------------- 23 files changed, 407 insertions(+), 355 deletions(-) diff --git a/shared/src/core/image.rs b/shared/src/core/image.rs index efaacc2..6f072fc 100644 --- a/shared/src/core/image.rs +++ b/shared/src/core/image.rs @@ -1,8 +1,8 @@ use crate::core::color::{ColorEncoding, ColorEncodingTrait, LINEAR}; use crate::core::geometry::{Bounds2f, Point2f, Point2fi, Point2i}; use crate::utils::math::{f16_to_f32_software, lerp, square}; -use crate::{gvec_with_capacity, Float, GVec}; -use anyhow::{Result, bail}; +use crate::{gvec_with_capacity, Float, GVec, Ptr}; +use anyhow::{bail, Result}; use core::hash; use core::ops::{Deref, DerefMut}; use num_traits::Float as NumFloat; @@ -23,7 +23,7 @@ impl WrapMode { "black" => Ok(WrapMode::Black), "repeat" => Ok(WrapMode::Repeat), "octahedralsphere" => Ok(WrapMode::OctahedralSphere), - _ => bail!("{:?}: wrap mode unknown", name) + _ => bail!("{:?}: wrap mode unknown", name), } } } @@ -236,6 +236,17 @@ pub struct Image { pub pixels: Pixels, } +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ImageView { + pub pixels: *const u8, + pub byte_len: usize, + pub resolution: Point2i, + pub n_channels: i32, + pub format: PixelFormat, + pub encoding: ColorEncoding, +} + impl Image { pub fn new( format: PixelFormat, @@ -472,3 +483,34 @@ impl Image { false } } + +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum FilterFunction { + Point, + Bilinear, + Trilinear, + Ewa, +} + +impl FilterFunction { + pub fn parse(name: &str) -> Result { + match name { + "ewa" | "EWA" => Ok(FilterFunction::Ewa), + "trilinear" => Ok(FilterFunction::Trilinear), + "bilinear" => Ok(FilterFunction::Bilinear), + "point" => Ok(FilterFunction::Point), + _ => bail!("Filter function unknown"), + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct ImagePyramid { + pub levels: *const Ptr, + pub level_count: u32, + pub wrap_mode: WrapMode, + pub filter: FilterFunction, + pub max_aniso: f32, +} diff --git a/shared/src/core/interaction.rs b/shared/src/core/interaction.rs index df5f67f..031ea6b 100644 --- a/shared/src/core/interaction.rs +++ b/shared/src/core/interaction.rs @@ -15,7 +15,7 @@ use crate::core::material::{ use crate::core::medium::{Medium, MediumInterface, PhaseFunction}; use crate::core::sampler::{Sampler, SamplerTrait}; use crate::core::shape::Shape; -use crate::core::texture::{GPUFloatTexture, UniversalTextureEvaluator}; +use crate::core::texture::{FloatTexture, UniversalTextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::Ptr; use crate::utils::math::{clamp, difference_of_products, square}; @@ -347,7 +347,7 @@ impl SurfaceInteraction { pub fn compute_bump_geom( &mut self, tex_eval: &UniversalTextureEvaluator, - displacement: Ptr, + displacement: Ptr, normal_image: Ptr, ) { let ctx = NormalBumpEvalContext::from(&*self); diff --git a/shared/src/core/material.rs b/shared/src/core/material.rs index 55b7e86..680d0fe 100644 --- a/shared/src/core/material.rs +++ b/shared/src/core/material.rs @@ -14,7 +14,7 @@ use crate::core::interaction::{Interaction, InteractionTrait, ShadingGeom, Surfa use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; use crate::core::texture::{ - GPUFloatTexture, GPUSpectrumTexture, TextureEvalContext, TextureEvaluator, + FloatTexture, SpectrumTexture, TextureEvalContext, TextureEvaluator, }; use crate::materials::*; use crate::spectra::{SampledSpectrum, SampledWavelengths}; @@ -122,7 +122,7 @@ pub fn normal_map(normal_map: &Image, ctx: &NormalBumpEvalContext) -> (Vector3f, pub fn bump_map( tex_eval: &T, - displacement: &GPUFloatTexture, + displacement: &FloatTexture, ctx: &NormalBumpEvalContext, ) -> (Vector3f, Vector3f) { debug_assert!(tex_eval.can_evaluate(&[Ptr::from(displacement)], &[])); @@ -174,7 +174,7 @@ pub trait MaterialTrait { fn can_evaluate_textures(&self, tex_eval: &dyn TextureEvaluator) -> bool; fn get_normal_map(&self) -> Option<&Image>; - fn get_displacement(&self) -> Ptr; + fn get_displacement(&self) -> Ptr; fn has_subsurface_scattering(&self) -> bool; } diff --git a/shared/src/core/pbrt.rs b/shared/src/core/pbrt.rs index fc3b813..c8bdf4c 100644 --- a/shared/src/core/pbrt.rs +++ b/shared/src/core/pbrt.rs @@ -4,7 +4,7 @@ use num_traits::{Float as NumFloat, Num, NumCast, PrimInt}; use crate::core::light::LightTrait; use crate::core::shape::Shape; -use crate::core::texture::GPUFloatTexture; +use crate::core::texture::FloatTexture; use crate::lights::*; use crate::spectra::{DenselySampledSpectrum, RGBColorSpace}; use crate::utils::Ptr; diff --git a/shared/src/core/primitive.rs b/shared/src/core/primitive.rs index 3213313..a23516a 100644 --- a/shared/src/core/primitive.rs +++ b/shared/src/core/primitive.rs @@ -6,7 +6,7 @@ use crate::core::material::Material; use crate::core::medium::{Medium, MediumInterface}; use crate::core::pbrt::Float; use crate::core::shape::{Shape, ShapeIntersection, ShapeTrait}; -use crate::core::texture::{GPUFloatTexture, TextureEvalContext}; +use crate::core::texture::{FloatTexture, TextureEvalContext}; use crate::utils::hash::hash_float; use crate::utils::transform::{AnimatedTransform, Transform}; use crate::utils::Ptr; @@ -29,7 +29,7 @@ pub struct GeometricPrimitive { pub material: Ptr, pub area_light: Ptr, pub medium_interface: MediumInterface, - pub alpha: Ptr, + pub alpha: Ptr, } unsafe impl Send for GeometricPrimitive {} diff --git a/shared/src/core/texture.rs b/shared/src/core/texture.rs index 8b5574d..e40befa 100644 --- a/shared/src/core/texture.rs +++ b/shared/src/core/texture.rs @@ -341,34 +341,34 @@ impl From<&Interaction> for TextureEvalContext { #[repr(C)] #[derive(Clone, Copy, Debug)] -pub enum GPUFloatTexture { +pub enum FloatTexture { Constant(FloatConstantTexture), - DirectionMix(GPUFloatDirectionMixTexture), - Scaled(GPUFloatScaledTexture), + DirectionMix(FloatDirectionMixTexture), + Scaled(FloatScaledTexture), Bilerp(FloatBilerpTexture), Checkerboard(FloatCheckerboardTexture), Dots(FloatDotsTexture), FBm(FBmTexture), Windy(WindyTexture), Wrinkled(WrinkledTexture), - Image(GPUFloatImageTexture), - Mix(GPUFloatMixTexture), + Image(FloatImageTexture), + Mix(FloatMixTexture), } -impl GPUFloatTexture { +impl FloatTexture { pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float { match self { - GPUFloatTexture::Constant(t) => t.evaluate(ctx), - GPUFloatTexture::DirectionMix(t) => t.evaluate(ctx), - GPUFloatTexture::Scaled(t) => t.evaluate(ctx), - GPUFloatTexture::Bilerp(t) => t.evaluate(ctx), - GPUFloatTexture::Checkerboard(t) => t.evaluate(ctx), - GPUFloatTexture::Dots(t) => t.evaluate(ctx), - GPUFloatTexture::FBm(t) => t.evaluate(ctx), - GPUFloatTexture::Windy(t) => t.evaluate(ctx), - GPUFloatTexture::Wrinkled(t) => t.evaluate(ctx), - GPUFloatTexture::Image(t) => t.evaluate(ctx), - GPUFloatTexture::Mix(t) => t.evaluate(ctx), + FloatTexture::Constant(t) => t.evaluate(ctx), + FloatTexture::DirectionMix(t) => t.evaluate(ctx), + FloatTexture::Scaled(t) => t.evaluate(ctx), + FloatTexture::Bilerp(t) => t.evaluate(ctx), + FloatTexture::Checkerboard(t) => t.evaluate(ctx), + FloatTexture::Dots(t) => t.evaluate(ctx), + FloatTexture::FBm(t) => t.evaluate(ctx), + FloatTexture::Windy(t) => t.evaluate(ctx), + FloatTexture::Wrinkled(t) => t.evaluate(ctx), + FloatTexture::Image(t) => t.evaluate(ctx), + FloatTexture::Mix(t) => t.evaluate(ctx), } } } @@ -384,51 +384,51 @@ pub enum SpectrumType { #[repr(C)] #[enum_dispatch] #[derive(Clone, Copy, Debug)] -pub enum GPUSpectrumTexture { +pub enum SpectrumTexture { Constant(SpectrumConstantTexture), Bilerp(SpectrumBilerpTexture), Checkerboard(SpectrumCheckerboardTexture), Marble(MarbleTexture), - DirectionMix(GPUSpectrumDirectionMixTexture), + DirectionMix(SpectrumDirectionMixTexture), Dots(SpectrumDotsTexture), - Scaled(GPUSpectrumScaledTexture), - Image(GPUSpectrumImageTexture), - Mix(GPUSpectrumMixTexture), + Scaled(SpectrumScaledTexture), + Image(SpectrumImageTexture), + Mix(SpectrumMixTexture), } -impl GPUSpectrumTexture { +impl SpectrumTexture { pub fn evaluate( &self, ctx: &TextureEvalContext, lambda: &SampledWavelengths, ) -> SampledSpectrum { match self { - GPUSpectrumTexture::Constant(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Bilerp(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Checkerboard(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Marble(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::DirectionMix(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Dots(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Scaled(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Image(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Mix(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Constant(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Bilerp(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Checkerboard(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Marble(t) => t.evaluate(ctx, lambda), + SpectrumTexture::DirectionMix(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Dots(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Scaled(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Image(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Mix(t) => t.evaluate(ctx, lambda), } } } pub trait TextureEvaluator: Send + Sync { - fn evaluate_float(&self, tex: &GPUFloatTexture, ctx: &TextureEvalContext) -> Float; + fn evaluate_float(&self, tex: &FloatTexture, ctx: &TextureEvalContext) -> Float; fn evaluate_spectrum( &self, - tex: &GPUSpectrumTexture, + tex: &SpectrumTexture, ctx: &TextureEvalContext, lambda: &SampledWavelengths, ) -> SampledSpectrum; fn can_evaluate( &self, - _ftex: &[Ptr], - _stex: &[Ptr], + _ftex: &[Ptr], + _stex: &[Ptr], ) -> bool; } @@ -437,13 +437,13 @@ pub trait TextureEvaluator: Send + Sync { pub struct UniversalTextureEvaluator; impl TextureEvaluator for UniversalTextureEvaluator { - fn evaluate_float(&self, tex: &GPUFloatTexture, ctx: &TextureEvalContext) -> Float { + fn evaluate_float(&self, tex: &FloatTexture, ctx: &TextureEvalContext) -> Float { tex.evaluate(ctx) } fn evaluate_spectrum( &self, - tex: &GPUSpectrumTexture, + tex: &SpectrumTexture, ctx: &TextureEvalContext, lambda: &SampledWavelengths, ) -> SampledSpectrum { @@ -452,8 +452,8 @@ impl TextureEvaluator for UniversalTextureEvaluator { fn can_evaluate( &self, - _float_textures: &[Ptr], - _spectrum_textures: &[Ptr], + _float_textures: &[Ptr], + _spectrum_textures: &[Ptr], ) -> bool { true } @@ -464,39 +464,39 @@ impl TextureEvaluator for UniversalTextureEvaluator { pub struct BasicTextureEvaluator; impl TextureEvaluator for BasicTextureEvaluator { - fn evaluate_float(&self, tex: &GPUFloatTexture, ctx: &TextureEvalContext) -> Float { + fn evaluate_float(&self, tex: &FloatTexture, ctx: &TextureEvalContext) -> Float { match tex { - GPUFloatTexture::Constant(t) => t.evaluate(ctx), - GPUFloatTexture::Image(t) => t.evaluate(ctx), + FloatTexture::Constant(t) => t.evaluate(ctx), + FloatTexture::Image(t) => t.evaluate(ctx), _ => 0.0, } } fn evaluate_spectrum( &self, - tex: &GPUSpectrumTexture, + tex: &SpectrumTexture, ctx: &TextureEvalContext, lambda: &SampledWavelengths, ) -> SampledSpectrum { match tex { - GPUSpectrumTexture::Constant(t) => t.evaluate(ctx, lambda), - GPUSpectrumTexture::Image(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Constant(t) => t.evaluate(ctx, lambda), + SpectrumTexture::Image(t) => t.evaluate(ctx, lambda), _ => SampledSpectrum::new(0.0), } } fn can_evaluate( &self, - ftex: &[Ptr], - stex: &[Ptr], + ftex: &[Ptr], + stex: &[Ptr], ) -> bool { for t in ftex { if t.is_null() { continue; } match t.get().unwrap() { - GPUFloatTexture::Constant(_) - | GPUFloatTexture::Image(_) => {} + FloatTexture::Constant(_) + | FloatTexture::Image(_) => {} _ => return false, } } @@ -505,8 +505,8 @@ impl TextureEvaluator for BasicTextureEvaluator { continue; } match t.get().unwrap() { - GPUSpectrumTexture::Constant(_) - | GPUSpectrumTexture::Image(_) => {} + SpectrumTexture::Constant(_) + | SpectrumTexture::Image(_) => {} _ => return false, } } diff --git a/shared/src/lights/diffuse.rs b/shared/src/lights/diffuse.rs index b093188..f704c06 100644 --- a/shared/src/lights/diffuse.rs +++ b/shared/src/lights/diffuse.rs @@ -11,7 +11,7 @@ use crate::core::medium::MediumInterface; use crate::core::shape::{Shape, ShapeSampleContext, ShapeTrait}; use crate::core::spectrum::{Spectrum, SpectrumTrait}; use crate::core::texture::{ - GPUFloatTexture, TextureEvalContext, TextureEvaluator, UniversalTextureEvaluator, + FloatTexture, TextureEvalContext, TextureEvaluator, UniversalTextureEvaluator, }; use crate::spectra::*; use crate::utils::hash::hash_float; @@ -24,7 +24,7 @@ use num_traits::Float as NumFloat; pub struct DiffuseAreaLight { pub base: LightBase, pub shape: Ptr, - pub alpha: Ptr, + pub alpha: Ptr, pub colorspace: Ptr, pub lemit: Ptr, pub image: Ptr, diff --git a/shared/src/materials/coated.rs b/shared/src/materials/coated.rs index 36197d8..d9170ca 100644 --- a/shared/src/materials/coated.rs +++ b/shared/src/materials/coated.rs @@ -8,7 +8,7 @@ use crate::core::image::Image; use crate::core::material::{Material, MaterialEvalContext, MaterialTrait}; use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvaluator}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::Ptr; use crate::utils::math::clamp; @@ -17,13 +17,13 @@ use crate::utils::math::clamp; #[derive(Clone, Copy, Debug)] pub struct CoatedDiffuseMaterial { pub normal_map: Ptr, - pub displacement: Ptr, - pub reflectance: Ptr, - pub albedo: Ptr, - pub u_roughness: Ptr, - pub v_roughness: Ptr, - pub thickness: Ptr, - pub g: Ptr, + pub displacement: Ptr, + pub reflectance: Ptr, + pub albedo: Ptr, + pub u_roughness: Ptr, + pub v_roughness: Ptr, + pub thickness: Ptr, + pub g: Ptr, pub eta: Ptr, pub max_depth: u32, pub n_samples: u32, @@ -34,13 +34,13 @@ pub struct CoatedDiffuseMaterial { impl CoatedDiffuseMaterial { #[allow(clippy::too_many_arguments)] pub fn new( - reflectance: Ptr, - u_roughness: Ptr, - v_roughness: Ptr, - thickness: Ptr, - albedo: Ptr, - g: Ptr, - displacement: Ptr, + reflectance: Ptr, + u_roughness: Ptr, + v_roughness: Ptr, + thickness: Ptr, + albedo: Ptr, + g: Ptr, + displacement: Ptr, eta: Ptr, normal_map: Ptr, remap_roughness: bool, @@ -141,7 +141,7 @@ impl MaterialTrait for CoatedDiffuseMaterial { Some(&*self.normal_map) } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } @@ -153,18 +153,18 @@ impl MaterialTrait for CoatedDiffuseMaterial { #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct CoatedConductorMaterial { - displacement: Ptr, - interface_uroughness: Ptr, - interface_vroughness: Ptr, - thickness: Ptr, + displacement: Ptr, + interface_uroughness: Ptr, + interface_vroughness: Ptr, + thickness: Ptr, interface_eta: Ptr, - g: Ptr, - albedo: Ptr, - conductor_uroughness: Ptr, - conductor_vroughness: Ptr, - conductor_eta: Ptr, - k: Ptr, - reflectance: Ptr, + g: Ptr, + albedo: Ptr, + conductor_uroughness: Ptr, + conductor_vroughness: Ptr, + conductor_eta: Ptr, + k: Ptr, + reflectance: Ptr, normal_map: Ptr, max_depth: u32, n_samples: u32, @@ -175,17 +175,17 @@ pub struct CoatedConductorMaterial { impl CoatedConductorMaterial { #[allow(clippy::too_many_arguments)] pub fn new( - displacement: Ptr, - interface_uroughness: Ptr, - interface_vroughness: Ptr, - thickness: Ptr, - g: Ptr, - albedo: Ptr, - conductor_uroughness: Ptr, - conductor_vroughness: Ptr, - conductor_eta: Ptr, - k: Ptr, - reflectance: Ptr, + displacement: Ptr, + interface_uroughness: Ptr, + interface_vroughness: Ptr, + thickness: Ptr, + g: Ptr, + albedo: Ptr, + conductor_uroughness: Ptr, + conductor_vroughness: Ptr, + conductor_eta: Ptr, + k: Ptr, + reflectance: Ptr, normal_map: Ptr, interface_eta: Ptr, max_depth: u32, @@ -337,7 +337,7 @@ impl MaterialTrait for CoatedConductorMaterial { self.normal_map.get() } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } diff --git a/shared/src/materials/complex.rs b/shared/src/materials/complex.rs index 1087d2f..94ca52a 100644 --- a/shared/src/materials/complex.rs +++ b/shared/src/materials/complex.rs @@ -10,37 +10,37 @@ use crate::core::image::Image; use crate::core::material::{Material, MaterialEvalContext, MaterialTrait}; use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvaluator}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; -use crate::textures::GPUSpectrumMixTexture; +use crate::textures::SpectrumMixTexture; use crate::utils::Ptr; use crate::utils::math::clamp; #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct HairMaterial { - pub sigma_a: Ptr, - pub color: Ptr, - pub eumelanin: Ptr, - pub pheomelanin: Ptr, - pub eta: Ptr, - pub beta_m: Ptr, - pub beta_n: Ptr, - pub alpha: Ptr, + pub sigma_a: Ptr, + pub color: Ptr, + pub eumelanin: Ptr, + pub pheomelanin: Ptr, + pub eta: Ptr, + pub beta_m: Ptr, + pub beta_n: Ptr, + pub alpha: Ptr, } impl HairMaterial { #[cfg(not(target_os = "cuda"))] #[allow(clippy::too_many_arguments)] pub fn new( - sigma_a: Ptr, - color: Ptr, - eumelanin: Ptr, - pheomelanin: Ptr, - eta: Ptr, - beta_m: Ptr, - beta_n: Ptr, - alpha: Ptr, + sigma_a: Ptr, + color: Ptr, + eumelanin: Ptr, + pheomelanin: Ptr, + eta: Ptr, + beta_m: Ptr, + beta_n: Ptr, + alpha: Ptr, ) -> Self { Self { sigma_a, @@ -81,7 +81,7 @@ impl MaterialTrait for HairMaterial { todo!() } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { Ptr::null() } @@ -93,7 +93,7 @@ impl MaterialTrait for HairMaterial { #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct MeasuredMaterial { - pub displacement: Ptr, + pub displacement: Ptr, pub normal_map: Ptr, pub brdf: Ptr, } @@ -126,7 +126,7 @@ impl MaterialTrait for MeasuredMaterial { Some(&*self.normal_map) } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } @@ -139,15 +139,15 @@ impl MaterialTrait for MeasuredMaterial { #[derive(Clone, Copy, Debug)] pub struct SubsurfaceMaterial { pub normal_map: Ptr, - pub displacement: Ptr, - pub sigma_a: Ptr, - pub sigma_s: Ptr, - pub reflectance: Ptr, - pub mfp: Ptr, + pub displacement: Ptr, + pub sigma_a: Ptr, + pub sigma_s: Ptr, + pub reflectance: Ptr, + pub mfp: Ptr, pub eta: Float, pub scale: Float, - pub u_roughness: Ptr, - pub v_roughness: Ptr, + pub u_roughness: Ptr, + pub v_roughness: Ptr, pub remap_roughness: bool, pub table: Ptr, } @@ -178,7 +178,7 @@ impl MaterialTrait for SubsurfaceMaterial { todo!() } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { todo!() } diff --git a/shared/src/materials/conductor.rs b/shared/src/materials/conductor.rs index a621c87..8d94d6c 100644 --- a/shared/src/materials/conductor.rs +++ b/shared/src/materials/conductor.rs @@ -8,7 +8,7 @@ use crate::core::image::Image; use crate::core::material::{Material, MaterialEvalContext, MaterialTrait}; use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvaluator}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::math::clamp; use crate::utils::Ptr; @@ -17,24 +17,24 @@ use crate::utils::Ptr; #[derive(Clone, Copy, Debug)] pub struct ConductorMaterial { pub normal_map: Ptr, - pub reflectance: Ptr, - pub eta: Ptr, - pub k: Ptr, - pub u_roughness: Ptr, - pub v_roughness: Ptr, - pub displacement: Ptr, + pub reflectance: Ptr, + pub eta: Ptr, + pub k: Ptr, + pub u_roughness: Ptr, + pub v_roughness: Ptr, + pub displacement: Ptr, pub remap_roughness: bool, } impl ConductorMaterial { pub fn new( normal_map: Ptr, - reflectance: Ptr, - eta: Ptr, - k: Ptr, - u_roughness: Ptr, - v_roughness: Ptr, - displacement: Ptr, + reflectance: Ptr, + eta: Ptr, + k: Ptr, + u_roughness: Ptr, + v_roughness: Ptr, + displacement: Ptr, remap_roughness: bool, ) -> Self { Self { @@ -105,7 +105,7 @@ impl MaterialTrait for ConductorMaterial { self.normal_map.get() } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } diff --git a/shared/src/materials/dielectric.rs b/shared/src/materials/dielectric.rs index 316a587..790f85d 100644 --- a/shared/src/materials/dielectric.rs +++ b/shared/src/materials/dielectric.rs @@ -8,7 +8,7 @@ use crate::core::image::Image; use crate::core::material::{Material, MaterialEvalContext, MaterialTrait}; use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvaluator}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::math::clamp; use crate::Ptr; @@ -17,9 +17,9 @@ use crate::Ptr; #[derive(Clone, Copy, Debug)] pub struct DielectricMaterial { pub normal_map: Ptr, - pub displacement: Ptr, - pub u_roughness: Ptr, - pub v_roughness: Ptr, + pub displacement: Ptr, + pub u_roughness: Ptr, + pub v_roughness: Ptr, pub eta: Ptr, pub remap_roughness: bool, } @@ -71,7 +71,7 @@ impl MaterialTrait for DielectricMaterial { Some(&*self.normal_map) } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } @@ -83,7 +83,7 @@ impl MaterialTrait for DielectricMaterial { #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct ThinDielectricMaterial { - pub displacement: Ptr, + pub displacement: Ptr, pub normal_map: Ptr, pub eta: Ptr, } @@ -114,7 +114,7 @@ impl MaterialTrait for ThinDielectricMaterial { Some(&*self.normal_map) } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } diff --git a/shared/src/materials/diffuse.rs b/shared/src/materials/diffuse.rs index 94a24bd..c471aaa 100644 --- a/shared/src/materials/diffuse.rs +++ b/shared/src/materials/diffuse.rs @@ -9,7 +9,7 @@ use crate::core::image::Image; use crate::core::material::{Material, MaterialEvalContext, MaterialTrait}; use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvaluator}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::Ptr; use crate::utils::math::clamp; @@ -18,8 +18,8 @@ use crate::utils::math::clamp; #[derive(Clone, Copy, Debug)] pub struct DiffuseMaterial { pub normal_map: Ptr, - pub displacement: Ptr, - pub reflectance: Ptr, + pub displacement: Ptr, + pub reflectance: Ptr, } impl MaterialTrait for DiffuseMaterial { @@ -51,7 +51,7 @@ impl MaterialTrait for DiffuseMaterial { self.normal_map.get() } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } @@ -64,9 +64,9 @@ impl MaterialTrait for DiffuseMaterial { #[derive(Clone, Copy, Debug)] pub struct DiffuseTransmissionMaterial { pub image: Ptr, - pub displacement: Ptr, - pub reflectance: Ptr, - pub transmittance: Ptr, + pub displacement: Ptr, + pub reflectance: Ptr, + pub transmittance: Ptr, pub scale: Float, } @@ -96,7 +96,7 @@ impl MaterialTrait for DiffuseTransmissionMaterial { self.image.get() } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { self.displacement } diff --git a/shared/src/materials/mix.rs b/shared/src/materials/mix.rs index 5e1da28..c24edad 100644 --- a/shared/src/materials/mix.rs +++ b/shared/src/materials/mix.rs @@ -8,7 +8,7 @@ use crate::core::image::Image; use crate::core::material::{Material, MaterialEvalContext, MaterialTrait}; use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvaluator}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::Ptr; use crate::utils::hash::hash_float; @@ -17,7 +17,7 @@ use crate::utils::math::clamp; #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct MixMaterial { - pub amount: Ptr, + pub amount: Ptr, pub materials: [Ptr; 2], } @@ -73,7 +73,7 @@ impl MaterialTrait for MixMaterial { None } - fn get_displacement(&self) -> Ptr { + fn get_displacement(&self) -> Ptr { panic!( "MixMaterial::get_displacement() shouldn't be called. \ Displacement is not supported on Mix materials directly." diff --git a/shared/src/textures/checkerboard.rs b/shared/src/textures/checkerboard.rs index c175e4b..ea4ee3d 100644 --- a/shared/src/textures/checkerboard.rs +++ b/shared/src/textures/checkerboard.rs @@ -1,6 +1,6 @@ use crate::Float; use crate::core::texture::{ - GPUFloatTexture, GPUSpectrumTexture, TextureEvalContext, TextureMapping2D, TextureMapping3D, + FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D, TextureMapping3D, TextureMapping3DTrait, }; use crate::spectra::{SampledSpectrum, SampledWavelengths}; @@ -46,7 +46,7 @@ fn checkerboard( pub struct FloatCheckerboardTexture { pub map2d: Ptr, pub map3d: Ptr, - pub tex: [Ptr; 2], + pub tex: [Ptr; 2], } impl FloatCheckerboardTexture { @@ -77,7 +77,7 @@ impl FloatCheckerboardTexture { pub struct SpectrumCheckerboardTexture { pub map2d: Ptr, pub map3d: Ptr, - pub tex: [Ptr; 2], + pub tex: [Ptr; 2], } impl SpectrumCheckerboardTexture { diff --git a/shared/src/textures/dots.rs b/shared/src/textures/dots.rs index f2b2ccc..84191da 100644 --- a/shared/src/textures/dots.rs +++ b/shared/src/textures/dots.rs @@ -1,7 +1,7 @@ use crate::Float; use crate::core::geometry::{Point2f, VectorLike}; use crate::core::texture::{ - GPUFloatTexture, GPUSpectrumTexture, TextureEvalContext, TextureMapping2D, + FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D, }; use crate::spectra::sampled::{SampledSpectrum, SampledWavelengths}; use crate::utils::Ptr; @@ -29,8 +29,8 @@ fn inside_polka_dot(st: Point2f) -> bool { #[derive(Debug, Clone, Copy)] pub struct FloatDotsTexture { pub mapping: TextureMapping2D, - pub outside_dot: Ptr, - pub inside_dot: Ptr, + pub outside_dot: Ptr, + pub inside_dot: Ptr, } impl FloatDotsTexture { @@ -54,8 +54,8 @@ impl FloatDotsTexture { #[derive(Clone, Copy, Debug)] pub struct SpectrumDotsTexture { pub mapping: TextureMapping2D, - pub outside_dot: Ptr, - pub inside_dot: Ptr, + pub outside_dot: Ptr, + pub inside_dot: Ptr, } impl SpectrumDotsTexture { diff --git a/shared/src/textures/image.rs b/shared/src/textures/image.rs index 32e44e2..2eb2038 100644 --- a/shared/src/textures/image.rs +++ b/shared/src/textures/image.rs @@ -1,5 +1,5 @@ use crate::core::color::{RGB, XYZ}; -use crate::core::image::Image; +use crate::core::image::{Image, WrapMode, WrapMode2D}; use crate::core::spectrum::SpectrumTrait; use crate::core::texture::{SpectrumType, TextureEvalContext, TextureMapping2D}; use crate::spectra::{ @@ -13,104 +13,118 @@ use crate::Float; * Leaving it here isolated, for careful handling */ #[repr(C)] #[derive(Clone, Debug, Copy)] -pub struct GPUSpectrumImageTexture { - pub mapping: TextureMapping2D, +pub struct SpectrumImageTexture { + pub wrap_mode: WrapMode, pub tex_obj: u64, - pub image: Ptr, pub scale: Float, - pub invert: bool, - pub is_single_channel: bool, - pub color_space: Ptr, pub spectrum_type: SpectrumType, + pub image: Ptr, + pub color_space: Ptr, + pub mapping: TextureMapping2D, + pub is_single_channel: bool, + pub invert: bool, } -impl GPUSpectrumImageTexture { - #[allow(unused)] +impl SpectrumImageTexture { pub fn evaluate( &self, ctx: &TextureEvalContext, lambda: &SampledWavelengths, ) -> SampledSpectrum { - #[cfg(not(feature = "cuda"))] - { - return SampledSpectrum::zero(); + #[cfg(feature = "cuda")] + if self.tex_obj != 0 { + // FUTURE: hardware sampling path. + // let c = self.mapping.map(ctx); + // let rgb = tex2d_grad(self.tex_obj, c.st, [c.dsdx,c.dtdx], [c.dsdy,c.dtdy]); + // return spectrum_from_rgb(rgb * self.scale, self.invert, self.spectrum_type, ...); + // Until then, fall through to software path below. } - #[cfg(feature = "cuda")] - { - use cuda_std::intrinsics; - let c = self.mapping.map(ctx); - let u = c.st.x(); - let v = 1.0 - c.st.y(); + let Some(image) = self.image.get() else { + return SampledSpectrum::zero(); + }; + let mut c = self.mapping.map(ctx); + c.st[1] = 1.0 - c.st[1]; // flip V to match pbrt convention - let d_p_dx = [c.dsdx, c.dtdx]; - let d_p_dy = [c.dsdy, c.dtdy]; - - let tex_color = if self.is_single_channel { - let val = 0.; - // let val: Float = - // unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; - RGB::new(val, val, val) - } else { - let val = [0., 0., 0., 0.]; - // let val: [Float; 4] = - // unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; - RGB::new(val[0], val[1], val[2]) - }; - - let mut rgb = tex_color * self.scale; - if self.invert { - rgb = (RGB::new(1.0, 1.0, 1.0) - rgb).clamp_zero(); - } - - match self.spectrum_type { - SpectrumType::Unbounded => { - RGBUnboundedSpectrum::new(&self.color_space, rgb).sample(lambda) - } - SpectrumType::Albedo => { - RGBAlbedoSpectrum::new(&self.color_space, rgb.clamp(0.0, 1.0)).sample(lambda) - } - _ => RGBIlluminantSpectrum::new(&self.color_space, rgb).sample(lambda), - } + let wrap = WrapMode2D { + uv: [self.wrap_mode; 2], + }; + let rgb = if image.n_channels == 1 { + let v = image.bilerp_channel_with_wrap(c.st, 0, wrap); + RGB::new(v, v, v) + } else { + RGB::new( + image.bilerp_channel_with_wrap(c.st, 0, wrap), + image.bilerp_channel_with_wrap(c.st, 1, wrap), + image.bilerp_channel_with_wrap(c.st, 2, wrap), + ) + }; + let mut rgb = rgb * self.scale; + if self.invert { + rgb = (RGB::new(1.0, 1.0, 1.0) - rgb).clamp_zero(); + } + let cs = self + .color_space + .get() + .expect("color_space must not be null"); + match self.spectrum_type { + SpectrumType::Unbounded => RGBUnboundedSpectrum::new(cs, rgb).sample(lambda), + SpectrumType::Albedo => RGBAlbedoSpectrum::new(cs, rgb.clamp(0.0, 1.0)).sample(lambda), + _ => RGBIlluminantSpectrum::new(cs, rgb).sample(lambda), } } } +#[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct GPUFloatImageTexture { +pub struct FloatImageTexture { + pub image: Ptr, pub mapping: TextureMapping2D, + pub wrap_mode: WrapMode, pub tex_obj: u64, pub scale: Float, pub invert: bool, } -impl GPUFloatImageTexture { +impl FloatImageTexture { #[allow(unused_variables)] pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float { #[cfg(not(feature = "cuda"))] { - return 0.; + let wrap = WrapMode2D { + uv: [self.wrap_mode; 2], + }; + let mut c = self.mapping.map(ctx); + c.st[1] = 1.0 - c.st[1]; + let Some(image) = self.image.get() else { return 0. }; + + let v = image.bilerp_channel_with_wrap(c.st, 0, wrap); + let v = if self.invert { (1.0 - v).max(0.0) } else { v }; + return v * self.scale; } #[cfg(feature = "cuda")] - #[allow(unused)] { - use cuda_std::intrinsics; - let c = self.mapping.map(ctx); - let u = c.st.x(); - let v = 1.0 - c.st.y(); - let d_p_dx = [c.dsdx, c.dtdx]; - let d_p_dy = [c.dsdy, c.dtdy]; - // let val: Float = unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; - let val: Float = 0.; - - let result = if self.invert { - // Invert the pixel intensity - (1.0 - val).max(0.0) - } else { - val - }; - - return result * self.scale; + if self.tex_obj != 0 { + use cuda_std::intrinsics; + let c = self.mapping.map(ctx); + let u = c.st.x(); + let v = 1.0 - c.st.y(); + let d_p_dx = [c.dsdx, c.dtdx]; + let d_p_dy = [c.dsdy, c.dtdy]; + // let val: Float = unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; + let _ = (u, v, d_p_dx, d_p_dy); + let val: Float = 0.; + let result = if self.invert { (1.0 - val).max(0.0) } else { val }; + return result * self.scale; + } + // software path (no hardware texture object) + let wrap = WrapMode2D { uv: [self.wrap_mode; 2] }; + let mut c = self.mapping.map(ctx); + c.st[1] = 1.0 - c.st[1]; + let Some(image) = self.image.get() else { return 0. }; + let v = image.bilerp_channel_with_wrap(c.st, 0, wrap); + let v = if self.invert { (1.0 - v).max(0.0) } else { v }; + return v * self.scale; } } } diff --git a/shared/src/textures/mix.rs b/shared/src/textures/mix.rs index 6a8991c..08ec68d 100644 --- a/shared/src/textures/mix.rs +++ b/shared/src/textures/mix.rs @@ -1,18 +1,18 @@ use crate::Float; use crate::core::geometry::{Vector3f, VectorLike}; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvalContext}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvalContext}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::Ptr; #[repr(C)] #[derive(Copy, Clone, Debug)] -pub struct GPUFloatMixTexture { - pub tex1: Ptr, - pub tex2: Ptr, - pub amount: Ptr, +pub struct FloatMixTexture { + pub tex1: Ptr, + pub tex2: Ptr, + pub amount: Ptr, } -impl GPUFloatMixTexture { +impl FloatMixTexture { pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float { let amt = self.amount.get().map(|t| t.evaluate(ctx)).unwrap_or(0.0); let t1 = if amt != 1.0 { @@ -33,13 +33,13 @@ impl GPUFloatMixTexture { #[repr(C)] #[derive(Copy, Clone, Debug)] -pub struct GPUFloatDirectionMixTexture { - pub tex1: Ptr, - pub tex2: Ptr, +pub struct FloatDirectionMixTexture { + pub tex1: Ptr, + pub tex2: Ptr, pub dir: Vector3f, } -impl GPUFloatDirectionMixTexture { +impl FloatDirectionMixTexture { pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float { let amt = self.dir.abs_dot(ctx.n.into()); let t1 = if amt != 1.0 { @@ -60,13 +60,13 @@ impl GPUFloatDirectionMixTexture { #[repr(C)] #[derive(Copy, Clone, Debug)] -pub struct GPUSpectrumMixTexture { - pub tex1: Ptr, - pub tex2: Ptr, - pub amount: Ptr, +pub struct SpectrumMixTexture { + pub tex1: Ptr, + pub tex2: Ptr, + pub amount: Ptr, } -impl GPUSpectrumMixTexture { +impl SpectrumMixTexture { pub fn evaluate( &self, ctx: &TextureEvalContext, @@ -97,13 +97,13 @@ impl GPUSpectrumMixTexture { #[repr(C)] #[derive(Copy, Clone, Debug)] -pub struct GPUSpectrumDirectionMixTexture { - pub tex1: Ptr, - pub tex2: Ptr, +pub struct SpectrumDirectionMixTexture { + pub tex1: Ptr, + pub tex2: Ptr, pub dir: Vector3f, } -impl GPUSpectrumDirectionMixTexture { +impl SpectrumDirectionMixTexture { pub fn evaluate( &self, ctx: &TextureEvalContext, diff --git a/shared/src/textures/scaled.rs b/shared/src/textures/scaled.rs index de2c81a..69d41a7 100644 --- a/shared/src/textures/scaled.rs +++ b/shared/src/textures/scaled.rs @@ -1,16 +1,16 @@ use crate::Float; -use crate::core::texture::{GPUFloatTexture, GPUSpectrumTexture, TextureEvalContext}; +use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvalContext}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; use crate::utils::Ptr; #[repr(C)] #[derive(Debug, Clone, Copy)] -pub struct GPUFloatScaledTexture { - pub tex: Ptr, - pub scale: Ptr, +pub struct FloatScaledTexture { + pub tex: Ptr, + pub scale: Ptr, } -impl GPUFloatScaledTexture { +impl FloatScaledTexture { pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float { let sc = self.scale.get().map(|t| t.evaluate(ctx)).unwrap(); if sc == 0. { @@ -22,12 +22,12 @@ impl GPUFloatScaledTexture { #[repr(C)] #[derive(Debug, Clone, Copy)] -pub struct GPUSpectrumScaledTexture { - pub tex: Ptr, - pub scale: Ptr, +pub struct SpectrumScaledTexture { + pub tex: Ptr, + pub scale: Ptr, } -impl GPUSpectrumScaledTexture { +impl SpectrumScaledTexture { pub fn evaluate( &self, ctx: &TextureEvalContext, diff --git a/src/core/material.rs b/src/core/material.rs index e3608e5..54b0438 100644 --- a/src/core/material.rs +++ b/src/core/material.rs @@ -88,14 +88,14 @@ impl MaterialFactory for Material { } pub fn default_diffuse_material(arena: &Arena) -> Material { - use shared::core::texture::GPUSpectrumTexture; + use shared::core::texture::SpectrumTexture; use shared::core::texture::SpectrumConstantTexture; use shared::core::spectrum::{ConstantSpectrum, Spectrum}; use shared::materials::DiffuseMaterial; use shared::utils::Ptr; let grey = Spectrum::Constant(ConstantSpectrum { c: 0.5 }); - let tex = GPUSpectrumTexture::Constant(SpectrumConstantTexture::new(grey)); + let tex = SpectrumTexture::Constant(SpectrumConstantTexture::new(grey)); let tex_ptr = arena.alloc(tex); Material::Diffuse(DiffuseMaterial { diff --git a/src/core/primitive.rs b/src/core/primitive.rs index 1d9d4b9..4faa16d 100644 --- a/src/core/primitive.rs +++ b/src/core/primitive.rs @@ -4,7 +4,7 @@ use shared::core::{ medium::MediumInterface, primitive::{GeometricPrimitive, SimplePrimitive}, shape::Shape, - texture::GPUFloatTexture, + texture::FloatTexture, }; use shared::utils::Ptr; @@ -23,7 +23,7 @@ pub trait CreateGeometricPrimitive { material: Ptr, area_light: Ptr, medium_interface: MediumInterface, - alpha: Ptr, + alpha: Ptr, ) -> GeometricPrimitive { GeometricPrimitive { shape, diff --git a/src/core/texture.rs b/src/core/texture.rs index ada66ec..12d9379 100644 --- a/src/core/texture.rs +++ b/src/core/texture.rs @@ -12,7 +12,11 @@ use shared::core::texture::{ UVMapping, }; use shared::spectra::{SampledSpectrum, SampledWavelengths}; -use shared::textures::*; +use shared::textures::{ + FBmTexture, FloatBilerpTexture, FloatCheckerboardTexture, FloatConstantTexture, + FloatDotsTexture, MarbleTexture, SpectrumBilerpTexture, SpectrumCheckerboardTexture, + SpectrumConstantTexture, SpectrumDotsTexture, WindyTexture, WrinkledTexture, +}; use shared::utils::Transform; use shared::Float; use std::collections::HashMap; @@ -45,16 +49,6 @@ pub enum FloatTexture { Bilerp(FloatBilerpTexture), } -impl FloatTexture { - fn upload_image(inner: &FloatImageTexture, _arena: &Arena) -> GPUFloatImageTexture { - GPUFloatImageTexture { - mapping: inner.base.mapping, - tex_obj: inner.base.mipmap.texture_object(), - scale: inner.base.scale, - invert: inner.base.invert, - } - } -} impl Default for FloatTexture { fn default() -> Self { diff --git a/src/lights/diffuse.rs b/src/lights/diffuse.rs index e3bee4d..0d3ed7c 100644 --- a/src/lights/diffuse.rs +++ b/src/lights/diffuse.rs @@ -1,7 +1,6 @@ use crate::core::image::{HostImage, ImageIO}; use crate::core::light::lookup_spectrum; use crate::core::spectrum::spectrum_to_photometric; -use crate::core::texture::FloatTexture; use crate::utils::resolve_filename; use crate::utils::upload::ArenaUpload; use crate::{Arena, FileLoc, ParameterDictionary}; @@ -11,7 +10,8 @@ use shared::core::light::{Light, LightBase, LightType}; use shared::core::medium::{Medium, MediumInterface}; use shared::core::shape::{Shape, ShapeTrait}; use shared::core::spectrum::Spectrum; -use shared::core::texture::{GPUFloatTexture, SpectrumType, TextureEvalContext}; +use crate::core::texture::FloatTexture as HostFloatTexture; +use shared::core::texture::{FloatTexture, SpectrumType, TextureEvalContext}; use shared::lights::DiffuseAreaLight; use shared::spectra::RGBColorSpace; use shared::utils::Transform; @@ -24,7 +24,7 @@ pub fn create( params: &ParameterDictionary, loc: &FileLoc, shape: &Shape, - alpha: &FloatTexture, + alpha: &HostFloatTexture, colorspace: Option<&RGBColorSpace>, arena: &Arena, ) -> Result { @@ -102,7 +102,7 @@ pub fn create( // Upload alpha texture to GPU and check for null texture let alpha_ptr = arena.upload(alpha); let light_type = match alpha_ptr.get().unwrap() { - GPUFloatTexture::Constant(t) if t.evaluate(&TextureEvalContext::default()) == 0.0 => { + FloatTexture::Constant(t) if t.evaluate(&TextureEvalContext::default()) == 0.0 => { LightType::DeltaPosition } _ => LightType::Area, diff --git a/src/utils/upload.rs b/src/utils/upload.rs index a40d92c..8cab6fd 100644 --- a/src/utils/upload.rs +++ b/src/utils/upload.rs @@ -1,8 +1,9 @@ -use crate::core::texture::{FloatTexture, SpectrumTexture}; use crate::core::image::HostImage; -use shared::core::image::Image; +use crate::core::texture::{FloatTexture as HostFloatTexture, SpectrumTexture as HostSpectrumTexture}; +use crate::spectra::default_colorspace; use crate::Arena; -use shared::core::texture::{GPUFloatTexture, GPUSpectrumTexture}; +use shared::core::image::Image; +use shared::core::texture::{FloatTexture, SpectrumTexture}; use shared::textures::*; use shared::Ptr; use std::sync::Arc; @@ -12,43 +13,46 @@ pub trait Upload { fn upload(self, arena: &Arena) -> Self::Target; } -fn convert_float(tex: &FloatTexture, arena: &Arena) -> GPUFloatTexture { +fn convert_float(tex: &HostFloatTexture, arena: &Arena) -> FloatTexture { match tex { - FloatTexture::Constant(t) => GPUFloatTexture::Constant(*t), - FloatTexture::Bilerp(t) => GPUFloatTexture::Bilerp(*t), - FloatTexture::Checkerboard(t) => GPUFloatTexture::Checkerboard(*t), - FloatTexture::Dots(t) => GPUFloatTexture::Dots(*t), - FloatTexture::FBm(t) => GPUFloatTexture::FBm(*t), - FloatTexture::Windy(t) => GPUFloatTexture::Windy(*t), - FloatTexture::Wrinkled(t) => GPUFloatTexture::Wrinkled(*t), + HostFloatTexture::Constant(t) => FloatTexture::Constant(*t), + HostFloatTexture::Bilerp(t) => FloatTexture::Bilerp(*t), + HostFloatTexture::Checkerboard(t) => FloatTexture::Checkerboard(*t), + HostFloatTexture::Dots(t) => FloatTexture::Dots(*t), + HostFloatTexture::FBm(t) => FloatTexture::FBm(*t), + HostFloatTexture::Windy(t) => FloatTexture::Windy(*t), + HostFloatTexture::Wrinkled(t) => FloatTexture::Wrinkled(*t), - FloatTexture::Scaled(t) => { - let tex = arena.alloc(convert_float(&t.tex, arena)); - let scale = arena.alloc(convert_float(&t.scale, arena)); - GPUFloatTexture::Scaled(GPUFloatScaledTexture { tex, scale }) + HostFloatTexture::Scaled(t) => { + let tex = arena.alloc(convert_float(t.tex.as_ref(), arena)); + let scale = arena.alloc(convert_float(t.scale.as_ref(), arena)); + FloatTexture::Scaled(FloatScaledTexture { tex, scale }) } - FloatTexture::Mix(t) => { - let tex1 = arena.alloc(convert_float(&t.tex1, arena)); - let tex2 = arena.alloc(convert_float(&t.tex2, arena)); - let amount = arena.alloc(convert_float(&t.amount, arena)); - GPUFloatTexture::Mix(GPUFloatMixTexture { tex1, tex2, amount }) + HostFloatTexture::Mix(t) => { + let tex1 = arena.alloc(convert_float(t.tex1.as_ref(), arena)); + let tex2 = arena.alloc(convert_float(t.tex2.as_ref(), arena)); + let amount = arena.alloc(convert_float(t.amount.as_ref(), arena)); + FloatTexture::Mix(FloatMixTexture { tex1, tex2, amount }) } - FloatTexture::DirectionMix(t) => { - let tex1 = arena.alloc(convert_float(&t.tex1, arena)); - let tex2 = arena.alloc(convert_float(&t.tex2, arena)); - GPUFloatTexture::DirectionMix(GPUFloatDirectionMixTexture { + HostFloatTexture::DirectionMix(t) => { + let tex1 = arena.alloc(convert_float(t.tex1.as_ref(), arena)); + let tex2 = arena.alloc(convert_float(t.tex2.as_ref(), arena)); + FloatTexture::DirectionMix(FloatDirectionMixTexture { tex1, tex2, dir: t.dir, }) } - FloatTexture::Image(t) => { + HostFloatTexture::Image(t) => { + let image = arena.alloc(t.base.mipmap.base_image().inner.clone()); let tex_obj = arena.get_texture_object(&t.base.mipmap); - GPUFloatTexture::Image(GPUFloatImageTexture { + FloatTexture::Image(FloatImageTexture { + image, mapping: t.base.mapping, + wrap_mode: t.base.mipmap.wrap_mode, tex_obj, scale: t.base.scale, invert: t.base.invert, @@ -57,94 +61,92 @@ fn convert_float(tex: &FloatTexture, arena: &Arena) -> GPUFloatTexture { } } -fn convert_spectrum(tex: &SpectrumTexture, arena: &Arena) -> GPUSpectrumTexture { +fn convert_spectrum(tex: &HostSpectrumTexture, arena: &Arena) -> SpectrumTexture { match tex { - SpectrumTexture::Constant(t) => GPUSpectrumTexture::Constant(*t), - SpectrumTexture::Bilerp(t) => GPUSpectrumTexture::Bilerp(*t), - SpectrumTexture::Checkerboard(t) => GPUSpectrumTexture::Checkerboard(*t), - SpectrumTexture::Dots(t) => GPUSpectrumTexture::Dots(*t), - SpectrumTexture::Marble(t) => GPUSpectrumTexture::Marble(*t), + HostSpectrumTexture::Constant(t) => SpectrumTexture::Constant(*t), + HostSpectrumTexture::Bilerp(t) => SpectrumTexture::Bilerp(*t), + HostSpectrumTexture::Checkerboard(t) => SpectrumTexture::Checkerboard(*t), + HostSpectrumTexture::Dots(t) => SpectrumTexture::Dots(*t), + HostSpectrumTexture::Marble(t) => SpectrumTexture::Marble(*t), - SpectrumTexture::Scaled(t) => { - let tex = arena.alloc(convert_spectrum(&t.tex, arena)); - let scale = arena.alloc(convert_float(&t.scale, arena)); - GPUSpectrumTexture::Scaled(GPUSpectrumScaledTexture { tex, scale }) + HostSpectrumTexture::Scaled(t) => { + let tex = arena.alloc(convert_spectrum(t.tex.as_ref(), arena)); + let scale = arena.alloc(convert_float(t.scale.as_ref(), arena)); + SpectrumTexture::Scaled(SpectrumScaledTexture { tex, scale }) } - SpectrumTexture::Mix(t) => { - let tex1 = arena.alloc(convert_spectrum(&t.tex1, arena)); - let tex2 = arena.alloc(convert_spectrum(&t.tex2, arena)); - let amount = arena.alloc(convert_float(&t.amount, arena)); - GPUSpectrumTexture::Mix(GPUSpectrumMixTexture { tex1, tex2, amount }) + HostSpectrumTexture::Mix(t) => { + let tex1 = arena.alloc(convert_spectrum(t.tex1.as_ref(), arena)); + let tex2 = arena.alloc(convert_spectrum(t.tex2.as_ref(), arena)); + let amount = arena.alloc(convert_float(t.amount.as_ref(), arena)); + SpectrumTexture::Mix(SpectrumMixTexture { tex1, tex2, amount }) } - SpectrumTexture::DirectionMix(t) => { - let tex1 = arena.alloc(convert_spectrum(&t.tex1, arena)); - let tex2 = arena.alloc(convert_spectrum(&t.tex2, arena)); - GPUSpectrumTexture::DirectionMix(GPUSpectrumDirectionMixTexture { + HostSpectrumTexture::DirectionMix(t) => { + let tex1 = arena.alloc(convert_spectrum(t.tex1.as_ref(), arena)); + let tex2 = arena.alloc(convert_spectrum(t.tex2.as_ref(), arena)); + SpectrumTexture::DirectionMix(SpectrumDirectionMixTexture { tex1, tex2, dir: t.dir, }) } - SpectrumTexture::Image(t) => { + HostSpectrumTexture::Image(t) => { + let image = arena.alloc(t.base.mipmap.base_image().inner.clone()); let tex_obj = arena.get_texture_object(&t.base.mipmap); - GPUSpectrumTexture::Image(GPUSpectrumImageTexture { - mapping: t.base.mapping, + SpectrumTexture::Image(SpectrumImageTexture { + image, tex_obj, + wrap_mode: t.base.mipmap.wrap_mode, + color_space: arena + .alloc(t.base.mipmap.color_space.unwrap_or_else(default_colorspace)), + mapping: t.base.mapping, scale: t.base.scale, invert: t.base.invert, is_single_channel: t.base.mipmap.is_single_channel(), spectrum_type: t.spectrum_type, - - color_space: arena.alloc( - t.base - .mipmap - .color_space - .unwrap_or_else(crate::spectra::default_colorspace), - ), }) } } } -impl Upload for Arc { - type Target = Ptr; +impl Upload for Arc { + type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_float(&self, arena)) } } -impl Upload for Arc { - type Target = Ptr; +impl Upload for Arc { + type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_spectrum(&self, arena)) } } -impl Upload for &FloatTexture { - type Target = Ptr; +impl Upload for &HostFloatTexture { + type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_float(self, arena)) } } -impl Upload for &SpectrumTexture { - type Target = Ptr; +impl Upload for &HostSpectrumTexture { + type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_spectrum(self, arena)) } } -impl Upload for Option> { - type Target = Ptr; +impl Upload for Option> { + type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc_opt(self.map(|v| convert_float(&v, arena))) } } -impl Upload for Option> { - type Target = Ptr; +impl Upload for Option> { + type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc_opt(self.map(|v| convert_spectrum(&v, arena))) }