Added gpu config flag, completed light sampling methods
This commit is contained in:
parent
2448ab890e
commit
0fcfcbd467
18 changed files with 110 additions and 60 deletions
|
|
@ -2,4 +2,13 @@ fn main() {
|
||||||
// This allows "spirv" to be used in #[cfg(target_arch = "...")]
|
// This allows "spirv" to be used in #[cfg(target_arch = "...")]
|
||||||
// without triggering a warning.
|
// without triggering a warning.
|
||||||
println!("cargo:rustc-check-cfg=cfg(target_arch, values(\"spirv\"))");
|
println!("cargo:rustc-check-cfg=cfg(target_arch, values(\"spirv\"))");
|
||||||
|
|
||||||
|
// `gpu` is set for every device backend, so host-only code can be gated once
|
||||||
|
// as #[cfg(not(gpu))] instead of naming each target. Adding a backend means
|
||||||
|
// editing this line, not 30-odd cfg attributes.
|
||||||
|
println!("cargo::rustc-check-cfg=cfg(gpu)");
|
||||||
|
let target = std::env::var("TARGET").unwrap_or_default();
|
||||||
|
if target.contains("spirv") || target.contains("cuda") {
|
||||||
|
println!("cargo::rustc-cfg=gpu");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ pub struct OrthographicCamera {
|
||||||
pub dy_camera: Vector3f,
|
pub dy_camera: Vector3f,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
impl OrthographicCamera {
|
impl OrthographicCamera {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
base: CameraBase,
|
base: CameraBase,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub struct PerspectiveCamera {
|
||||||
pub cos_total_width: Float,
|
pub cos_total_width: Float,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
impl PerspectiveCamera {
|
impl PerspectiveCamera {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
base: CameraBase,
|
base: CameraBase,
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ pub trait CameraTrait {
|
||||||
fn generate_ray(&self, sample: CameraSample, lambda: &SampledWavelengths) -> Option<CameraRay>;
|
fn generate_ray(&self, sample: CameraSample, lambda: &SampledWavelengths) -> Option<CameraRay>;
|
||||||
|
|
||||||
fn get_film(&self) -> &Film {
|
fn get_film(&self) -> &Film {
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
{
|
{
|
||||||
if self.base().film.is_null() {
|
if self.base().film.is_null() {
|
||||||
panic!(
|
panic!(
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ impl RGBFilm {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sensor(&self) -> &PixelSensor {
|
pub fn get_sensor(&self) -> &PixelSensor {
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
{
|
{
|
||||||
if self.base.sensor.is_null() {
|
if self.base.sensor.is_null() {
|
||||||
panic!(
|
panic!(
|
||||||
|
|
@ -203,7 +203,7 @@ impl RGBFilm {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(target_os = "cuda", derive(Copy))]
|
#[cfg_attr(gpu, derive(Copy))]
|
||||||
pub struct GBufferPixel {
|
pub struct GBufferPixel {
|
||||||
pub rgb_sum: [AtomicFloat; 3],
|
pub rgb_sum: [AtomicFloat; 3],
|
||||||
pub weight_sum: AtomicFloat,
|
pub weight_sum: AtomicFloat,
|
||||||
|
|
@ -240,7 +240,7 @@ impl Default for GBufferPixel {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(target_os = "cuda", derive(Copy))]
|
#[cfg_attr(gpu, derive(Copy))]
|
||||||
pub struct GBufferFilm {
|
pub struct GBufferFilm {
|
||||||
pub base: FilmBase,
|
pub base: FilmBase,
|
||||||
pub output_from_render: AnimatedTransform,
|
pub output_from_render: AnimatedTransform,
|
||||||
|
|
@ -294,7 +294,7 @@ impl GBufferFilm {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sensor(&self) -> &PixelSensor {
|
pub fn get_sensor(&self) -> &PixelSensor {
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
{
|
{
|
||||||
if self.base.sensor.is_null() {
|
if self.base.sensor.is_null() {
|
||||||
panic!(
|
panic!(
|
||||||
|
|
@ -387,7 +387,7 @@ impl GBufferFilm {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(target_os = "cuda", derive(Copy))]
|
#[cfg_attr(gpu, derive(Copy))]
|
||||||
pub struct SpectralPixel {
|
pub struct SpectralPixel {
|
||||||
pub rgb_sum: [AtomicFloat; 3],
|
pub rgb_sum: [AtomicFloat; 3],
|
||||||
pub rgb_weight_sum: AtomicFloat,
|
pub rgb_weight_sum: AtomicFloat,
|
||||||
|
|
@ -419,7 +419,7 @@ impl Default for SpectralPixel {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(target_os = "cuda", derive(Copy, Clone))]
|
#[cfg_attr(gpu, derive(Copy, Clone))]
|
||||||
pub struct SpectralFilm {
|
pub struct SpectralFilm {
|
||||||
pub base: FilmBase,
|
pub base: FilmBase,
|
||||||
pub lambda_min: Float,
|
pub lambda_min: Float,
|
||||||
|
|
@ -609,7 +609,7 @@ pub struct FilmBase {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(target_os = "cuda", derive(Copy, Clone))]
|
#[cfg_attr(gpu, derive(Copy, Clone))]
|
||||||
pub enum Film {
|
pub enum Film {
|
||||||
RGB(RGBFilm),
|
RGB(RGBFilm),
|
||||||
GBuffer(GBufferFilm),
|
GBuffer(GBufferFilm),
|
||||||
|
|
|
||||||
|
|
@ -590,7 +590,7 @@ impl SurfaceInteraction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
pub fn set_intersection_properties(
|
pub fn set_intersection_properties(
|
||||||
&mut self,
|
&mut self,
|
||||||
mtl: MaterialIdx,
|
mtl: MaterialIdx,
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ pub struct LightLiSample {
|
||||||
pub p_light: Interaction,
|
pub p_light: Interaction,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
impl LightLiSample {
|
impl LightLiSample {
|
||||||
pub fn new(l: SampledSpectrum, wi: Vector3f, pdf: Float, p_light: Interaction) -> Self {
|
pub fn new(l: SampledSpectrum, wi: Vector3f, pdf: Float, p_light: Interaction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -188,7 +188,7 @@ pub struct LightBounds {
|
||||||
pub two_sided: bool,
|
pub two_sided: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
impl LightBounds {
|
impl LightBounds {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
bounds: &Bounds3f,
|
bounds: &Bounds3f,
|
||||||
|
|
@ -327,13 +327,13 @@ pub trait LightTrait {
|
||||||
self.base().light_type
|
self.base().light_type
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn bounds(&self) -> Option<LightBounds>;
|
fn bounds(&self) -> Option<LightBounds>;
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn preprocess(&mut self, scene_bounds: &Bounds3f);
|
fn preprocess(&mut self, scene_bounds: &Bounds3f);
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum;
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ pub struct MajorantGrid {
|
||||||
|
|
||||||
|
|
||||||
impl MajorantGrid {
|
impl MajorantGrid {
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
||||||
let n_voxels = (res.x() * res.y() * res.z()) as usize;
|
let n_voxels = (res.x() * res.y() * res.z()) as usize;
|
||||||
let voxels = gvec_with_capacity(n_voxels);
|
let voxels = gvec_with_capacity(n_voxels);
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ pub struct PointTransformMapping {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointTransformMapping {
|
impl PointTransformMapping {
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
pub fn new(texture_from_render: Transform) -> Self {
|
pub fn new(texture_from_render: Transform) -> Self {
|
||||||
Self {
|
Self {
|
||||||
texture_from_render,
|
texture_from_render,
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ impl LightTrait for DiffuseAreaLight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
let mut l = SampledSpectrum::new(0.);
|
let mut l = SampledSpectrum::new(0.);
|
||||||
if !self.image.is_null() {
|
if !self.image.is_null() {
|
||||||
|
|
@ -153,10 +153,10 @@ impl LightTrait for DiffuseAreaLight {
|
||||||
PI * two_side * self.area * l
|
PI * two_side * self.area * l
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn preprocess(&mut self, _scene_bounds: &Bounds3f) {}
|
fn preprocess(&mut self, _scene_bounds: &Bounds3f) {}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn bounds(&self) -> Option<LightBounds> {
|
fn bounds(&self) -> Option<LightBounds> {
|
||||||
let mut phi = 0.;
|
let mut phi = 0.;
|
||||||
if !self.image.is_null() {
|
if !self.image.is_null() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::core::geometry::{Bounds3f, Normal3f, Point2f, Point2i, Point3f, Ray, Vector3f};
|
use crate::core::geometry::{
|
||||||
|
Bounds3f, Normal3f, Point2f, Point2i, Point3f, Ray, Vector3f, VectorLike,
|
||||||
|
};
|
||||||
use crate::core::image::Image;
|
use crate::core::image::Image;
|
||||||
|
use crate::core::interaction::{Interaction, InteractionBase, SimpleInteraction};
|
||||||
use crate::core::light::{
|
use crate::core::light::{
|
||||||
LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait, LightType,
|
LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait, LightType,
|
||||||
};
|
};
|
||||||
|
|
@ -34,12 +37,20 @@ impl LightTrait for GoniometricLight {
|
||||||
|
|
||||||
fn sample_li(
|
fn sample_li(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &LightSampleContext,
|
ctx: &LightSampleContext,
|
||||||
_u: Point2f,
|
_u: Point2f,
|
||||||
_lambda: &SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
_allow_incomplete_pdf: bool,
|
_allow_incomplete_pdf: bool,
|
||||||
) -> Option<LightLiSample> {
|
) -> Option<LightLiSample> {
|
||||||
todo!()
|
let render_from_light = self.base().render_from_light;
|
||||||
|
let p = render_from_light.apply_to_point(Point3f::new(0., 0., 0.));
|
||||||
|
let wi = (p - ctx.p()).normalize();
|
||||||
|
let wl = render_from_light.apply_inverse_vector(-wi);
|
||||||
|
let li = self.i(wl, lambda) / p.distance_squared(ctx.p());
|
||||||
|
let base = InteractionBase::new_boundary(p, 0., self.base.medium_interface);
|
||||||
|
let intr = SimpleInteraction::new(base);
|
||||||
|
|
||||||
|
Some(LightLiSample::new(li, wi, 1., Interaction::Simple(intr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pdf_li(
|
fn pdf_li(
|
||||||
|
|
@ -76,7 +87,7 @@ impl LightTrait for GoniometricLight {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
let resolution = self.image.resolution();
|
let resolution = self.image.resolution();
|
||||||
let mut sum_y = 0.;
|
let mut sum_y = 0.;
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ impl LightTrait for UniformInfiniteLight {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
4. * PI * PI * square(self.scene_radius) * self.scale * self.lemit.sample(&lambda)
|
4. * PI * PI * square(self.scene_radius) * self.scale * self.lemit.sample(&lambda)
|
||||||
}
|
}
|
||||||
|
|
@ -227,21 +227,17 @@ impl LightTrait for ImageInfiniteLight {
|
||||||
self.image_le(uv, lambda)
|
self.image_le(uv, lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
let mut sum_l = SampledSpectrum::new(0.);
|
let mut sum_l = SampledSpectrum::new(0.);
|
||||||
let width = self.image.resolution().x();
|
let width = self.image.resolution().x();
|
||||||
let height = self.image.resolution().y();
|
let height = self.image.resolution().y();
|
||||||
for v in 0..height {
|
for v in 0..height {
|
||||||
for u in 0..width {
|
for u in 0..width {
|
||||||
let mut rgb = RGB::default();
|
let rgb = RGB::from(self.image.get_channels_with_wrap::<3>(
|
||||||
for c in 0..3 {
|
Point2i::new(u, v),
|
||||||
rgb[c] = self.image.get_channel_with_wrap(
|
WrapMode::OctahedralSphere.into(),
|
||||||
Point2i::new(u, v),
|
));
|
||||||
c,
|
|
||||||
WrapMode::OctahedralSphere.into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
sum_l += RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero())
|
sum_l += RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero())
|
||||||
.sample(&lambda);
|
.sample(&lambda);
|
||||||
}
|
}
|
||||||
|
|
@ -341,7 +337,7 @@ impl PortalInfiniteLight {
|
||||||
(self.portal[1] - self.portal[0]).norm() * (self.portal[3] - self.portal[0]).norm()
|
(self.portal[1] - self.portal[0]).norm() * (self.portal[3] - self.portal[0]).norm()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_from_image(portal_frame: Frame, uv: Point2f) -> (Vector3f, Float) {
|
pub fn render_from_image_with(portal_frame: Frame, uv: Point2f) -> (Vector3f, Float) {
|
||||||
let alpha = -PI / 2.0 + uv.x() * PI;
|
let alpha = -PI / 2.0 + uv.x() * PI;
|
||||||
let beta = -PI / 2.0 + uv.y() * PI;
|
let beta = -PI / 2.0 + uv.y() * PI;
|
||||||
|
|
||||||
|
|
@ -354,6 +350,11 @@ impl PortalInfiniteLight {
|
||||||
|
|
||||||
(portal_frame.from_local(w), duv_dw)
|
(portal_frame.from_local(w), duv_dw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn render_from_image(&self, uv: Point2f) -> (Vector3f, Float) {
|
||||||
|
Self::render_from_image_with(self.portal_frame, uv)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightTrait for PortalInfiniteLight {
|
impl LightTrait for PortalInfiniteLight {
|
||||||
|
|
@ -370,7 +371,7 @@ impl LightTrait for PortalInfiniteLight {
|
||||||
) -> Option<LightLiSample> {
|
) -> Option<LightLiSample> {
|
||||||
let b = self.image_bounds(ctx.p())?;
|
let b = self.image_bounds(ctx.p())?;
|
||||||
let (uv, map_pdf) = self.distribution.sample(u, b)?;
|
let (uv, map_pdf) = self.distribution.sample(u, b)?;
|
||||||
let (wi, duv_dw) = Self::render_from_image(self.portal_frame, uv);
|
let (wi, duv_dw) = self.render_from_image(uv);
|
||||||
if duv_dw == 0. {
|
if duv_dw == 0. {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
@ -403,17 +404,34 @@ impl LightTrait for PortalInfiniteLight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, _lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
todo!()
|
let mut sum_l = SampledSpectrum::new(0.);
|
||||||
|
let width = self.image.resolution().x();
|
||||||
|
let height = self.image.resolution().y();
|
||||||
|
for y in 0..height {
|
||||||
|
for x in 0..width {
|
||||||
|
let rgb = RGB::from(self.image.get_channels::<3>(Point2i::new(x, y)));
|
||||||
|
let st = Point2f::new(
|
||||||
|
(x as Float + 0.5) / width as Float,
|
||||||
|
(y as Float + 0.5) / height as Float,
|
||||||
|
);
|
||||||
|
let (_, duv_dw) = self.render_from_image(st);
|
||||||
|
sum_l += RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero())
|
||||||
|
.sample(&lambda)
|
||||||
|
/ duv_dw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.scale * self.area() * sum_l / (width * height) as Float
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn preprocess(&mut self, scene_bounds: &Bounds3f) {
|
fn preprocess(&mut self, scene_bounds: &Bounds3f) {
|
||||||
(self.scene_center, self.scene_radius) = scene_bounds.bounding_sphere();
|
(self.scene_center, self.scene_radius) = scene_bounds.bounding_sphere();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn bounds(&self) -> Option<LightBounds> {
|
fn bounds(&self) -> Option<LightBounds> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,14 @@ impl LightTrait for PointLight {
|
||||||
0.
|
0.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
4. * PI * self.scale * self.i.sample(&lambda)
|
4. * PI * self.scale * self.i.sample(&lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preprocess(&mut self, _scene_bounds: &Bounds3f) {}
|
fn preprocess(&mut self, _scene_bounds: &Bounds3f) {}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn bounds(&self) -> Option<LightBounds> {
|
fn bounds(&self) -> Option<LightBounds> {
|
||||||
let p = self
|
let p = self
|
||||||
.base
|
.base
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use crate::core::geometry::{
|
||||||
Bounds2f, Bounds3f, Normal3f, Point2f, Point2i, Point3f, Ray, Vector3f, VectorLike, cos_theta,
|
Bounds2f, Bounds3f, Normal3f, Point2f, Point2i, Point3f, Ray, Vector3f, VectorLike, cos_theta,
|
||||||
};
|
};
|
||||||
use crate::core::image::Image;
|
use crate::core::image::Image;
|
||||||
|
use crate::core::interaction::{Interaction, InteractionBase, SimpleInteraction};
|
||||||
use crate::core::light::{
|
use crate::core::light::{
|
||||||
LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait, LightType,
|
LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait, LightType,
|
||||||
};
|
};
|
||||||
|
|
@ -33,7 +34,7 @@ pub struct ProjectionLight {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectionLight {
|
impl ProjectionLight {
|
||||||
pub fn i(&self, w: Vector3f, lambda: SampledWavelengths) -> SampledSpectrum {
|
pub fn i(&self, w: Vector3f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
if w.z() < self.hither {
|
if w.z() < self.hither {
|
||||||
return SampledSpectrum::new(0.);
|
return SampledSpectrum::new(0.);
|
||||||
}
|
}
|
||||||
|
|
@ -44,10 +45,10 @@ impl ProjectionLight {
|
||||||
let uv = Point2f::from(self.screen_bounds.offset(&Point2f::new(ps.x(), ps.y())));
|
let uv = Point2f::from(self.screen_bounds.offset(&Point2f::new(ps.x(), ps.y())));
|
||||||
let mut rgb = RGB::default();
|
let mut rgb = RGB::default();
|
||||||
for c in 0..3 {
|
for c in 0..3 {
|
||||||
rgb[c] = self.image.lookup_nearest_channel(uv, c as i32);
|
rgb[c] = self.image.lookup_nearest_channel(uv, c);
|
||||||
}
|
}
|
||||||
let s = RGBIlluminantSpectrum::new(&*self.image_color_space, rgb.clamp_zero());
|
let s = RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero());
|
||||||
self.scale * s.sample(&lambda)
|
self.scale * s.sample(lambda)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,12 +59,23 @@ impl LightTrait for ProjectionLight {
|
||||||
|
|
||||||
fn sample_li(
|
fn sample_li(
|
||||||
&self,
|
&self,
|
||||||
_ctx: &LightSampleContext,
|
ctx: &LightSampleContext,
|
||||||
_u: Point2f,
|
_u: Point2f,
|
||||||
_lambda: &SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
_allow_incomplete_pdf: bool,
|
_allow_incomplete_pdf: bool,
|
||||||
) -> Option<LightLiSample> {
|
) -> Option<LightLiSample> {
|
||||||
todo!()
|
let render_from_light = self.base().render_from_light;
|
||||||
|
let p = render_from_light.apply_to_point(Point3f::new(0., 0., 0.));
|
||||||
|
let wi = (p - ctx.p()).normalize();
|
||||||
|
let wl = render_from_light.apply_inverse_vector(-wi);
|
||||||
|
let li = self.i(wl, lambda) / p.distance_squared(ctx.p());
|
||||||
|
if li.is_black() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let base = InteractionBase::new_boundary(p, 0., self.base.medium_interface);
|
||||||
|
let intr = SimpleInteraction::new(base);
|
||||||
|
|
||||||
|
Some(LightLiSample::new(li, wi, 1., Interaction::Simple(intr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pdf_li(
|
fn pdf_li(
|
||||||
|
|
@ -72,7 +84,7 @@ impl LightTrait for ProjectionLight {
|
||||||
_wi: Vector3f,
|
_wi: Vector3f,
|
||||||
_allow_incomplete_pdf: bool,
|
_allow_incomplete_pdf: bool,
|
||||||
) -> Float {
|
) -> Float {
|
||||||
todo!()
|
0.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
|
|
@ -93,10 +105,10 @@ impl LightTrait for ProjectionLight {
|
||||||
let dwda = cos_theta(w).powi(3);
|
let dwda = cos_theta(w).powi(3);
|
||||||
let mut rgb = RGB::default();
|
let mut rgb = RGB::default();
|
||||||
for c in 0..3 {
|
for c in 0..3 {
|
||||||
rgb[c] = self.image.get_channel(Point2i::new(x, y), c as i32);
|
rgb[c] = self.image.get_channel(Point2i::new(x, y), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
let s = RGBIlluminantSpectrum::new(&*self.image_color_space, rgb.clamp_zero());
|
let s = RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero());
|
||||||
sum += s.sample(&lambda) * dwda;
|
sum += s.sample(&lambda) * dwda;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ impl LightTrait for SpotLight {
|
||||||
0.
|
0.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum {
|
||||||
self.scale
|
self.scale
|
||||||
* self.iemit.sample(&lambda)
|
* self.iemit.sample(&lambda)
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ pub struct HairMaterial {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HairMaterial {
|
impl HairMaterial {
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sigma_a: Ptr<SpectrumTexture>,
|
sigma_a: Ptr<SpectrumTexture>,
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ impl BilinearPatchShape {
|
||||||
Some([mesh.n[v0], mesh.n[v1], mesh.n[v2], mesh.n[v3]])
|
Some([mesh.n[v0], mesh.n[v1], mesh.n[v2], mesh.n[v3]])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "cuda"))]
|
#[cfg(not(gpu))]
|
||||||
pub fn new(mesh: Ptr<BilinearPatchMesh>, blp_index: i32) -> Self {
|
pub fn new(mesh: Ptr<BilinearPatchMesh>, blp_index: i32) -> Self {
|
||||||
let mut bp = BilinearPatchShape {
|
let mut bp = BilinearPatchShape {
|
||||||
mesh,
|
mesh,
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ fn create_portal_light(
|
||||||
|
|
||||||
// Build distribution
|
// Build distribution
|
||||||
let duv_dw = |p: Point2f| -> Float {
|
let duv_dw = |p: Point2f| -> Float {
|
||||||
let (_, jacobian) = PortalInfiniteLight::render_from_image(portal_frame, p);
|
let (_, jacobian) = PortalInfiniteLight::render_from_image_with(portal_frame, p);
|
||||||
jacobian
|
jacobian
|
||||||
};
|
};
|
||||||
let d = remapped.get_sampling_distribution(
|
let d = remapped.get_sampling_distribution(
|
||||||
|
|
@ -247,7 +247,7 @@ fn remap_image_through_portal(
|
||||||
(y as Float + 0.5) / height as Float,
|
(y as Float + 0.5) / height as Float,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (w_world, _) = PortalInfiniteLight::render_from_image(*portal_frame, uv);
|
let (w_world, _) = PortalInfiniteLight::render_from_image_with(*portal_frame, uv);
|
||||||
let w_local = render_from_light.apply_inverse_vector(w_world).normalize();
|
let w_local = render_from_light.apply_inverse_vector(w_world).normalize();
|
||||||
let uv_equi = equal_area_sphere_to_square(w_local);
|
let uv_equi = equal_area_sphere_to_square(w_local);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue