allow choosing which normals to use

This commit is contained in:
numzero 2025-11-24 00:21:06 +03:00
parent a51f46a038
commit 4b138deb34
6 changed files with 95 additions and 7 deletions

View File

@ -27,6 +27,13 @@ pub struct SphericalPosition {
pub distance: f32, pub distance: f32,
} }
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum UseNormal {
Light,
Camera,
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct RedrawArgs { pub struct RedrawArgs {
@ -36,7 +43,8 @@ pub struct RedrawArgs {
pub light_spread: f32, pub light_spread: f32,
pub accum_sigma: f32, pub accum_sigma: f32,
pub accum_scale: f32, pub accum_scale: f32,
pub reflections: u32, pub reflections: u8,
pub use_normal: UseNormal,
pub show_axes: bool, pub show_axes: bool,
pub show_shapes: bool, pub show_shapes: bool,
pub show_hit_emission: bool, pub show_hit_emission: bool,
@ -305,12 +313,15 @@ impl Core {
if d2 > 9. * sigma2 { if d2 > 9. * sigma2 {
continue; continue;
} }
assert!(hit.normal.is_normalized()); let normal = match args.use_normal {
UseNormal::Light => light_hit.normal,
UseNormal::Camera => hit.normal,
};
assert!(normal.is_normalized());
assert!(hit.incident.dir.is_normalized()); assert!(hit.incident.dir.is_normalized());
let reflector = Lambertian; let reflector = Lambertian;
let in_lm = 1.0; let in_lm = 1.0;
let out_cd = let out_cd = in_lm * reflector.brdf(normal, light_hit.incident.dir, -ray.dir);
in_lm * reflector.brdf(light_hit.normal, light_hit.incident.dir, -ray.dir);
let weight = accum_normalizator * (-0.5 * d2 / sigma2).exp(); let weight = accum_normalizator * (-0.5 * d2 / sigma2).exp();
total_cd += weight * out_cd; total_cd += weight * out_cd;
} }

View File

@ -1,7 +1,7 @@
use std::{f32::consts::PI, sync::Arc}; use std::{f32::consts::PI, sync::Arc};
use glam::uvec2; use glam::uvec2;
use photon_light::{Core, RedrawArgs, SphericalPosition, init_gpu_inner}; use photon_light::{Core, RedrawArgs, SphericalPosition, UseNormal, init_gpu_inner};
use winit::{ use winit::{
application::ApplicationHandler, application::ApplicationHandler,
event::WindowEvent, event::WindowEvent,
@ -53,6 +53,7 @@ impl MainWindow {
accum_sigma: 0.025, accum_sigma: 0.025,
accum_scale: 0.01, accum_scale: 0.01,
reflections: 2, reflections: 2,
use_normal: UseNormal::Light,
show_axes: true, show_axes: true,
show_shapes: true, show_shapes: true,
show_hit_emission: false, show_hit_emission: false,

View File

@ -13,6 +13,11 @@ struct SphericalPosition {
float distance = 1.; float distance = 1.;
}; };
enum class UseNormal: std::uint8_t {
Light,
Camera,
};
struct RedrawArgs { struct RedrawArgs {
SphericalPosition camera_position; SphericalPosition camera_position;
SphericalPosition light_position; SphericalPosition light_position;
@ -20,7 +25,8 @@ struct RedrawArgs {
float light_spread = 0.; float light_spread = 0.;
float accum_sigma = 1.; float accum_sigma = 1.;
float accum_scale = 1.; float accum_scale = 1.;
std::uint32_t reflections = 0; std::uint8_t reflections = 0;
UseNormal use_normal = UseNormal::Light;
bool show_axes = true; bool show_axes = true;
bool show_shapes = true; bool show_shapes = true;
bool show_hit_emission = true; bool show_hit_emission = true;
@ -31,6 +37,7 @@ struct RedrawArgs {
}; };
} // namespace ffi } // namespace ffi
using ffi::UseNormal;
using ffi::RedrawArgs; using ffi::RedrawArgs;
using ffi::SphericalPosition; using ffi::SphericalPosition;

View File

@ -16,6 +16,11 @@ float deg_to_rad(float val) {
} }
void PhotonLight::updateView() { void PhotonLight::updateView() {
UseNormal use_normal = {};
if (m_ui->normalFromLight->isChecked())
use_normal = UseNormal::Light;
else if (m_ui->normalFromCamera->isChecked())
use_normal = UseNormal::Camera;
RedrawArgs args{ RedrawArgs args{
.camera_position = SphericalPosition{ .camera_position = SphericalPosition{
.yaw = deg_to_rad(m_ui->cameraYaw->value()), .yaw = deg_to_rad(m_ui->cameraYaw->value()),
@ -31,7 +36,8 @@ void PhotonLight::updateView() {
.light_spread = 0.125, .light_spread = 0.125,
.accum_sigma = exp10f(m_ui->accumSigma->value() / 25.0), .accum_sigma = exp10f(m_ui->accumSigma->value() / 25.0),
.accum_scale = exp10f(m_ui->accumScale->value() / 25.0), .accum_scale = exp10f(m_ui->accumScale->value() / 25.0),
.reflections = std::uint32_t(m_ui->reflections->value()), .reflections = std::uint8_t(m_ui->reflections->value()),
.use_normal = use_normal,
.show_axes = m_ui->displayAxes->isChecked(), .show_axes = m_ui->displayAxes->isChecked(),
.show_shapes = m_ui->displayShapes->isChecked(), .show_shapes = m_ui->displayShapes->isChecked(),
.show_hit_emission = m_ui->displayEmitted->isChecked(), .show_hit_emission = m_ui->displayEmitted->isChecked(),
@ -51,4 +57,9 @@ void PhotonLight::updateView() {
m_ui->viewport->setView(args); m_ui->viewport->setView(args);
} }
void PhotonLight::updateViewIf(bool update) {
if (update)
updateView();
}
#include "moc_main_window.cpp" #include "moc_main_window.cpp"

View File

@ -16,6 +16,7 @@ public:
public slots: public slots:
void updateView(); void updateView();
void updateViewIf(bool update); // for radio buttons
private: private:
const std::unique_ptr<Ui::MainWindow> m_ui; const std::unique_ptr<Ui::MainWindow> m_ui;

View File

@ -298,6 +298,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Use normal at</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="normalFromLight">
<property name="text">
<string>Hit position</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="normalFromCamera">
<property name="text">
<string>Show position</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -637,8 +661,41 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>normalFromLight</sender>
<signal>toggled(bool)</signal>
<receiver>MainWindow</receiver>
<slot>updateViewIf(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>1429</x>
<y>787</y>
</hint>
<hint type="destinationlabel">
<x>1381</x>
<y>783</y>
</hint>
</hints>
</connection>
<connection>
<sender>normalFromCamera</sender>
<signal>toggled(bool)</signal>
<receiver>MainWindow</receiver>
<slot>updateViewIf(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>1932</x>
<y>816</y>
</hint>
<hint type="destinationlabel">
<x>1600</x>
<y>874</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots> <slots>
<slot>updateView()</slot> <slot>updateView()</slot>
<slot>updateViewIf(bool)</slot>
</slots> </slots>
</ui> </ui>