From a2b7543086542af1813c2190825cd2e733653b15 Mon Sep 17 00:00:00 2001 From: Alexey Smolenchuk Date: Mon, 24 Aug 2026 00:06:53 +0100 Subject: [PATCH 1/6] fix fov, add named camera spaces Signed-off-by: Alexey Smolenchuk --- src/testrender/cuda/optix_raytracer.cu | 4 ++ src/testrender/optixraytracer.cpp | 25 ++++++- src/testrender/optixraytracer.h | 3 + src/testrender/raytracer.h | 7 +- src/testrender/simpleraytracer.cpp | 97 +++++++++++++++----------- src/testrender/simpleraytracer.h | 12 ++-- 6 files changed, 97 insertions(+), 51 deletions(-) diff --git a/src/testrender/cuda/optix_raytracer.cu b/src/testrender/cuda/optix_raytracer.cu index c102d25dc..985a7810d 100644 --- a/src/testrender/cuda/optix_raytracer.cu +++ b/src/testrender/cuda/optix_raytracer.cu @@ -245,6 +245,10 @@ __raygen__setglobals() OSL::pvt::test_str_2 = render_params.test_str_2; } + OSL::pvt::num_named_xforms = render_params.num_named_xforms; + OSL::pvt::xform_name_buffer = render_params.xform_name_buffer; + OSL::pvt::xform_buffer = render_params.xform_buffer; + if (render_params.bg_id < 0) return; diff --git a/src/testrender/optixraytracer.cpp b/src/testrender/optixraytracer.cpp index 5f6037a8c..b62346447 100644 --- a/src/testrender/optixraytracer.cpp +++ b/src/testrender/optixraytracer.cpp @@ -114,6 +114,8 @@ OptixRaytracer::OptixRaytracer() CUDA_CHECK(cudaSetDevice(0)); CUDA_CHECK(cudaStreamCreate(&m_cuda_stream)); + + cache = OIIO::ImageCache::create (); } @@ -930,7 +932,7 @@ OptixRaytracer::get_texture_handle(ustring filename, auto itr = m_samplers.find(filename); if (itr == m_samplers.end()) { // Open image to check the number of mip levels - OIIO::ImageBuf image; + OIIO::ImageBuf image(filename, 0, 0, cache); if (!image.init_spec(filename, 0, 0)) { errhandler().errorfmt("Could not load: {} (hash {})", filename, filename); @@ -1092,6 +1094,27 @@ OptixRaytracer::render(int xres OSL_MAYBE_UNUSED, int yres OSL_MAYBE_UNUSED) params.test_str_1 = test_str_1; params.test_str_2 = test_str_2; + // Named transforms + int nxforms = m_named_xforms.size(); + params.num_named_xforms = nxforms; + params.xform_name_buffer = DEVICE_ALLOC(sizeof(ustringhash)*nxforms); + params.xform_buffer = DEVICE_ALLOC(sizeof(Transformation)*nxforms); + + std::vector names; + std::vector xforms; + names.reserve(nxforms); + xforms.reserve(nxforms); + + for (auto &pair : m_named_xforms) + { + names.push_back(pair.first); + xforms.push_back(*pair.second); + } + + COPY_TO_DEVICE(params.xform_name_buffer, names.data(), sizeof(ustringhash)*nxforms); + COPY_TO_DEVICE(params.xform_buffer, xforms.data(), sizeof(Transformation)*nxforms); + CUDA_SYNC_CHECK(); + // Mesh data params.verts = d_vertices; params.triangles = d_vert_indices; diff --git a/src/testrender/optixraytracer.h b/src/testrender/optixraytracer.h index 420c8de03..bd336b4a9 100644 --- a/src/testrender/optixraytracer.h +++ b/src/testrender/optixraytracer.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include @@ -144,6 +145,8 @@ class OptixRaytracer final : public SimpleRaytracer { // CUdeviceptrs that need to be freed after we are done std::vector m_ptrs_to_free; std::vector m_arrays_to_free; + + std::shared_ptr cache; }; diff --git a/src/testrender/raytracer.h b/src/testrender/raytracer.h index eef7f2a3e..ec78d7370 100644 --- a/src/testrender/raytracer.h +++ b/src/testrender/raytracer.h @@ -135,8 +135,9 @@ struct Camera { { float k = OIIO::fast_tan(fov * float(M_PI / 360)); Vec3 right = dir.cross(up).normalize(); - cx = right * (xres * k / yres); - cy = (cx.cross(dir)).normalize() * k; + // fov is horizontal + cx = right * k; + cy = (cx.cross(dir)).normalize() * k * yres / xres; } // Get a ray for the given screen coordinates. @@ -147,7 +148,7 @@ struct Camera { // components with magnitudes slightly greater than 1.0, which can cause // downstream computations to blow up and produce NaNs. Normalizing the // vector again avoids this issue. - const Vec3 v = (cx * (x * invw - 0.5f) + cy * (0.5f - y * invh) + dir) + const Vec3 v = (cx * (x * invw - 0.5f) * 2.f + cy * (0.5f - y * invh) * 2.f + dir) #ifndef __CUDACC__ .normalize(); #else diff --git a/src/testrender/simpleraytracer.cpp b/src/testrender/simpleraytracer.cpp index 0f1258be9..22b8d46f1 100644 --- a/src/testrender/simpleraytracer.cpp +++ b/src/testrender/simpleraytracer.cpp @@ -332,6 +332,7 @@ SimpleRaytracer::parse_scene_xml(const std::string& scenefile) if (fov_attr) fov = OIIO::Strutil::from_string(fov_attr.value()); + m_fov = fov; camera.lookat(eye, dir, up, fov); } else if (strcmp(node.name(), "Sphere") == 0) { // load sphere @@ -506,6 +507,60 @@ SimpleRaytracer::parse_scene_xml(const std::string& scenefile) if (scene.num_prims() == 0) errhandler().severefmt("No primitives in scene"); camera.finalize(); + prepare_camera_spaces(); +} + + + +void +SimpleRaytracer::prepare_camera_spaces() +{ + Vec3 right = camera.cx.normalized(); + Vec3 up = camera.cy.normalized(); + + Matrix44 camera_to_world = {right.x, right.y, right.z, 0, + up.x, up.y, up.z, 0, + camera.dir.x, camera.dir.y, camera.dir.z, 0, + camera.eye.x, camera.eye.y, camera.eye.z, 1}; + + name_transform("camera", camera_to_world ); + + // Seems never used once moved to named transforms + m_world_to_camera = camera_to_world.inverse(); + Matrix44 M = m_world_to_camera; + float depthrange = (double)m_yon-(double)m_hither; + if (m_projection == RS::Hashes::perspective) { + float tanhalffov = tanf (0.5f * m_fov * M_PI/180.0); + Matrix44 camera_to_screen (1/tanhalffov, 0, 0, 0, + 0, 1/tanhalffov, 0, 0, + 0, 0, m_yon/depthrange, 1, + 0, 0, -m_yon*m_hither/depthrange, 0); + M = M * camera_to_screen; + } else { + Matrix44 camera_to_screen (1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1/depthrange, 0, + 0, 0, -m_hither/depthrange, 1); + M = M * camera_to_screen; + } + name_transform("screen", M.inverse() ); + + float aspect = (float)camera.yres / (float)camera.xres; + float screenleft = -1.0, screenwidth = 2.0; + float screenbottom = -1.0*aspect, screenheight = 2.0*aspect; + Matrix44 screen_to_ndc (1/screenwidth, 0, 0, 0, + 0, 1/screenheight, 0, 0, + 0, 0, 1, 0, + -screenleft/screenwidth, -screenbottom/screenheight, 0, 1); + M = M * screen_to_ndc; + name_transform("NDC", M.inverse() ); + + Matrix44 ndc_to_raster (camera.xres, 0, 0, 0, + 0, camera.yres, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + M = M * ndc_to_raster; + name_transform("raster", M.inverse() ); } @@ -577,48 +632,6 @@ bool SimpleRaytracer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, ustringhash to, float /*time*/) { - if (to == OSL::Hashes::camera || to == OSL::Hashes::screen - || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { - // clang-format off - Matrix44 M = m_world_to_camera; - if (to == OSL::Hashes::screen || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { - float depthrange = (double)m_yon-(double)m_hither; - if (m_projection == RS::Hashes::perspective) { - float tanhalffov = tanf (0.5f * m_fov * M_PI/180.0); - Matrix44 camera_to_screen (1/tanhalffov, 0, 0, 0, - 0, 1/tanhalffov, 0, 0, - 0, 0, m_yon/depthrange, 1, - 0, 0, -m_yon*m_hither/depthrange, 0); - M = M * camera_to_screen; - } else { - Matrix44 camera_to_screen (1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1/depthrange, 0, - 0, 0, -m_hither/depthrange, 1); - M = M * camera_to_screen; - } - if (to == OSL::Hashes::NDC || to == RS::Hashes::raster) { - float screenleft = -1.0, screenwidth = 2.0; - float screenbottom = -1.0, screenheight = 2.0; - Matrix44 screen_to_ndc (1/screenwidth, 0, 0, 0, - 0, 1/screenheight, 0, 0, - 0, 0, 1, 0, - -screenleft/screenwidth, -screenbottom/screenheight, 0, 1); - M = M * screen_to_ndc; - if (to == RS::Hashes::raster) { - Matrix44 ndc_to_raster (camera.xres, 0, 0, 0, - 0, camera.yres, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - M = M * ndc_to_raster; - } - } - } - // clang-format on - result = M; - return true; - } - TransformMap::const_iterator found = m_named_xforms.find(to); if (found != m_named_xforms.end()) { result = *(found->second); diff --git a/src/testrender/simpleraytracer.h b/src/testrender/simpleraytracer.h index 124266eca..14bc42049 100644 --- a/src/testrender/simpleraytracer.h +++ b/src/testrender/simpleraytracer.h @@ -85,6 +85,7 @@ class SimpleRaytracer : public RendererServices { float yon, int xres, int yres); virtual void parse_scene_xml(const std::string& scenefile); + virtual void prepare_camera_spaces(); virtual void prepare_render(); void prepare_lights(); void prepare_geometry(); @@ -113,7 +114,7 @@ class SimpleRaytracer : public RendererServices { int getBackgroundShaderID() const { return backgroundShaderID; } int getBackgroundResolution() const { return backgroundResolution; } -private: +protected: // Camera parameters Matrix44 m_world_to_camera; ustringhash m_projection; @@ -121,6 +122,11 @@ class SimpleRaytracer : public RendererServices { float m_shutter[2]; float m_screen_window[4]; + // Named transforms + typedef std::map> TransformMap; + TransformMap m_named_xforms; + +private: int backgroundShaderID = -1; int backgroundResolution = 1024; int aa = 1; @@ -140,10 +146,6 @@ class SimpleRaytracer : public RendererServices { std::unique_ptr m_errhandler; bool m_had_error = false; - // Named transforms - typedef std::map> TransformMap; - TransformMap m_named_xforms; - // Attribute and userdata retrieval -- for fast dispatch, use a hash // table to map attribute names to functions that retrieve them. We // imagine this to be fairly quick, but for a performance-critical From 6d928bcce0d61a826baf398ae2d3156b3fcd7f76 Mon Sep 17 00:00:00 2001 From: Alexey Smolenchuk Date: Mon, 24 Aug 2026 00:34:00 +0100 Subject: [PATCH 2/6] format Signed-off-by: Alexey Smolenchuk --- src/testrender/optixraytracer.cpp | 17 +++++++++-------- src/testrender/optixraytracer.h | 3 ++- src/testrender/raytracer.h | 7 ++++--- src/testrender/simpleraytracer.cpp | 30 ++++++++++++++++-------------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/testrender/optixraytracer.cpp b/src/testrender/optixraytracer.cpp index b62346447..8d5bb9158 100644 --- a/src/testrender/optixraytracer.cpp +++ b/src/testrender/optixraytracer.cpp @@ -115,7 +115,7 @@ OptixRaytracer::OptixRaytracer() CUDA_CHECK(cudaSetDevice(0)); CUDA_CHECK(cudaStreamCreate(&m_cuda_stream)); - cache = OIIO::ImageCache::create (); + cache = OIIO::ImageCache::create (); } @@ -1095,24 +1095,25 @@ OptixRaytracer::render(int xres OSL_MAYBE_UNUSED, int yres OSL_MAYBE_UNUSED) params.test_str_2 = test_str_2; // Named transforms - int nxforms = m_named_xforms.size(); + int nxforms = m_named_xforms.size(); params.num_named_xforms = nxforms; - params.xform_name_buffer = DEVICE_ALLOC(sizeof(ustringhash)*nxforms); - params.xform_buffer = DEVICE_ALLOC(sizeof(Transformation)*nxforms); + params.xform_name_buffer = DEVICE_ALLOC(sizeof(ustringhash) * nxforms); + params.xform_buffer = DEVICE_ALLOC(sizeof(Transformation) * nxforms); std::vector names; std::vector xforms; names.reserve(nxforms); xforms.reserve(nxforms); - for (auto &pair : m_named_xforms) - { + for (auto &pair : m_named_xforms) { names.push_back(pair.first); xforms.push_back(*pair.second); } - COPY_TO_DEVICE(params.xform_name_buffer, names.data(), sizeof(ustringhash)*nxforms); - COPY_TO_DEVICE(params.xform_buffer, xforms.data(), sizeof(Transformation)*nxforms); + COPY_TO_DEVICE(params.xform_name_buffer, names.data(), + sizeof(ustringhash)*nxforms); + COPY_TO_DEVICE(params.xform_buffer, xforms.data(), + sizeof(Transformation)*nxforms); CUDA_SYNC_CHECK(); // Mesh data diff --git a/src/testrender/optixraytracer.h b/src/testrender/optixraytracer.h index bd336b4a9..6ddd0fc3b 100644 --- a/src/testrender/optixraytracer.h +++ b/src/testrender/optixraytracer.h @@ -4,8 +4,9 @@ #pragma once -#include #include +#include + #include diff --git a/src/testrender/raytracer.h b/src/testrender/raytracer.h index ec78d7370..425da43b5 100644 --- a/src/testrender/raytracer.h +++ b/src/testrender/raytracer.h @@ -136,8 +136,8 @@ struct Camera { float k = OIIO::fast_tan(fov * float(M_PI / 360)); Vec3 right = dir.cross(up).normalize(); // fov is horizontal - cx = right * k; - cy = (cx.cross(dir)).normalize() * k * yres / xres; + cx = right * k; + cy = (cx.cross(dir)).normalize() * k * yres / xres; } // Get a ray for the given screen coordinates. @@ -148,7 +148,8 @@ struct Camera { // components with magnitudes slightly greater than 1.0, which can cause // downstream computations to blow up and produce NaNs. Normalizing the // vector again avoids this issue. - const Vec3 v = (cx * (x * invw - 0.5f) * 2.f + cy * (0.5f - y * invh) * 2.f + dir) + const Vec3 v = (cx * (x * invw - 0.5f) * 2.f + + cy * (0.5f - y * invh) * 2.f + dir) #ifndef __CUDACC__ .normalize(); #else diff --git a/src/testrender/simpleraytracer.cpp b/src/testrender/simpleraytracer.cpp index 22b8d46f1..0710750f9 100644 --- a/src/testrender/simpleraytracer.cpp +++ b/src/testrender/simpleraytracer.cpp @@ -518,49 +518,51 @@ SimpleRaytracer::prepare_camera_spaces() Vec3 right = camera.cx.normalized(); Vec3 up = camera.cy.normalized(); - Matrix44 camera_to_world = {right.x, right.y, right.z, 0, - up.x, up.y, up.z, 0, - camera.dir.x, camera.dir.y, camera.dir.z, 0, - camera.eye.x, camera.eye.y, camera.eye.z, 1}; + Matrix44 camera_to_world = { right.x, right.y, right.z, 0, + up.x, up.y, up.z, 0, + camera.dir.x, camera.dir.y, camera.dir.z, 0, + camera.eye.x, camera.eye.y, camera.eye.z, 1 }; - name_transform("camera", camera_to_world ); + name_transform("camera", camera_to_world); // Seems never used once moved to named transforms m_world_to_camera = camera_to_world.inverse(); - Matrix44 M = m_world_to_camera; - float depthrange = (double)m_yon-(double)m_hither; + Matrix44 M = m_world_to_camera; + float depthrange = (double)m_yon - (double)m_hither; + // clang-format off if (m_projection == RS::Hashes::perspective) { float tanhalffov = tanf (0.5f * m_fov * M_PI/180.0); - Matrix44 camera_to_screen (1/tanhalffov, 0, 0, 0, + Matrix44 camera_to_screen ( 1/tanhalffov, 0, 0, 0, 0, 1/tanhalffov, 0, 0, 0, 0, m_yon/depthrange, 1, 0, 0, -m_yon*m_hither/depthrange, 0); M = M * camera_to_screen; } else { - Matrix44 camera_to_screen (1, 0, 0, 0, + Matrix44 camera_to_screen ( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1/depthrange, 0, 0, 0, -m_hither/depthrange, 1); M = M * camera_to_screen; } - name_transform("screen", M.inverse() ); + name_transform("screen", M.inverse()); - float aspect = (float)camera.yres / (float)camera.xres; + float aspect = (float)camera.yres / (float)camera.xres; float screenleft = -1.0, screenwidth = 2.0; - float screenbottom = -1.0*aspect, screenheight = 2.0*aspect; + float screenbottom = -1.0 * aspect, screenheight = 2.0 * aspect; Matrix44 screen_to_ndc (1/screenwidth, 0, 0, 0, 0, 1/screenheight, 0, 0, 0, 0, 1, 0, -screenleft/screenwidth, -screenbottom/screenheight, 0, 1); M = M * screen_to_ndc; - name_transform("NDC", M.inverse() ); + name_transform("NDC", M.inverse()); Matrix44 ndc_to_raster (camera.xres, 0, 0, 0, 0, camera.yres, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); M = M * ndc_to_raster; - name_transform("raster", M.inverse() ); + name_transform("raster", M.inverse()); + // clang-format on } From 8e70b154808ecc935ecbd84eeed69dd9f693cb00 Mon Sep 17 00:00:00 2001 From: Alexey Smolenchuk Date: Mon, 24 Aug 2026 00:48:30 +0100 Subject: [PATCH 3/6] remove cache for now Signed-off-by: Alexey Smolenchuk --- src/testrender/optixraytracer.cpp | 4 +--- src/testrender/optixraytracer.h | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/testrender/optixraytracer.cpp b/src/testrender/optixraytracer.cpp index 8d5bb9158..d0309dfae 100644 --- a/src/testrender/optixraytracer.cpp +++ b/src/testrender/optixraytracer.cpp @@ -114,8 +114,6 @@ OptixRaytracer::OptixRaytracer() CUDA_CHECK(cudaSetDevice(0)); CUDA_CHECK(cudaStreamCreate(&m_cuda_stream)); - - cache = OIIO::ImageCache::create (); } @@ -932,7 +930,7 @@ OptixRaytracer::get_texture_handle(ustring filename, auto itr = m_samplers.find(filename); if (itr == m_samplers.end()) { // Open image to check the number of mip levels - OIIO::ImageBuf image(filename, 0, 0, cache); + OIIO::ImageBuf image; if (!image.init_spec(filename, 0, 0)) { errhandler().errorfmt("Could not load: {} (hash {})", filename, filename); diff --git a/src/testrender/optixraytracer.h b/src/testrender/optixraytracer.h index 6ddd0fc3b..420c8de03 100644 --- a/src/testrender/optixraytracer.h +++ b/src/testrender/optixraytracer.h @@ -4,10 +4,8 @@ #pragma once -#include #include - #include #include @@ -146,8 +144,6 @@ class OptixRaytracer final : public SimpleRaytracer { // CUdeviceptrs that need to be freed after we are done std::vector m_ptrs_to_free; std::vector m_arrays_to_free; - - std::shared_ptr cache; }; From d3e0290760c68b64c011dc0a2251835014c660b7 Mon Sep 17 00:00:00 2001 From: Alexey Smolenchuk Date: Mon, 24 Aug 2026 03:16:35 +0100 Subject: [PATCH 4/6] update fov in xml scenes Signed-off-by: Alexey Smolenchuk --- testsuite/render-background/scene.xml | 2 +- testsuite/render-bumptest/bumptest.xml | 2 +- testsuite/render-bunny/bunny.xml | 2 +- testsuite/render-cornell/cornell.xml | 2 +- testsuite/render-displacement/scene.xml | 2 +- testsuite/render-furnace-diffuse/scene.xml | 2 +- testsuite/render-microfacet/scene.xml | 2 +- testsuite/render-mx-anisotropic-vdf/scene.xml | 2 +- testsuite/render-mx-burley-diffuse/scene.xml | 2 +- testsuite/render-mx-conductor/scene.xml | 2 +- testsuite/render-mx-dielectric-glass/scene.xml | 2 +- testsuite/render-mx-dielectric/scene.xml | 2 +- testsuite/render-mx-furnace-burley-diffuse/scene.xml | 2 +- testsuite/render-mx-furnace-oren-nayar/scene.xml | 2 +- testsuite/render-mx-furnace-sheen/scene.xml | 2 +- testsuite/render-mx-generalized-schlick-glass/scene.xml | 2 +- testsuite/render-mx-generalized-schlick/scene.xml | 2 +- testsuite/render-mx-layer/scene.xml | 2 +- testsuite/render-mx-medium-vdf-glass/scene.xml | 2 +- testsuite/render-mx-medium-vdf/scene.xml | 2 +- testsuite/render-mx-sheen/scene.xml | 2 +- testsuite/render-oren-nayar/scene.xml | 2 +- testsuite/render-raytypes/scene.xml | 2 +- testsuite/render-spi-thinlayer/scene.xml | 2 +- testsuite/render-uv/scene.xml | 2 +- testsuite/render-veachmis/veach.xml | 2 +- testsuite/render-ward/scene.xml | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/testsuite/render-background/scene.xml b/testsuite/render-background/scene.xml index 3e7028ef8..92ff05893 100644 --- a/testsuite/render-background/scene.xml +++ b/testsuite/render-background/scene.xml @@ -1,5 +1,5 @@ - + string filename "../common/textures/kitchen_probe.hdr"; diff --git a/testsuite/render-bumptest/bumptest.xml b/testsuite/render-bumptest/bumptest.xml index 6b78db75f..64079da45 100644 --- a/testsuite/render-bumptest/bumptest.xml +++ b/testsuite/render-bumptest/bumptest.xml @@ -1,5 +1,5 @@ - +