Compare commits
No commits in common. "80be92faaabfaa0825537a6a5c7027b75e5c4656" and "1a91735a6a77ad94215526e6119ea45b5911fdc6" have entirely different histories.
80be92faaa
...
1a91735a6a
|
|
@ -9,9 +9,6 @@ find_package(Qt6 REQUIRED COMPONENTS Gui Widgets)
|
|||
find_program(CARGO cargo REQUIRED)
|
||||
set(CARGO_TARGET_DIR "${CMAKE_SOURCE_DIR}/target" CACHE PATH "Path to the Cargo target directory")
|
||||
|
||||
include(diplomat.cmake)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(ui)
|
||||
|
|
|
|||
91
Cargo.lock
generated
91
Cargo.lock
generated
|
|
@ -165,9 +165,9 @@ checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.25.2"
|
||||
version = "1.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
|
||||
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
|
@ -180,7 +180,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -354,38 +354,6 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
|
||||
|
||||
[[package]]
|
||||
name = "diplomat"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61a80510e6103d35c5cd031c0e3f21165b32742c301ee3dafdbb5904c6dca46a"
|
||||
dependencies = [
|
||||
"diplomat_core",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diplomat-runtime"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9d981121ba76150987fda68185b37853c0b928a55dfdc28897348cd068440be"
|
||||
|
||||
[[package]]
|
||||
name = "diplomat_core"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa5c594efd1d097105255fc325c430a517c97b7b7c69f8727f653593e1ce726"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"strck",
|
||||
"syn 3.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
|
@ -474,7 +442,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -924,7 +892,7 @@ dependencies = [
|
|||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1214,8 +1182,6 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"approx",
|
||||
"bytemuck",
|
||||
"diplomat",
|
||||
"diplomat-runtime",
|
||||
"glam",
|
||||
"pollster",
|
||||
"rand",
|
||||
|
|
@ -1225,6 +1191,17 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "photon-light-impl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"photon-light",
|
||||
"pollster",
|
||||
"raw-window-handle",
|
||||
"wgpu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
|
|
@ -1242,7 +1219,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1553,7 +1530,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1632,15 +1609,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strck"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42316e70da376f3d113a68d138a60d8a9883c604fe97942721ec2068dab13a9f"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strict-num"
|
||||
version = "0.1.1"
|
||||
|
|
@ -1658,17 +1626,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
|
|
@ -1704,7 +1661,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1715,7 +1672,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1884,7 +1841,7 @@ dependencies = [
|
|||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
|
@ -2217,7 +2174,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2228,7 +2185,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2560,5 +2517,5 @@ checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
"syn",
|
||||
]
|
||||
|
|
|
|||
10
Cargo.toml
10
Cargo.toml
|
|
@ -1,11 +1,11 @@
|
|||
[workspace]
|
||||
members = ["ui"]
|
||||
|
||||
[package]
|
||||
name = "photon-light"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "staticlib"]
|
||||
|
||||
[profile.dev]
|
||||
panic = 'abort'
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ debug = false
|
|||
opt-level = 3
|
||||
|
||||
[dependencies]
|
||||
bytemuck = "1.25.2"
|
||||
bytemuck = "1.24.0"
|
||||
glam = { version = "0.30.9", features = ["bytemuck", "approx"] }
|
||||
pollster = "0.4.0"
|
||||
rand = "0.9.2"
|
||||
|
|
@ -26,8 +26,6 @@ rand_distr = "0.5.1"
|
|||
rand_pcg = "0.9.0"
|
||||
wgpu = "27.0.1"
|
||||
winit = "0.30.12"
|
||||
diplomat = "0.17.0"
|
||||
diplomat-runtime = "0.16.1"
|
||||
|
||||
[dev-dependencies]
|
||||
approx = "0.5.1"
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
set(crates "${CMAKE_BINARY_DIR}/crates")
|
||||
set(diplomat "${crates}/bin/diplomat-tool")
|
||||
|
||||
if(NOT IS_EXECUTABLE "${diplomat}")
|
||||
message(CONFIGURE_LOG "Downloading Diplomat...")
|
||||
file(MAKE_DIRECTORY "${crates}")
|
||||
execute_process(COMMAND ${CARGO} install --root "${crates}" diplomat-tool@0.17.0)
|
||||
endif()
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# build the Rust side as a static library
|
||||
set(impl_basename "${CARGO_TARGET_DIR}/release/libphoton_light")
|
||||
|
||||
set(cargo_cmake_args)
|
||||
set(diplomat_cmake_args)
|
||||
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.27")
|
||||
list(APPEND cargo_cmake_args DEPENDS_EXPLICIT_ONLY)
|
||||
list(APPEND diplomat_cmake_args DEPENDS_EXPLICIT_ONLY)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.28")
|
||||
list(APPEND cargo_cmake_args JOB_SERVER_AWARE TRUE)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.31")
|
||||
list(APPEND diplomat_cmake_args CODEGEN)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${impl_basename}.a"
|
||||
COMMAND env "CARGO_TARGET_DIR=${CARGO_TARGET_DIR}" ${CARGO} build --release --package photon-light
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
DEPFILE "${impl_basename}.d"
|
||||
USES_TERMINAL
|
||||
VERBATIM
|
||||
${cargo_cmake_args}
|
||||
)
|
||||
|
||||
# HACK ensure CMake *actually adds* the command above
|
||||
add_custom_target(build_impl
|
||||
DEPENDS "${impl_basename}.a"
|
||||
)
|
||||
|
||||
add_library(photon_light_impl STATIC IMPORTED GLOBAL)
|
||||
|
||||
set_target_properties(photon_light_impl PROPERTIES
|
||||
IMPORTED_LOCATION "${impl_basename}.a"
|
||||
)
|
||||
|
||||
# generate the bindings
|
||||
set(bindings_dir "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
file(MAKE_DIRECTORY "${bindings_dir}")
|
||||
set(bindings
|
||||
"${bindings_dir}/Core.hpp"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${bindings}
|
||||
COMMAND ${diplomat} cpp "${bindings_dir}"
|
||||
MAIN_DEPENDENCY "lib.rs"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
VERBATIM
|
||||
${diplomat_cmake_args}
|
||||
)
|
||||
|
||||
# HACK ensure CMake *actually adds* the command above
|
||||
add_custom_target(codegen_impl
|
||||
DEPENDS ${bindings}
|
||||
)
|
||||
|
||||
target_sources(photon_light_impl INTERFACE ${bindings})
|
||||
target_include_directories(photon_light_impl INTERFACE "${bindings_dir}")
|
||||
22
src/iter.rs
22
src/iter.rs
|
|
@ -1,22 +0,0 @@
|
|||
use std::convert::identity;
|
||||
|
||||
pub(crate) fn loop_list<T: Clone>(iter: impl IntoIterator<Item = T>) -> impl Iterator<Item = T> {
|
||||
loop_list_ex(iter, identity, identity)
|
||||
}
|
||||
|
||||
pub(crate) fn loop_list_ex<T: Clone, U>(
|
||||
iter: impl IntoIterator<Item = T>,
|
||||
mut fa: impl FnMut(T) -> U,
|
||||
mut fb: impl FnMut(T) -> U,
|
||||
) -> impl Iterator<Item = U> {
|
||||
gen move {
|
||||
let mut iter = iter.into_iter();
|
||||
let Some(first) = iter.next() else { return };
|
||||
yield fa(first.clone());
|
||||
for item in iter {
|
||||
yield fb(item.clone());
|
||||
yield fa(item);
|
||||
}
|
||||
yield fb(first);
|
||||
}
|
||||
}
|
||||
98
src/lib.rs
98
src/lib.rs
|
|
@ -1,14 +1,12 @@
|
|||
#![feature(gen_blocks)]
|
||||
|
||||
use std::{error::Error, f32::consts::PI};
|
||||
use std::{convert::identity, error::Error, f32::consts::PI};
|
||||
|
||||
use glam::{Mat4, UVec2, Vec2, Vec3, vec3};
|
||||
use rand_distr::Distribution as _;
|
||||
use wgpu::rwh::{RawDisplayHandle, RawWindowHandle};
|
||||
|
||||
use crate::{
|
||||
camera::OrbitalCamera,
|
||||
iter::loop_list,
|
||||
ray::Ray,
|
||||
render::{
|
||||
DEPTH_FORMAT, OUTPUT_FORMAT,
|
||||
|
|
@ -17,37 +15,30 @@ use crate::{
|
|||
trace::{Hit, Lambertian, Reflector, Scene, Source, Sphere},
|
||||
};
|
||||
|
||||
pub use crate::ffi::{RedrawArgs, SphericalPosition, UseNormal};
|
||||
|
||||
mod camera;
|
||||
mod iter;
|
||||
mod ray;
|
||||
mod render;
|
||||
mod shape;
|
||||
mod trace;
|
||||
|
||||
#[diplomat::bridge]
|
||||
mod ffi {
|
||||
use std::{f32::consts::PI, num::NonZero, ptr::NonNull};
|
||||
|
||||
use glam::uvec2;
|
||||
use wgpu::rwh::{XcbDisplayHandle, XcbWindowHandle};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct SphericalPosition {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct SphericalPosition {
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
pub distance: f32,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UseNormal {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum UseNormal {
|
||||
Light,
|
||||
Camera,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RedrawArgs {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct RedrawArgs {
|
||||
pub camera_position: SphericalPosition,
|
||||
pub light_position: SphericalPosition,
|
||||
pub light_radius: f32,
|
||||
|
|
@ -63,9 +54,9 @@ mod ffi {
|
|||
pub show_direct_hit: bool,
|
||||
pub show_indirect_hit: bool,
|
||||
pub show_light: bool,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RedrawArgs {
|
||||
impl Default for RedrawArgs {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
camera_position: SphericalPosition {
|
||||
|
|
@ -93,29 +84,6 @@ mod ffi {
|
|||
show_light: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[diplomat::opaque_mut]
|
||||
pub struct Core(crate::Core);
|
||||
|
||||
impl Core {
|
||||
pub fn from_xcb(connection: usize, window: u32, width: u32, height: u32) -> Box<Core> {
|
||||
let display =
|
||||
XcbDisplayHandle::new(Some(NonNull::new(connection as *mut _).unwrap()), 0);
|
||||
let window = XcbWindowHandle::new(NonZero::new(window).unwrap());
|
||||
let gpu = unsafe { crate::Gpu::new_raw(display, window) };
|
||||
let size = uvec2(width, height);
|
||||
Box::new(Self(crate::Core::new(gpu, size)))
|
||||
}
|
||||
|
||||
pub fn configure(&mut self, width: u32, height: u32) {
|
||||
self.0.configure(uvec2(width, height));
|
||||
}
|
||||
|
||||
pub fn redraw(&mut self, args: &RedrawArgs) {
|
||||
self.0.redraw(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Gpu {
|
||||
|
|
@ -124,23 +92,6 @@ pub struct Gpu {
|
|||
surface: wgpu::Surface<'static>,
|
||||
}
|
||||
|
||||
impl Gpu {
|
||||
unsafe fn new_raw(
|
||||
display: impl Into<RawDisplayHandle>,
|
||||
window: impl Into<RawWindowHandle>,
|
||||
) -> Self {
|
||||
let target = wgpu::SurfaceTargetUnsafe::RawHandle {
|
||||
raw_display_handle: display.into(),
|
||||
raw_window_handle: window.into(),
|
||||
};
|
||||
let gpu = pollster::block_on(init_gpu_inner(|instance| unsafe {
|
||||
instance.create_surface_unsafe(target)
|
||||
}))
|
||||
.unwrap();
|
||||
gpu
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Core {
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
|
|
@ -167,6 +118,27 @@ pub fn new_tripod(device: &wgpu::Device) -> Mesh {
|
|||
)
|
||||
}
|
||||
|
||||
fn loop_list<T: Clone>(iter: impl IntoIterator<Item = T>) -> impl Iterator<Item = T> {
|
||||
loop_list_ex(iter, identity, identity)
|
||||
}
|
||||
|
||||
fn loop_list_ex<T: Clone, U>(
|
||||
iter: impl IntoIterator<Item = T>,
|
||||
mut fa: impl FnMut(T) -> U,
|
||||
mut fb: impl FnMut(T) -> U,
|
||||
) -> impl Iterator<Item = U> {
|
||||
gen move {
|
||||
let mut iter = iter.into_iter();
|
||||
let Some(first) = iter.next() else { return };
|
||||
yield fa(first.clone());
|
||||
for item in iter {
|
||||
yield fb(item.clone());
|
||||
yield fa(item);
|
||||
}
|
||||
yield fb(first);
|
||||
}
|
||||
}
|
||||
|
||||
impl OrbitalCamera {
|
||||
fn make_ray(&self, rng: &mut impl rand::Rng) -> Ray {
|
||||
let off: f32 = rand_distr::StandardUniform.sample(rng);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
include(impl.cmake)
|
||||
|
||||
qt_add_executable(photon-light
|
||||
src/api.cxx
|
||||
src/main.cxx
|
||||
src/main_window.cxx
|
||||
src/main_window.ui
|
||||
|
|
|
|||
15
ui/Cargo.toml
Normal file
15
ui/Cargo.toml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "photon-light-impl"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
photon-light = {path = "../"}
|
||||
|
||||
glam = { version = "0.30" }
|
||||
pollster = "0.4.0"
|
||||
raw-window-handle = "0.6.2"
|
||||
wgpu = "27.0.1"
|
||||
33
ui/impl.cmake
Normal file
33
ui/impl.cmake
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# build the Rust side as a static library
|
||||
set(impl_basename "${CARGO_TARGET_DIR}/release/libphoton_light_impl")
|
||||
|
||||
set(cargo_cmake_args)
|
||||
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.27")
|
||||
list(APPEND cargo_cmake_args DEPENDS_EXPLICIT_ONLY)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.28")
|
||||
list(APPEND cargo_cmake_args JOB_SERVER_AWARE TRUE)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${impl_basename}.a"
|
||||
COMMAND env "CARGO_TARGET_DIR=${CARGO_TARGET_DIR}" ${CARGO} build --release --package photon-light-impl
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
DEPFILE "${impl_basename}.d"
|
||||
USES_TERMINAL
|
||||
VERBATIM
|
||||
${cargo_cmake_args}
|
||||
)
|
||||
|
||||
# HACK ensure CMake *actually adds* the command above
|
||||
add_custom_target(build_impl
|
||||
DEPENDS "${impl_basename}.a"
|
||||
)
|
||||
|
||||
add_library(photon_light_impl STATIC IMPORTED)
|
||||
|
||||
set_target_properties(photon_light_impl PROPERTIES
|
||||
IMPORTED_LOCATION "${impl_basename}.a"
|
||||
)
|
||||
57
ui/src/api.cxx
Normal file
57
ui/src/api.cxx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "api.hxx"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace ffi {
|
||||
extern "C" Core* rt4_viewport_create(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height);
|
||||
extern "C" void rt4_viewport_destroy(Core* viewport);
|
||||
extern "C" void rt4_viewport_configure(Core* viewport, std::uint32_t width, std::uint32_t height);
|
||||
extern "C" void rt4_viewport_redraw(Core* viewport, const RedrawArgs* args);
|
||||
} // namespace ffi
|
||||
|
||||
BoxCore::BoxCore(BoxCore&& b)
|
||||
: ptr(std::exchange(b.ptr, {})) {
|
||||
}
|
||||
|
||||
BoxCore::~BoxCore() {
|
||||
reset();
|
||||
}
|
||||
|
||||
BoxCore& BoxCore::operator=(BoxCore&& b) {
|
||||
if (&b == this)
|
||||
return *this;
|
||||
std::swap(ptr, b.ptr);
|
||||
b.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
BoxCore BoxCore::from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) {
|
||||
if (!connection)
|
||||
throw std::logic_error("attempt to use a null connection");
|
||||
if (!window)
|
||||
throw std::logic_error("attempt to use a null window");
|
||||
BoxCore out;
|
||||
out.ptr.ptr = ffi::rt4_viewport_create(connection, window, width, height);
|
||||
return out;
|
||||
}
|
||||
|
||||
void BoxCore::reset() {
|
||||
auto viewport = std::exchange(ptr, {});
|
||||
if (viewport)
|
||||
ffi::rt4_viewport_destroy(viewport.use());
|
||||
}
|
||||
|
||||
ffi::Core* MutCore::use() const {
|
||||
if (!ptr)
|
||||
throw std::logic_error("attempt to use a null Core");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void MutCore::configure(std::uint32_t width, std::uint32_t height) const {
|
||||
rt4_viewport_configure(use(), width, height);
|
||||
}
|
||||
|
||||
void MutCore::redraw(const RedrawArgs& args) const {
|
||||
rt4_viewport_redraw(use(), &args);
|
||||
}
|
||||
76
ui/src/api.hxx
Normal file
76
ui/src/api.hxx
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct xcb_connection_t;
|
||||
|
||||
namespace ffi {
|
||||
struct Core;
|
||||
|
||||
struct SphericalPosition {
|
||||
float yaw = 0.;
|
||||
float pitch = 0.;
|
||||
float distance = 1.;
|
||||
};
|
||||
|
||||
enum class UseNormal: std::uint8_t {
|
||||
Light,
|
||||
Camera,
|
||||
};
|
||||
|
||||
struct RedrawArgs {
|
||||
SphericalPosition camera_position;
|
||||
SphericalPosition light_position;
|
||||
float light_radius = 1.;
|
||||
float light_spread = 0.;
|
||||
float accum_sigma = 1.;
|
||||
float accum_scale = 1.;
|
||||
std::uint8_t reflections = 0;
|
||||
UseNormal use_normal = UseNormal::Light;
|
||||
bool show_axes = true;
|
||||
bool show_shapes = true;
|
||||
bool show_hit_emission = true;
|
||||
bool show_miss_emission = true;
|
||||
bool show_direct_hit = true;
|
||||
bool show_indirect_hit = true;
|
||||
bool show_light = true;
|
||||
};
|
||||
} // namespace ffi
|
||||
|
||||
using ffi::UseNormal;
|
||||
using ffi::RedrawArgs;
|
||||
using ffi::SphericalPosition;
|
||||
|
||||
class MutCore {
|
||||
friend class BoxCore;
|
||||
|
||||
public:
|
||||
explicit operator bool() const { return ptr; }
|
||||
|
||||
void configure(std::uint32_t width, std::uint32_t height) const;
|
||||
void redraw(const RedrawArgs& args) const;
|
||||
|
||||
private:
|
||||
ffi::Core* ptr = nullptr;
|
||||
ffi::Core* use() const;
|
||||
};
|
||||
|
||||
class BoxCore {
|
||||
public:
|
||||
BoxCore() = default;
|
||||
BoxCore(const BoxCore&) = delete;
|
||||
BoxCore(BoxCore&&);
|
||||
BoxCore& operator=(const BoxCore&) = delete;
|
||||
BoxCore& operator=(BoxCore&&);
|
||||
~BoxCore();
|
||||
|
||||
explicit operator bool() const { return !!ptr; }
|
||||
const MutCore* operator->() const { return &ptr; }
|
||||
|
||||
void reset();
|
||||
|
||||
static BoxCore from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height);
|
||||
|
||||
private:
|
||||
MutCore ptr;
|
||||
};
|
||||
49
ui/src/lib.rs
Normal file
49
ui/src/lib.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use std::{ffi::c_void, num::NonZero, ptr::NonNull};
|
||||
|
||||
use glam::{UVec2, uvec2};
|
||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle};
|
||||
|
||||
use photon_light::{Core, RedrawArgs, init_gpu_inner};
|
||||
|
||||
unsafe fn create_viewport(
|
||||
display: impl Into<RawDisplayHandle>,
|
||||
window: impl Into<RawWindowHandle>,
|
||||
size: UVec2,
|
||||
) -> Box<Core> {
|
||||
let target = wgpu::SurfaceTargetUnsafe::RawHandle {
|
||||
raw_display_handle: display.into(),
|
||||
raw_window_handle: window.into(),
|
||||
};
|
||||
let gpu = pollster::block_on(init_gpu_inner(|instance| unsafe {
|
||||
instance.create_surface_unsafe(target)
|
||||
}))
|
||||
.unwrap();
|
||||
Box::new(Core::new(gpu, size))
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn rt4_viewport_create(
|
||||
connection: NonNull<c_void>,
|
||||
window: NonZero<u32>,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Box<Core> {
|
||||
let display = XcbDisplayHandle::new(Some(connection), 0);
|
||||
let window = XcbWindowHandle::new(window);
|
||||
unsafe { create_viewport(display, window, uvec2(width, height)) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn rt4_viewport_destroy(viewport: Box<Core>) {
|
||||
drop(viewport);
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn rt4_viewport_configure(viewport: &mut Core, width: u32, height: u32) {
|
||||
viewport.configure(uvec2(width, height));
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn rt4_viewport_redraw(viewport: &mut Core, args: &RedrawArgs) {
|
||||
viewport.redraw(args);
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ void Viewport::recreate() try {
|
|||
|
||||
const QSize device_size = size() * devicePixelRatio();
|
||||
core.reset();
|
||||
core = Core::from_xcb((std::uintptr_t)xcb_connection, x11_window, device_size.width(), device_size.height());
|
||||
core = BoxCore::from_xcb(xcb_connection, x11_window, device_size.width(), device_size.height());
|
||||
} catch (const std::exception& e) {
|
||||
fprintf(stderr, "failed to recreate the viewport: %s", e.what());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Core.hpp"
|
||||
#include "api.hxx"
|
||||
|
||||
class Viewport : public QWidget {
|
||||
Q_OBJECT
|
||||
|
|
@ -20,7 +20,7 @@ protected:
|
|||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Core> core;
|
||||
BoxCore core;
|
||||
RedrawArgs args = {};
|
||||
|
||||
void recreate();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user