Compare commits
6 Commits
features/b
...
features/m
| Author | SHA1 | Date | |
|---|---|---|---|
| 5183e73ca0 | |||
| b41ea60c02 | |||
| acaaa2a86e | |||
| 5c988108ef | |||
| 84b2504a6f | |||
| f1d3dddb9a |
7
.clangd
@@ -1,7 +0,0 @@
|
|||||||
CompileFlags:
|
|
||||||
Add:
|
|
||||||
- -IF:/c/SimpleRayTracer/external
|
|
||||||
- -IF:/c/SimpleRayTracer/header
|
|
||||||
- -LF:/c/SimpleRayTracer/lib
|
|
||||||
- -lcglm
|
|
||||||
- -lassimp-vc143-mt
|
|
||||||
365
.gitignore
vendored
@@ -1 +1,366 @@
|
|||||||
[Bb]uild/
|
[Bb]uild/
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
61
.vscode/tasks.json
vendored
@@ -1,61 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "CMake Build (Debug)",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"f:\\c\\SimpleRayTracer\\build",
|
|
||||||
"--config",
|
|
||||||
"Debug"
|
|
||||||
],
|
|
||||||
"isBackground": false,
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "CMake Build (Debug)",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"f:\\c\\SimpleRayTracer\\build",
|
|
||||||
"--config",
|
|
||||||
"Debug"
|
|
||||||
],
|
|
||||||
"isBackground": false,
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "CMake Build (Debug)",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"f:\\c\\SimpleRayTracer\\build",
|
|
||||||
"--config",
|
|
||||||
"Debug"
|
|
||||||
],
|
|
||||||
"isBackground": false,
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "CMake Build (Debug)",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"f:\\c\\SimpleRayTracer\\build",
|
|
||||||
"--config",
|
|
||||||
"Debug"
|
|
||||||
],
|
|
||||||
"isBackground": false,
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": "build"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
10
README.md
@@ -43,7 +43,7 @@ If you have powershell installed, you can run the build.ps1 script in project ro
|
|||||||
|
|
||||||
### Multiple Importance Sampling (MIS)
|
### Multiple Importance Sampling (MIS)
|
||||||
- Balance heuristic weights BSDF and light sampling PDFs.
|
- Balance heuristic weights BSDF and light sampling PDFs.
|
||||||
- Supports both directional lights and sky light via next-event estimation. Produce noise-free renders with low sample counts.
|
- Supports directional lights, punctual lgiths, and sky light via next-event estimation. Produce noise-free renders with low sample counts.
|
||||||
|
|
||||||
### HDR Sky Lighting
|
### HDR Sky Lighting
|
||||||
- Supports importance sampling of environment maps using a hierarchical CDF over solid angles.
|
- Supports importance sampling of environment maps using a hierarchical CDF over solid angles.
|
||||||
@@ -54,7 +54,7 @@ If you have powershell installed, you can run the build.ps1 script in project ro
|
|||||||
- Faster convergence and lower variance than pure RNG at 64 spp.
|
- Faster convergence and lower variance than pure RNG at 64 spp.
|
||||||
|
|
||||||
### Materials (BSDFs)
|
### Materials (BSDFs)
|
||||||
- Lambertian, and specular supported.
|
- Oren-Naray and Multi-Scattered GGX support
|
||||||
- Designed to align with the OpenPBR material model.
|
- Designed to align with the OpenPBR material model.
|
||||||
|
|
||||||
### Path Tracing
|
### Path Tracing
|
||||||
@@ -68,9 +68,9 @@ If you have powershell installed, you can run the build.ps1 script in project ro
|
|||||||
- [ ] Standardize light unit
|
- [ ] Standardize light unit
|
||||||
- [ ] General speed improvements
|
- [ ] General speed improvements
|
||||||
- [ ] Add GPU backend with CUDA
|
- [ ] Add GPU backend with CUDA
|
||||||
- [ ] Support for glossy microfacet models (GGX)
|
- [x] Support for glossy microfacet models (GGX)
|
||||||
- [ ] Support for better diffuse models (Oren-Nayar)
|
- [x] Support for better diffuse models (Oren-Nayar)
|
||||||
- [ ] Support for volumetric scattering (homogeneous media)
|
- [ ] Support for volumetric scattering (homogeneous media)
|
||||||
- [ ] Light hierarchy for large emitter sets
|
- [ ] Light hierarchy for large emitter sets
|
||||||
- [ ] Better multithreaded rendering
|
- [x] Better multithreaded rendering
|
||||||
- [ ] GUI frontend with real-time control
|
- [ ] GUI frontend with real-time control
|
||||||
|
|||||||
360309
assets/bunny.obj
@@ -1,32 +0,0 @@
|
|||||||
#ifndef MESH_H
|
|
||||||
#define MESH_H
|
|
||||||
|
|
||||||
#include "Material/Material.h"
|
|
||||||
#include "Geometry/Triangle.h"
|
|
||||||
#include "Rendering/Scene.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// TODO: Currently transformation does not work because we store every triangle in to the same buffer and when bulding the bvh, we only consider that triangle buffer.
|
|
||||||
// One solution for this is we can have two levels of bvh, one for scene and one for each mesh. The mesh level bvh will apply the transformation to the triangles.
|
|
||||||
// The scene level bvh only tells the ray which mesh to check and the mesh level bvh will tell the ray which triangle to check.
|
|
||||||
// For instancing, we may need another mesh_model_t struct to store the actual bvh and triangle data(like id and size), and each mesh_entity_t will have a transformation matrix and the id to that mesh_model_t.
|
|
||||||
// This way we can share the same triangle and bvh for multiple instances of the same mesh, and we can also apply different transformations to each instance.
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
mat4s local_to_world;
|
|
||||||
|
|
||||||
// New TLAS/BLAS identifiers.
|
|
||||||
uint32_t model_id;
|
|
||||||
uint32_t instance_id;
|
|
||||||
|
|
||||||
// Legacy fields (kept for now).
|
|
||||||
uint64_t triangle_id;
|
|
||||||
uint64_t triangle_count;
|
|
||||||
uint16_t material_id;
|
|
||||||
uint16_t material_count;
|
|
||||||
} mesh_handle_t;
|
|
||||||
|
|
||||||
mesh_handle_t mesh_load(const char* filename, scene_t* scene);
|
|
||||||
|
|
||||||
#endif // MESH_H
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#ifndef TRIANGLE_H
|
|
||||||
#define TRIANGLE_H
|
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Geometry/AABB.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vec3s position;
|
|
||||||
vec3s normal;
|
|
||||||
vec3s tangent;
|
|
||||||
vec3s color;
|
|
||||||
vec2s uv;
|
|
||||||
} vertex_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vertex_t vertices[3];
|
|
||||||
vec3s face_normal;
|
|
||||||
|
|
||||||
uint8_t material_id;
|
|
||||||
} triangle_t;
|
|
||||||
|
|
||||||
// TODO: Handle material remove, we can use a lookup array.
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint64_t count;
|
|
||||||
uint64_t size;
|
|
||||||
|
|
||||||
triangle_t* buffer;
|
|
||||||
} triangle_collection_t;
|
|
||||||
|
|
||||||
bool triangle_collection_init(size_t size, triangle_collection_t* triangles);
|
|
||||||
void triangle_collection_resize(triangle_collection_t* collection, size_t size);
|
|
||||||
void triangle_collection_free(triangle_collection_t* collection);
|
|
||||||
|
|
||||||
void triangle_create(vertex_t v1, vertex_t v2, vertex_t v3, uint8_t material_id, triangle_collection_t* collection);
|
|
||||||
|
|
||||||
inline vec3s triangle_centroid(const triangle_t triangle)
|
|
||||||
{
|
|
||||||
return glms_vec3_scale(glms_vec3_add(glms_vec3_add(triangle.vertices[0].position, triangle.vertices[1].position), triangle.vertices[2].position), 1.0f / 3.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline aabb_t compute_bounds_triangle(triangle_t triangle)
|
|
||||||
{
|
|
||||||
aabb_t bounds;
|
|
||||||
bounds.min = glms_vec3_minv(triangle.vertices[0].position, glms_vec3_minv(triangle.vertices[1].position, triangle.vertices[2].position));
|
|
||||||
bounds.max = glms_vec3_maxv(triangle.vertices[0].position, glms_vec3_maxv(triangle.vertices[1].position, triangle.vertices[2].position));
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TRIANGLE_H
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
#ifndef LIGHT_H
|
|
||||||
#define LIGHT_H
|
|
||||||
|
|
||||||
#include "Algorithm/BVH.h"
|
|
||||||
#include "Algorithm/Sobol.h"
|
|
||||||
#include "Geometry/Triangle.h"
|
|
||||||
#include "Rendering/Texture.h"
|
|
||||||
#include "cglm/struct/vec3.h"
|
|
||||||
|
|
||||||
struct scene_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vec3s position;
|
|
||||||
vec3s normal;
|
|
||||||
vec3s geometric_normal;
|
|
||||||
vec3s tangent;
|
|
||||||
vec2s uv;
|
|
||||||
vec3s wo;
|
|
||||||
|
|
||||||
uint16_t bounce_depth;
|
|
||||||
|
|
||||||
const struct scene_t* scene;
|
|
||||||
|
|
||||||
const bvh_tree_t* bvh_tree;
|
|
||||||
const texture_collection_t* textures;
|
|
||||||
|
|
||||||
float spread_angle;
|
|
||||||
} light_shading_context_t;
|
|
||||||
|
|
||||||
typedef path_output (*evaluate_bsdf_sky_f) (const void* data, const light_shading_context_t* context, vec3s throughput, uint32_t sample_index);
|
|
||||||
typedef void (*sky_free_f) (void* data);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint16_t data_size;
|
|
||||||
void* data;
|
|
||||||
|
|
||||||
evaluate_bsdf_sky_f evaluate_bsdf_sky;
|
|
||||||
sky_free_f free_sky_data;
|
|
||||||
} sky_light_t;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
LIGHT_TYPE_POINT,
|
|
||||||
LIGHT_TYPE_SPOT,
|
|
||||||
LIGHT_TYPE_AREA,
|
|
||||||
} punctual_light_type_e;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vec3s position;
|
|
||||||
vec3s color;
|
|
||||||
float intensity;
|
|
||||||
punctual_light_type_e type;
|
|
||||||
} punctual_light_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vec3s direction;
|
|
||||||
vec3s color;
|
|
||||||
float intensity;
|
|
||||||
float angular_diameter;
|
|
||||||
} directional_light_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t punctual_light_count;
|
|
||||||
uint32_t directional_light_count;
|
|
||||||
uint32_t max_punctual_lights;
|
|
||||||
uint32_t max_directional_lights;
|
|
||||||
|
|
||||||
sky_light_t sky_light;
|
|
||||||
punctual_light_t* punctual_lights;
|
|
||||||
directional_light_t* directional_lights;
|
|
||||||
} light_collection_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t id;
|
|
||||||
bool is_punctual;
|
|
||||||
} light_entity_t;
|
|
||||||
|
|
||||||
inline bool light_collection_create(uint32_t max_punctual_lights, uint32_t max_directional_lights, light_collection_t* collection)
|
|
||||||
{
|
|
||||||
if (max_punctual_lights == 0 || max_directional_lights == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
collection->max_punctual_lights = max_punctual_lights;
|
|
||||||
collection->max_directional_lights = max_directional_lights;
|
|
||||||
collection->punctual_light_count = 0;
|
|
||||||
collection->directional_light_count = 0;
|
|
||||||
|
|
||||||
collection->punctual_lights = (punctual_light_t*)malloc(max_punctual_lights * sizeof(punctual_light_t));
|
|
||||||
if (collection->punctual_lights == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
collection->directional_lights = (directional_light_t*)malloc(max_directional_lights * sizeof(directional_light_t));
|
|
||||||
if (collection->directional_lights == NULL)
|
|
||||||
{
|
|
||||||
free(collection->punctual_lights);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline light_entity_t light_create_punctual_light(light_collection_t* collection)
|
|
||||||
{
|
|
||||||
if (collection->punctual_light_count >= collection->max_punctual_lights)
|
|
||||||
{
|
|
||||||
return (light_entity_t){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
punctual_light_t light = {0};
|
|
||||||
collection->punctual_lights[collection->punctual_light_count] = light;
|
|
||||||
light_entity_t entity = {.id = collection->punctual_light_count, .is_punctual = true};
|
|
||||||
collection->punctual_light_count++;
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline light_entity_t light_create_directional_light(light_collection_t* collection)
|
|
||||||
{
|
|
||||||
if (collection->directional_light_count >= collection->max_directional_lights)
|
|
||||||
{
|
|
||||||
return (light_entity_t){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
directional_light_t light = {0};
|
|
||||||
collection->directional_lights[collection->directional_light_count] = light;
|
|
||||||
light_entity_t entity = {.id = collection->directional_light_count, .is_punctual = false};
|
|
||||||
collection->directional_light_count++;
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void light_collection_free(light_collection_t* collection)
|
|
||||||
{
|
|
||||||
free(collection->punctual_lights);
|
|
||||||
free(collection->directional_lights);
|
|
||||||
|
|
||||||
if (collection->sky_light.free_sky_data != NULL)
|
|
||||||
{
|
|
||||||
collection->sky_light.free_sky_data(collection->sky_light.data);
|
|
||||||
}
|
|
||||||
free(collection->sky_light.data);
|
|
||||||
|
|
||||||
collection->max_punctual_lights = 0;
|
|
||||||
collection->max_directional_lights = 0;
|
|
||||||
collection->punctual_light_count = 0;
|
|
||||||
collection->directional_light_count = 0;
|
|
||||||
collection->punctual_lights = NULL;
|
|
||||||
collection->directional_lights = NULL;
|
|
||||||
collection->sky_light.data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // LIGHT_H
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef SHADING_CONTEXT_H
|
|
||||||
#define SHADING_CONTEXT_H
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SHADING_CONTEXT_H
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#ifndef SCENE_H
|
|
||||||
#define SCENE_H
|
|
||||||
|
|
||||||
#include "Algorithm/BVH.h"
|
|
||||||
#include "Algorithm/TLAS.h"
|
|
||||||
#include "Camera.h"
|
|
||||||
#include "Lighting/Light.h"
|
|
||||||
#include "Material/Material.h"
|
|
||||||
#include "Geometry/Triangle.h"
|
|
||||||
#include "Rendering/RenderTarget.h"
|
|
||||||
#include "Rendering/Texture.h"
|
|
||||||
|
|
||||||
#include "cglm/struct/mat3.h"
|
|
||||||
#include "cglm/struct/mat4.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
typedef struct scene_t
|
|
||||||
{
|
|
||||||
bool active;
|
|
||||||
triangle_collection_t triangles; // local-space triangles
|
|
||||||
bvh_tree_t blas; // BVH over local-space triangles
|
|
||||||
aabb_t local_bounds;
|
|
||||||
} mesh_model_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool active;
|
|
||||||
uint32_t model_id;
|
|
||||||
|
|
||||||
mat4s local_to_world;
|
|
||||||
mat4s world_to_local;
|
|
||||||
mat3s normal_matrix; // transpose(inverse(mat3(local_to_world)))
|
|
||||||
|
|
||||||
aabb_t world_bounds;
|
|
||||||
} mesh_instance_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t count;
|
|
||||||
uint32_t capacity;
|
|
||||||
mesh_model_t* buffer;
|
|
||||||
} mesh_model_collection_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t count;
|
|
||||||
uint32_t capacity;
|
|
||||||
mesh_instance_t* buffer;
|
|
||||||
} mesh_instance_collection_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
camera_t camera;
|
|
||||||
|
|
||||||
// Legacy: single big triangle array (kept for now for procedural geometry).
|
|
||||||
bvh_tree_t bvh_tree;
|
|
||||||
triangle_collection_t triangles;
|
|
||||||
|
|
||||||
// New: TLAS/BLAS mesh system.
|
|
||||||
mesh_model_collection_t mesh_models;
|
|
||||||
mesh_instance_collection_t mesh_instances;
|
|
||||||
tlas_tree_t tlas;
|
|
||||||
bool tlas_dirty;
|
|
||||||
|
|
||||||
material_collection_t materials;
|
|
||||||
texture_collection_t textures;
|
|
||||||
light_collection_t lights;
|
|
||||||
} scene_t;
|
|
||||||
|
|
||||||
bool scene_init(scene_t* scene, uint64_t triangle_count, uint16_t texture_count, uint8_t material_count, uint32_t punctual_light_count);
|
|
||||||
bool scene_build_bvh(scene_t* scene);
|
|
||||||
void scene_free(scene_t* scene);
|
|
||||||
|
|
||||||
// Mesh model/instance API (simple first, flexible later).
|
|
||||||
uint32_t scene_add_mesh_model(scene_t* scene, uint64_t triangle_reserve);
|
|
||||||
uint32_t scene_add_mesh_instance(scene_t* scene, uint32_t model_id, mat4s local_to_world);
|
|
||||||
void scene_remove_mesh_instance(scene_t* scene, uint32_t instance_id);
|
|
||||||
void scene_set_mesh_instance_transform(scene_t* scene, uint32_t instance_id, mat4s local_to_world);
|
|
||||||
|
|
||||||
#endif // SCENE_H
|
|
||||||
16
managed/SimpleRayTracer/App.xaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Application
|
||||||
|
x:Class="SimpleRayTracer.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:SimpleRayTracer">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||||
|
<!-- Other merged dictionaries here -->
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
<!-- Other app resources here -->
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
50
managed/SimpleRayTracer/App.xaml.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
|
using Microsoft.UI.Xaml.Shapes;
|
||||||
|
using Windows.ApplicationModel;
|
||||||
|
using Windows.ApplicationModel.Activation;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
|
||||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace SimpleRayTracer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
private Window? _window;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
|
/// </summary>
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when the application is launched.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Details about the launch request and process.</param>
|
||||||
|
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
_window = new MainWindow();
|
||||||
|
_window.Activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
managed/SimpleRayTracer/Assets/LockScreenLogo.scale-200.png
Normal file
|
After Width: | Height: | Size: 432 B |
BIN
managed/SimpleRayTracer/Assets/SplashScreen.scale-200.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
managed/SimpleRayTracer/Assets/Square150x150Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
managed/SimpleRayTracer/Assets/Square44x44Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 283 B |
BIN
managed/SimpleRayTracer/Assets/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 456 B |
BIN
managed/SimpleRayTracer/Assets/Wide310x150Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
147
managed/SimpleRayTracer/Interop/InteropSmokeTest.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using Microsoft.UI.Xaml.Media.Imaging;
|
||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SimpleRayTracer.Interop;
|
||||||
|
|
||||||
|
internal sealed partial class InteropSmokeTest : IDisposable
|
||||||
|
{
|
||||||
|
private SrtScene? _scene;
|
||||||
|
private SrtRenderJob? _job;
|
||||||
|
private WriteableBitmap? _bitmap;
|
||||||
|
private byte[]? _scratchBgra;
|
||||||
|
|
||||||
|
public WriteableBitmap Bitmap => _bitmap ?? throw new InvalidOperationException("Not started");
|
||||||
|
|
||||||
|
private static Quaternion FromEulerDegrees(Vector3 degrees)
|
||||||
|
{
|
||||||
|
var radians = degrees * (MathF.PI / 180f);
|
||||||
|
var cy = MathF.Cos(radians.Z * 0.5f);
|
||||||
|
var sy = MathF.Sin(radians.Z * 0.5f);
|
||||||
|
var cp = MathF.Cos(radians.Y * 0.5f);
|
||||||
|
var sp = MathF.Sin(radians.Y * 0.5f);
|
||||||
|
var cr = MathF.Cos(radians.X * 0.5f);
|
||||||
|
var sr = MathF.Sin(radians.X * 0.5f);
|
||||||
|
return new Quaternion
|
||||||
|
{
|
||||||
|
W = cr * cp * cy + sr * sp * sy,
|
||||||
|
X = sr * cp * cy - cr * sp * sy,
|
||||||
|
Y = cr * sp * cy + sr * cp * sy,
|
||||||
|
Z = cr * cp * sy - sr * sp * cy,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartAsync(uint width = 640, uint height = 360)
|
||||||
|
{
|
||||||
|
if (_scene is not null || _job is not null)
|
||||||
|
throw new InvalidOperationException("Already started");
|
||||||
|
|
||||||
|
_scene = SrtScene.Create(triangleCount: 0, textureCount: 1, materialCount: 8, punctualLightCount: 1);
|
||||||
|
|
||||||
|
// Camera similar to native defaults: at (0,0,5) looking towards -Z.
|
||||||
|
_scene.SetCamera(position: new Vector3(-7.5f, 2.5f, 0.0f), rotation: FromEulerDegrees(new Vector3(10, -90, 0)), focalLength: 0.025f, sizeX: 0.036f, aspectRatio: width / (float)height);
|
||||||
|
|
||||||
|
// Basic sky so we don't render into black/undefined environment.
|
||||||
|
_scene.SetSky(SrtSky.Constant(new Vector3(1, 1, 1), intensity: 1.0f));
|
||||||
|
|
||||||
|
// Directional light
|
||||||
|
var lightDir = Vector3.Normalize(new Vector3(0.6f, 1.0f, 0.25f));
|
||||||
|
_scene.AddDirectionalLight(direction: lightDir, color: new Vector3(1.0f, 0.93f, 0.87f), intensity: 2.0f, angularDiameter: 0.53f);
|
||||||
|
|
||||||
|
_scene.LoadMeshFromFile("F:/c/SimpleRayTracer/native/assets/sponza.fbx");
|
||||||
|
_scene.Commit();
|
||||||
|
|
||||||
|
_job = _scene.CreateRenderJob(width: width, height: height, sampleCount: 64, maxDepth: 4, bucketSize: 64, seed: 1);
|
||||||
|
|
||||||
|
_bitmap = new WriteableBitmap((int)width, (int)height);
|
||||||
|
|
||||||
|
// Run renderer on background thread.
|
||||||
|
_ = Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_job.StartBlocking();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// No UI exception throwing from background thread; this is a smoke test.
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Native render failed: {ex}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void CopyLatestToBitmap()
|
||||||
|
{
|
||||||
|
if (_job is null || _bitmap is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensure we have enough capacity
|
||||||
|
var res = SrtNative.srt_render_job_get_aov_desc(_job.Handle, SrtNative.SRT_AOV_BEAUTY_INDEX, out var w, out var h, out _);
|
||||||
|
if (res != SrtNative.Result.Ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((uint)_bitmap.PixelWidth != w || (uint)_bitmap.PixelHeight != h)
|
||||||
|
{
|
||||||
|
// Bitmap size mismatch (shouldn't happen in this smoke test).
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pixelBuffer = _bitmap.PixelBuffer;
|
||||||
|
var expectedBytes = checked(w * h * 4u);
|
||||||
|
if (pixelBuffer.Length < expectedBytes)
|
||||||
|
{
|
||||||
|
// Unexpected: WriteableBitmap pixel buffer is smaller than required.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast path: try raw pointer write (true zero-copy into PixelBuffer).
|
||||||
|
if (WinRtBufferByteAccess.TryGetPointer(pixelBuffer, out var dst) && dst != null)
|
||||||
|
{
|
||||||
|
_job.CopyBeautyBgra8(dst, w * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback: stream write. Still avoids per-frame allocations by reusing a scratch buffer.
|
||||||
|
int n = checked((int)expectedBytes);
|
||||||
|
_scratchBgra ??= new byte[n];
|
||||||
|
if (_scratchBgra.Length != n)
|
||||||
|
{
|
||||||
|
_scratchBgra = new byte[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed (byte* tmp = _scratchBgra)
|
||||||
|
{
|
||||||
|
_job.CopyBeautyBgra8(tmp, w * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var stream = pixelBuffer.AsStream();
|
||||||
|
stream.Position = 0;
|
||||||
|
stream.Write(_scratchBgra, 0, _scratchBgra.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bitmap.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDone
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_job is null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return _job.IsDone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_job?.Dispose();
|
||||||
|
_job = null;
|
||||||
|
|
||||||
|
_scene?.Dispose();
|
||||||
|
_scene = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
295
managed/SimpleRayTracer/Interop/SrtApi.cs
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace SimpleRayTracer.Interop;
|
||||||
|
|
||||||
|
internal sealed class SrtScene : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr Handle { get; private set; }
|
||||||
|
|
||||||
|
public static SrtScene Create(ulong triangleCount, ushort textureCount, byte materialCount, uint punctualLightCount)
|
||||||
|
{
|
||||||
|
var h = SrtNative.srt_scene_create(triangleCount, textureCount, materialCount, punctualLightCount);
|
||||||
|
if (h == IntPtr.Zero)
|
||||||
|
throw new InvalidOperationException("srt_scene_create failed (native DLL not found or init failed)");
|
||||||
|
|
||||||
|
return new SrtScene(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SrtScene(IntPtr handle) => Handle = handle;
|
||||||
|
|
||||||
|
public void SetCamera(Vector3 position, Quaternion rotation, float focalLength, float sizeX, float aspectRatio)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var cam = new SrtNative.CameraParams
|
||||||
|
{
|
||||||
|
position = SrtNative.Vec3.Of(position.X, position.Y, position.Z),
|
||||||
|
rotation = new SrtNative.Quat { x = rotation.X, y = rotation.Y, z = rotation.Z, w = rotation.W },
|
||||||
|
focal_length = focalLength,
|
||||||
|
size_x = sizeX,
|
||||||
|
aspect_ratio = aspectRatio,
|
||||||
|
};
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_camera_set(Handle, &cam));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSky(SrtSky sky)
|
||||||
|
{
|
||||||
|
if (sky is null) throw new ArgumentNullException(nameof(sky));
|
||||||
|
sky.Apply(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint AddDirectionalLight(Vector3 direction, Vector3 color, float intensity, float angularDiameter)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var l = new SrtNative.DirectionalLight
|
||||||
|
{
|
||||||
|
direction = SrtNative.Vec3.Of(direction.X, direction.Y, direction.Z),
|
||||||
|
color = SrtNative.Vec3.Of(color.X, color.Y, color.Z),
|
||||||
|
intensity = intensity,
|
||||||
|
angular_diameter = angularDiameter,
|
||||||
|
};
|
||||||
|
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_add_directional_light(Handle, &l, out var id));
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SrtNative.MaterialHandle CreateStandardLitMaterial(Vector3 albedo, float roughness, float diffuseRoughness, float metallic,
|
||||||
|
SrtNative.TextureHandle albedoTexture, SrtNative.TextureHandle normalTexture, SrtNative.TextureHandle roughnessTexture, SrtNative.TextureHandle metallicTexture,
|
||||||
|
Vector3 emission)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var props = new SrtNative.StandardLitProperties
|
||||||
|
{
|
||||||
|
albedo = SrtNative.Vec3.Of(albedo.X, albedo.Y, albedo.Z),
|
||||||
|
roughness = roughness,
|
||||||
|
diffuse_roughness = diffuseRoughness,
|
||||||
|
metallic = metallic,
|
||||||
|
albedo_texture = albedoTexture,
|
||||||
|
normal_texture = normalTexture,
|
||||||
|
roughness_texture = roughnessTexture,
|
||||||
|
metallic_texture = metallicTexture,
|
||||||
|
};
|
||||||
|
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_create_standard_lit_material(
|
||||||
|
Handle,
|
||||||
|
&props,
|
||||||
|
SrtNative.Vec3.Of(emission.X, emission.Y, emission.Z),
|
||||||
|
out var mat));
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint AddMeshModel(ulong triangleReserve)
|
||||||
|
{
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_add_mesh_model(Handle, triangleReserve, out var id));
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMeshTriangles(uint modelId, ReadOnlySpan<SrtNative.Triangle> triangles)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (SrtNative.Triangle* p = triangles)
|
||||||
|
{
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_mesh_model_set_triangles(Handle, modelId, p, (uint)triangles.Length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint AddMeshInstance(uint modelId, in SrtNative.Mat4 localToWorld)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (SrtNative.Mat4* p = &localToWorld)
|
||||||
|
{
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_add_mesh_instance(Handle, modelId, p, out var instanceId));
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Commit() => ThrowIfNotOk(SrtNative.srt_scene_commit(Handle));
|
||||||
|
|
||||||
|
public SrtNative.TextureHandle LoadTextureFromFile(string path, bool srgb = true, bool mipmap = true, SrtNative.TextureStride stride = SrtNative.TextureStride.UInt8)
|
||||||
|
{
|
||||||
|
if (path is null) throw new ArgumentNullException(nameof(path));
|
||||||
|
path = ResolveAssetPath(path);
|
||||||
|
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_texture_load(
|
||||||
|
Handle,
|
||||||
|
path,
|
||||||
|
srgb: (byte)(srgb ? 1 : 0),
|
||||||
|
mipmap: (byte)(mipmap ? 1 : 0),
|
||||||
|
stride: (uint)stride,
|
||||||
|
out var tex));
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SrtNative.MeshHandle LoadMeshFromFile(string path)
|
||||||
|
{
|
||||||
|
if (path is null) throw new ArgumentNullException(nameof(path));
|
||||||
|
path = ResolveAssetPath(path);
|
||||||
|
|
||||||
|
ThrowIfNotOk(SrtNative.srt_scene_load_mesh(Handle, path, out var mesh));
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveAssetPath(string path)
|
||||||
|
{
|
||||||
|
if (Path.IsPathRooted(path))
|
||||||
|
return path;
|
||||||
|
|
||||||
|
// Prefer app base directory (WinUI packaged/unpackaged), then fall back to CWD.
|
||||||
|
var baseDir = AppContext.BaseDirectory;
|
||||||
|
var candidate = Path.GetFullPath(Path.Combine(baseDir, path));
|
||||||
|
if (File.Exists(candidate))
|
||||||
|
return candidate;
|
||||||
|
|
||||||
|
candidate = Path.GetFullPath(path);
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SrtRenderJob CreateRenderJob(uint width, uint height, uint sampleCount, byte maxDepth, uint bucketSize, uint seed,
|
||||||
|
uint aovFlags = SrtNative.SRT_AOV_BEAUTY, uint renderingMode = SrtNative.SRT_RENDER_TILE_BASED)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var cfg = new SrtNative.RenderingConfig
|
||||||
|
{
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
sample_count = sampleCount,
|
||||||
|
max_depth = maxDepth,
|
||||||
|
bucket_size = bucketSize,
|
||||||
|
};
|
||||||
|
|
||||||
|
ThrowIfNotOk(SrtNative.srt_render_job_create(Handle, &cfg, aovFlags, renderingMode, seed, out var job));
|
||||||
|
return new SrtRenderJob(job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Handle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
SrtNative.srt_scene_destroy(Handle);
|
||||||
|
Handle = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ThrowIfNotOk(SrtNative.Result r)
|
||||||
|
{
|
||||||
|
if (r != SrtNative.Result.Ok)
|
||||||
|
throw new InvalidOperationException($"Native call failed: {r}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class SrtRenderJob : IDisposable
|
||||||
|
{
|
||||||
|
public IntPtr Handle { get; private set; }
|
||||||
|
|
||||||
|
internal SrtRenderJob(IntPtr handle) => Handle = handle;
|
||||||
|
|
||||||
|
public void StartBlocking() => SrtScene.ThrowIfNotOk(SrtNative.srt_render_job_start(Handle));
|
||||||
|
|
||||||
|
public bool IsDone
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var r = SrtNative.srt_render_job_is_done(Handle, out var done);
|
||||||
|
return r == SrtNative.Result.Ok && done != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void CopyBeautyBgra8(byte* dst, uint dstStrideBytes)
|
||||||
|
{
|
||||||
|
_ = SrtNative.srt_render_job_copy_aov_bgra8(Handle, SrtNative.SRT_AOV_BEAUTY_INDEX, dst, dstStrideBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Handle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
SrtNative.srt_render_job_request_stop(Handle);
|
||||||
|
SrtNative.srt_render_job_destroy(Handle);
|
||||||
|
Handle = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class SrtSky
|
||||||
|
{
|
||||||
|
internal abstract unsafe void Apply(SrtScene scene);
|
||||||
|
|
||||||
|
public static SrtSky None() => new NoneSky();
|
||||||
|
public static SrtSky Constant(Vector3 color, float intensity) => new ConstantSky(color, intensity);
|
||||||
|
public static SrtSky Hdr(SrtNative.TextureHandle hdri, float intensity) => new HdrSky(hdri, intensity);
|
||||||
|
|
||||||
|
private sealed class NoneSky : SrtSky
|
||||||
|
{
|
||||||
|
internal override unsafe void Apply(SrtScene scene)
|
||||||
|
{
|
||||||
|
var desc = new SrtNative.SkyDesc { kind = (uint)SrtNative.SkyKind.None, data_size = 0, data = null };
|
||||||
|
SrtScene.ThrowIfNotOk(SrtNative.srt_scene_set_sky(scene.Handle, &desc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ConstantSky : SrtSky
|
||||||
|
{
|
||||||
|
private readonly Vector3 _color;
|
||||||
|
private readonly float _intensity;
|
||||||
|
|
||||||
|
public ConstantSky(Vector3 color, float intensity)
|
||||||
|
{
|
||||||
|
_color = color;
|
||||||
|
_intensity = intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override unsafe void Apply(SrtScene scene)
|
||||||
|
{
|
||||||
|
var cd = new SrtNative.SkyConstantDesc
|
||||||
|
{
|
||||||
|
color = SrtNative.Vec3.Of(_color.X, _color.Y, _color.Z),
|
||||||
|
intensity = _intensity,
|
||||||
|
};
|
||||||
|
var desc = new SrtNative.SkyDesc
|
||||||
|
{
|
||||||
|
kind = (uint)SrtNative.SkyKind.Constant,
|
||||||
|
data_size = (uint)sizeof(SrtNative.SkyConstantDesc),
|
||||||
|
data = &cd,
|
||||||
|
};
|
||||||
|
SrtScene.ThrowIfNotOk(SrtNative.srt_scene_set_sky(scene.Handle, &desc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class HdrSky : SrtSky
|
||||||
|
{
|
||||||
|
private readonly SrtNative.TextureHandle _hdri;
|
||||||
|
private readonly float _intensity;
|
||||||
|
|
||||||
|
public HdrSky(SrtNative.TextureHandle hdri, float intensity)
|
||||||
|
{
|
||||||
|
_hdri = hdri;
|
||||||
|
_intensity = intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override unsafe void Apply(SrtScene scene)
|
||||||
|
{
|
||||||
|
var hd = new SrtNative.SkyHdrDesc { hdri = _hdri, intensity = _intensity };
|
||||||
|
var desc = new SrtNative.SkyDesc
|
||||||
|
{
|
||||||
|
kind = (uint)SrtNative.SkyKind.Hdr,
|
||||||
|
data_size = (uint)sizeof(SrtNative.SkyHdrDesc),
|
||||||
|
data = &hd,
|
||||||
|
};
|
||||||
|
SrtScene.ThrowIfNotOk(SrtNative.srt_scene_set_sky(scene.Handle, &desc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
278
managed/SimpleRayTracer/Interop/SrtNative.cs
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace SimpleRayTracer.Interop;
|
||||||
|
|
||||||
|
internal static unsafe class SrtNative
|
||||||
|
{
|
||||||
|
private const string _DLL = "SimpleRayTracerNative";
|
||||||
|
|
||||||
|
internal enum Result : int
|
||||||
|
{
|
||||||
|
Ok = 0,
|
||||||
|
Error = 1,
|
||||||
|
InvalidArgument = 2,
|
||||||
|
OutOfRange = 3,
|
||||||
|
OutOfCapacity = 4,
|
||||||
|
NotFound = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct Vec2
|
||||||
|
{
|
||||||
|
public float x, y;
|
||||||
|
|
||||||
|
public static Vec2 Of(float x, float y) => new() { x = x, y = y };
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct Vec3
|
||||||
|
{
|
||||||
|
public float x, y, z;
|
||||||
|
|
||||||
|
public static Vec3 Of(float x, float y, float z) => new() { x = x, y = y, z = z };
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct Quat
|
||||||
|
{
|
||||||
|
public float x, y, z, w;
|
||||||
|
|
||||||
|
public static Quat Identity() => new() { w = 1f };
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct Mat4
|
||||||
|
{
|
||||||
|
// Column-major float[16]
|
||||||
|
public fixed float m[16];
|
||||||
|
|
||||||
|
public static Mat4 Identity()
|
||||||
|
{
|
||||||
|
var r = new Mat4();
|
||||||
|
r.m[0] = 1;
|
||||||
|
r.m[5] = 1;
|
||||||
|
r.m[10] = 1;
|
||||||
|
r.m[15] = 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct CameraParams
|
||||||
|
{
|
||||||
|
public Vec3 position;
|
||||||
|
public Quat rotation;
|
||||||
|
|
||||||
|
public float focal_length;
|
||||||
|
public float size_x;
|
||||||
|
public float aspect_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct DirectionalLight
|
||||||
|
{
|
||||||
|
public Vec3 direction;
|
||||||
|
public Vec3 color;
|
||||||
|
public float intensity;
|
||||||
|
public float angular_diameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct TextureHandle
|
||||||
|
{
|
||||||
|
public uint id;
|
||||||
|
public uint generation;
|
||||||
|
|
||||||
|
public static TextureHandle Invalid() => new() { id = 0xFFFFFFFF, generation = 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct MaterialHandle
|
||||||
|
{
|
||||||
|
public byte id;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct StandardLitProperties
|
||||||
|
{
|
||||||
|
public Vec3 albedo;
|
||||||
|
public float diffuse_roughness;
|
||||||
|
public float roughness;
|
||||||
|
public float metallic;
|
||||||
|
|
||||||
|
public TextureHandle albedo_texture;
|
||||||
|
public TextureHandle normal_texture;
|
||||||
|
public TextureHandle roughness_texture;
|
||||||
|
public TextureHandle metallic_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum TextureWrapMode : uint
|
||||||
|
{
|
||||||
|
Repeat = 0,
|
||||||
|
Clamp = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum TextureFilterMode : uint
|
||||||
|
{
|
||||||
|
Nearest = 0,
|
||||||
|
Linear = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum TextureStride : uint
|
||||||
|
{
|
||||||
|
UInt8 = 1,
|
||||||
|
UInt16 = 2,
|
||||||
|
Float32 = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct RenderingConfig
|
||||||
|
{
|
||||||
|
public uint width;
|
||||||
|
public uint height;
|
||||||
|
public uint sample_count;
|
||||||
|
public byte max_depth;
|
||||||
|
public uint bucket_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct Vertex
|
||||||
|
{
|
||||||
|
public Vec3 position;
|
||||||
|
public Vec3 normal;
|
||||||
|
public Vec3 tangent;
|
||||||
|
public Vec3 color;
|
||||||
|
public Vec2 uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct Triangle
|
||||||
|
{
|
||||||
|
public Vertex v0;
|
||||||
|
public Vertex v1;
|
||||||
|
public Vertex v2;
|
||||||
|
public uint material_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct MeshHandle
|
||||||
|
{
|
||||||
|
public uint model_id;
|
||||||
|
public uint instance_id;
|
||||||
|
|
||||||
|
public ulong triangle_id;
|
||||||
|
public ulong triangle_count;
|
||||||
|
public ushort material_id;
|
||||||
|
public ushort material_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum SkyKind : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Constant = 1,
|
||||||
|
Hdr = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct SkyDesc
|
||||||
|
{
|
||||||
|
public uint kind;
|
||||||
|
public uint data_size;
|
||||||
|
public void* data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct SkyConstantDesc
|
||||||
|
{
|
||||||
|
public Vec3 color;
|
||||||
|
public float intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct SkyHdrDesc
|
||||||
|
{
|
||||||
|
public TextureHandle hdri;
|
||||||
|
public float intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern IntPtr srt_scene_create(ulong triangle_count, ushort texture_count, byte material_count, uint punctual_light_count);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern void srt_scene_destroy(IntPtr scene);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_commit(IntPtr scene);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_camera_set(IntPtr scene, CameraParams* @params);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_add_directional_light(IntPtr scene, DirectionalLight* light, out uint id);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_create_standard_lit_material(IntPtr scene, StandardLitProperties* props, Vec3 emission, out MaterialHandle mat);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_texture_load(IntPtr scene, [MarshalAs(UnmanagedType.LPUTF8Str)] string filename, byte srgb, byte mipmap, uint stride, out TextureHandle texture);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_texture_set_sampler(IntPtr scene, TextureHandle texture, uint wrapMode, uint filterMode);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_set_sky_none(IntPtr scene);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_set_sky(IntPtr scene, SkyDesc* desc);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_set_sky_constant(IntPtr scene, Vec3 color, float intensity);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_set_sky_hdr(IntPtr scene, TextureHandle hdri, float intensity);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_add_mesh_model(IntPtr scene, ulong triangle_reserve, out uint model_id);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_mesh_model_set_triangles(IntPtr scene, uint model_id, Triangle* triangles, uint triangle_count);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_add_mesh_instance(IntPtr scene, uint model_id, Mat4* local_to_world, out uint instance_id);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_scene_load_mesh(IntPtr scene, [MarshalAs(UnmanagedType.LPUTF8Str)] string filename_utf8, out MeshHandle mesh);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_render_job_create(
|
||||||
|
IntPtr scene,
|
||||||
|
RenderingConfig* config,
|
||||||
|
uint aov_flags,
|
||||||
|
uint rendering_mode,
|
||||||
|
uint seed,
|
||||||
|
out IntPtr job);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern void srt_render_job_destroy(IntPtr job);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_render_job_start(IntPtr job);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern void srt_render_job_request_stop(IntPtr job);
|
||||||
|
|
||||||
|
// C bool is 1 byte; use byte to avoid marshaling mismatches.
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_render_job_is_done(IntPtr job, out byte done);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_render_job_get_aov_desc(IntPtr job, uint aov_index, out uint width, out uint height, out uint strideBytes);
|
||||||
|
|
||||||
|
[DllImport(_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern Result srt_render_job_copy_aov_bgra8(IntPtr job, uint aov_index, byte* dst, uint dstStrideBytes);
|
||||||
|
|
||||||
|
internal const uint SRT_AOV_BEAUTY = 1u << 0;
|
||||||
|
internal const uint SRT_RENDER_TILE_BASED = 1;
|
||||||
|
internal const uint SRT_AOV_BEAUTY_INDEX = 0;
|
||||||
|
}
|
||||||
93
managed/SimpleRayTracer/Interop/WinRtBufferByteAccess.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Windows.Storage.Streams;
|
||||||
|
using WinRT;
|
||||||
|
|
||||||
|
namespace SimpleRayTracer.Interop;
|
||||||
|
|
||||||
|
// Allows zero-copy access to WriteableBitmap.PixelBuffer.
|
||||||
|
internal static class WinRtBufferByteAccess
|
||||||
|
{
|
||||||
|
private static readonly Guid IID_IBufferByteAccess = new("905a0fef-bc53-11df-8c49-001e4fc686da");
|
||||||
|
|
||||||
|
public static unsafe bool TryGetPointer(IBuffer buffer, out byte* ptr)
|
||||||
|
{
|
||||||
|
ptr = null;
|
||||||
|
if (buffer is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var unk = IntPtr.Zero;
|
||||||
|
var releaseUnk = false;
|
||||||
|
|
||||||
|
var acc = IntPtr.Zero;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (buffer is not IWinRTObject winrt)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unk = winrt.NativeObject.ThisPtr;
|
||||||
|
if (unk == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.AddRef(unk);
|
||||||
|
releaseUnk = true;
|
||||||
|
|
||||||
|
var iid = IID_IBufferByteAccess;
|
||||||
|
var hr = Marshal.QueryInterface(unk, in iid, out acc);
|
||||||
|
if (hr < 0 || acc == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vtable: [0]=QI, [1]=AddRef, [2]=Release, [3]=Buffer
|
||||||
|
var vtbl = *(IntPtr*)acc;
|
||||||
|
var bufferFnPtr = *((IntPtr*)vtbl + 3);
|
||||||
|
if (bufferFnPtr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPORTANT: COM uses stdcall on Windows.
|
||||||
|
var bufferFn = (delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, int>)bufferFnPtr;
|
||||||
|
|
||||||
|
var raw = IntPtr.Zero;
|
||||||
|
hr = bufferFn(acc, &raw);
|
||||||
|
if (hr < 0 || raw == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = (byte*)raw;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (acc != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.Release(acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (releaseUnk && unk != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.Release(unk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe byte* GetPointerOrThrow(IBuffer buffer)
|
||||||
|
{
|
||||||
|
if (!TryGetPointer(buffer, out var ptr))
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("WriteableBitmap.PixelBuffer does not expose IBufferByteAccess in this configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
managed/SimpleRayTracer/MainWindow.xaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Window
|
||||||
|
x:Class="SimpleRayTracer.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:SimpleRayTracer"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="SimpleRayTracer">
|
||||||
|
|
||||||
|
<Window.SystemBackdrop>
|
||||||
|
<MicaBackdrop />
|
||||||
|
</Window.SystemBackdrop>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="12" Margin="12">
|
||||||
|
<Button x:Name="RunSmokeTestButton" Content="Run Interop Smoke Test" Click="RunSmokeTestButton_Click" />
|
||||||
|
<TextBlock x:Name="StatusText" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<ScrollViewer Grid.Row="1" Margin="12">
|
||||||
|
<Image x:Name="RenderImage" Stretch="Uniform" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
62
managed/SimpleRayTracer/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.UI.Dispatching;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using SimpleRayTracer.Interop;
|
||||||
|
|
||||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace SimpleRayTracer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty window that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
private InteropSmokeTest? _smoke;
|
||||||
|
private DispatcherQueueTimer? _timer;
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunSmokeTestButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
RunSmokeTestButton.IsEnabled = false;
|
||||||
|
StatusText.Text = "Starting...";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_timer?.Stop();
|
||||||
|
_timer = null;
|
||||||
|
|
||||||
|
_smoke?.Dispose();
|
||||||
|
_smoke = new InteropSmokeTest();
|
||||||
|
|
||||||
|
_smoke.StartAsync(width: 640, height: 360);
|
||||||
|
|
||||||
|
RenderImage.Source = _smoke.Bitmap;
|
||||||
|
StatusText.Text = "Rendering...";
|
||||||
|
|
||||||
|
_timer = DispatcherQueue.CreateTimer();
|
||||||
|
_timer.Interval = TimeSpan.FromMilliseconds(33);
|
||||||
|
_timer.Tick += (_, _) =>
|
||||||
|
{
|
||||||
|
_smoke?.CopyLatestToBitmap();
|
||||||
|
if (_smoke?.IsDone == true)
|
||||||
|
{
|
||||||
|
StatusText.Text = "Done";
|
||||||
|
_timer?.Stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_timer.Start();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
StatusText.Text = ex.Message;
|
||||||
|
RunSmokeTestButton.IsEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
managed/SimpleRayTracer/Package.appxmanifest
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||||
|
IgnorableNamespaces="uap rescap">
|
||||||
|
|
||||||
|
<Identity
|
||||||
|
Name="f3ab7e56-7fa5-4a20-a3e7-94cab61bcb0d"
|
||||||
|
Publisher="CN=Misaki"
|
||||||
|
Version="1.0.0.0" />
|
||||||
|
|
||||||
|
<mp:PhoneIdentity PhoneProductId="f3ab7e56-7fa5-4a20-a3e7-94cab61bcb0d" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>SimpleRayTracer</DisplayName>
|
||||||
|
<PublisherDisplayName>Misaki</PublisherDisplayName>
|
||||||
|
<Logo>Assets\StoreLogo.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||||
|
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate"/>
|
||||||
|
</Resources>
|
||||||
|
|
||||||
|
<Applications>
|
||||||
|
<Application Id="App"
|
||||||
|
Executable="$targetnametoken$.exe"
|
||||||
|
EntryPoint="$targetentrypoint$">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="SimpleRayTracer"
|
||||||
|
Description="SimpleRayTracer"
|
||||||
|
BackgroundColor="transparent"
|
||||||
|
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||||
|
Square44x44Logo="Assets\Square44x44Logo.png">
|
||||||
|
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
|
||||||
|
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<rescap:Capability Name="runFullTrust" />
|
||||||
|
</Capabilities>
|
||||||
|
</Package>
|
||||||
10
managed/SimpleRayTracer/Properties/launchSettings.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"SimpleRayTracer (Package)": {
|
||||||
|
"commandName": "MsixPackage"
|
||||||
|
},
|
||||||
|
"SimpleRayTracer (Unpackaged)": {
|
||||||
|
"commandName": "Project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
77
managed/SimpleRayTracer/SimpleRayTracer.csproj
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net10.0-windows10.0.19041.0</TargetFramework>
|
||||||
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||||
|
<RootNamespace>SimpleRayTracer</RootNamespace>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<Platforms>x86;x64;ARM64</Platforms>
|
||||||
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||||
|
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
|
||||||
|
<UseWinUI>true</UseWinUI>
|
||||||
|
<WinUISDKReferences>false</WinUISDKReferences>
|
||||||
|
<EnableMsixTooling>true</EnableMsixTooling>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Assets\SplashScreen.scale-200.png" />
|
||||||
|
<Content Include="Assets\LockScreenLogo.scale-200.png" />
|
||||||
|
<Content Include="Assets\Square150x150Logo.scale-200.png" />
|
||||||
|
<Content Include="Assets\Square44x44Logo.scale-200.png" />
|
||||||
|
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||||
|
<Content Include="Assets\StoreLogo.png" />
|
||||||
|
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Manifest Include="$(ApplicationManifest)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
|
||||||
|
<PackageReference Include="WinUIEx" Version="2.9.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
|
||||||
|
Tools extension to be activated for this project even if the Windows App SDK Nuget
|
||||||
|
package has not yet been restored.
|
||||||
|
-->
|
||||||
|
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||||
|
<ProjectCapability Include="Msix" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
|
||||||
|
Explorer "Package and Publish" context menu entry to be enabled for this project even if
|
||||||
|
the Windows App SDK Nuget package has not yet been restored.
|
||||||
|
-->
|
||||||
|
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||||
|
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Publish Properties -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
|
||||||
|
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
|
||||||
|
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
|
||||||
|
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\..\build\bin\$(Configuration)\SimpleRayTracerNative.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="..\..\build\bin\$(Configuration)\cglm.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="..\..\build\bin\$(Configuration)\assimp-vc143-mt.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
13
managed/SimpleRayTracer/SimpleRayTracer.slnx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<Solution>
|
||||||
|
<Configurations>
|
||||||
|
<Platform Name="ARM64" />
|
||||||
|
<Platform Name="x64" />
|
||||||
|
<Platform Name="x86" />
|
||||||
|
</Configurations>
|
||||||
|
<Project Path="SimpleRayTracer.csproj">
|
||||||
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
<Platform Solution="*|x86" Project="x86" />
|
||||||
|
<Deploy />
|
||||||
|
</Project>
|
||||||
|
</Solution>
|
||||||
19
managed/SimpleRayTracer/app.manifest
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="SimpleRayTracer.app"/>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10.
|
||||||
|
It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
|
||||||
|
For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
</assembly>
|
||||||
7
native/.clangd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
CompileFlags:
|
||||||
|
Add:
|
||||||
|
- -IF:/c/SimpleRayTracer/native/external
|
||||||
|
- -IF:/c/SimpleRayTracer/native/header
|
||||||
|
- -LF:/c/SimpleRayTracer/native/lib
|
||||||
|
- -lcglm
|
||||||
|
- -lassimp-vc143-mt
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 23)
|
||||||
set(PROJECT_NAME SimpleRayTracer)
|
set(PROJECT_NAME SimpleRayTracer)
|
||||||
|
|
||||||
project(${PROJECT_NAME} LANGUAGES C)
|
project(${PROJECT_NAME} LANGUAGES C)
|
||||||
@@ -16,12 +16,25 @@ set(LIBRARY_PATH "${CMAKE_SOURCE_DIR}/lib")
|
|||||||
# Recursively find all .c files in the Sources directory
|
# Recursively find all .c files in the Sources directory
|
||||||
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "${SOURCE_DIR}/*.c")
|
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "${SOURCE_DIR}/*.c")
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} WIN32 ${SOURCES})
|
# App sources (exclude interop exports; those live in the Native DLL)
|
||||||
|
set(APP_SOURCES ${SOURCES})
|
||||||
|
list(FILTER APP_SOURCES EXCLUDE REGEX ".*/Interop/SrtInterop\\.c$")
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} WIN32 ${APP_SOURCES})
|
||||||
|
|
||||||
|
# Native DLL for C# interop (keeps existing exe target intact)
|
||||||
|
set(NATIVE_SOURCES ${SOURCES})
|
||||||
|
# Exclude the app entrypoint from the DLL
|
||||||
|
list(FILTER NATIVE_SOURCES EXCLUDE REGEX ".*/[Mm]ain\\.c$")
|
||||||
|
add_library(${PROJECT_NAME}Native SHARED ${NATIVE_SOURCES})
|
||||||
|
|
||||||
# Include directories
|
# Include directories
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${EXTERNAL_DIR})
|
target_include_directories(${PROJECT_NAME} PRIVATE ${EXTERNAL_DIR})
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${HEADER_DIR})
|
target_include_directories(${PROJECT_NAME} PRIVATE ${HEADER_DIR})
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME}Native PRIVATE ${EXTERNAL_DIR})
|
||||||
|
target_include_directories(${PROJECT_NAME}Native PRIVATE ${HEADER_DIR})
|
||||||
|
|
||||||
# Define imported target for cglm
|
# Define imported target for cglm
|
||||||
add_library(cglm_shared SHARED IMPORTED)
|
add_library(cglm_shared SHARED IMPORTED)
|
||||||
set_target_properties(cglm_shared PROPERTIES
|
set_target_properties(cglm_shared PROPERTIES
|
||||||
@@ -43,17 +56,29 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
|
|||||||
assimp_shared
|
assimp_shared
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}Native PRIVATE
|
||||||
|
cglm_shared
|
||||||
|
assimp_shared
|
||||||
|
)
|
||||||
|
|
||||||
# target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRARY_PATH}/cglm.lib)
|
# target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRARY_PATH}/cglm.lib)
|
||||||
# target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRARY_PATH}/assimp-vc143-mt.lib)
|
# target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRARY_PATH}/assimp-vc143-mt.lib)
|
||||||
|
|
||||||
if(OpenMP_C_FOUND)
|
if(OpenMP_C_FOUND)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenMP::OpenMP_C)
|
target_link_libraries(${PROJECT_NAME} PRIVATE OpenMP::OpenMP_C)
|
||||||
|
target_link_libraries(${PROJECT_NAME}Native PRIVATE OpenMP::OpenMP_C)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set_target_properties(${PROJECT_NAME}Native PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(${PROJECT_NAME}Native PRIVATE SRT_INTEROP_BUILD=1)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${PROJECT_NAME} POST_BUILD
|
TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
@@ -63,6 +88,15 @@ if(WIN32)
|
|||||||
VERBATIM
|
VERBATIM
|
||||||
COMMAND_EXPAND_LISTS
|
COMMAND_EXPAND_LISTS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${PROJECT_NAME}Native POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
$<TARGET_RUNTIME_DLLS:${PROJECT_NAME}Native>
|
||||||
|
$<TARGET_FILE_DIR:${PROJECT_NAME}Native>
|
||||||
|
VERBATIM
|
||||||
|
COMMAND_EXPAND_LISTS
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
BIN
native/assets/hdri/hansaplatz_1k.hdr
Normal file
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |