From 107990c1a117bd91cf5b920d756dbf663ff48434 Mon Sep 17 00:00:00 2001 From: Cyrille Pierre Henri Favreau Date: Wed, 17 Jan 2024 11:26:35 +0100 Subject: [PATCH 1/2] Fixed focal distance widget --- .../pythonsdk/bioexplorer/notebook_widgets.py | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py b/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py index 1ea52148b..775b9f46b 100644 --- a/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py +++ b/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py @@ -272,31 +272,31 @@ def __init__(self, client, with_preview): self._widget_value = None self._x = 0.5 self._y = 0.5 - self._aperture = 0.0 - self._focus_radius = 0.01 - self._focus_distance = 0.0 - self._nb_focus_points = 20 + self._aperture_radius = 0.0 + self._focal_radius = 0.01 + self._focal_distance = 0.0 + self._nb_focal_points = 20 self._snapshot = None self._with_preview = with_preview def _update_camera(self): - self._focus_distance = 1e6 - for _ in range(self._nb_focus_points): - self._focus_distance = min( - self._focus_distance, + self._focal_distance = 1e6 + for _ in range(self._nb_focal_points): + self._focal_distance = min( + self._focal_distance, self._get_focal_distance( ( - self._x + random.random() * self._focus_radius, - self._y + random.random() * self._focus_radius, + self._x + random.random() * self._focal_radius, + self._y + random.random() * self._focal_radius, ) ), ) params = self._client.PerspectiveCameraParams() - params.focus_distance = self._focus_distance - params.aperture_radius = self._aperture + params.focal_distance = self._focal_distance + params.aperture_radius = self._aperture_radius params.enable_clipping_planes = True - d_slider.value = self._focus_distance + d_slider.value = self._focal_distance self._client.set_camera_params(params) if self._with_preview: @@ -317,16 +317,16 @@ def update_target(self): self._client.set_camera(target=position) self._client.set_renderer() - def update_focus_radius(self, val_dict) -> None: + def update_focal_radius(self, val_dict) -> None: """Update camera focus radius""" self._widget_value = val_dict["new"] - self._focus_radius = self._widget_value + self._focal_radius = self._widget_value self._update_camera() - def update_aperture(self, val_dict) -> None: + def update_aperture_radius(self, val_dict) -> None: """Update camera aperture""" self._widget_value = val_dict["new"] - self._aperture = self._widget_value + self._aperture_radius = self._widget_value self._update_camera() def update_x(self, val_dict) -> None: @@ -372,8 +372,8 @@ def _get_preview(self, update_image): x = self._x * size[0] y = (1.0 - self._y) * size[1] - rx = self._focus_radius * size[0] - ry = self._focus_radius * size[1] + rx = self._focal_radius * size[0] + ry = self._focal_radius * size[1] byte_io = io.BytesIO() snapshot = self._snapshot.copy() draw = ImageDraw.Draw(snapshot) @@ -392,11 +392,11 @@ def update_x(value): def update_y(value): update_class.update_y(value) - def update_aperture(value): - update_class.update_aperture(value) + def update_aperture_radius(value): + update_class.update_aperture_radius(value) - def update_focus_radius(value): - update_class.update_focus_radius(value) + def update_focal_radius(value): + update_class.update_focal_radius(value) def update_button(_): update_class.update() @@ -406,8 +406,8 @@ def update_target(_): x_slider.observe(update_x, "value") y_slider.observe(update_y, "value") - a_slider.observe(update_aperture, "value") - f_slider.observe(update_focus_radius, "value") + a_slider.observe(update_aperture_radius, "value") + f_slider.observe(update_focal_radius, "value") f_button.on_click(update_button) f_target.on_click(update_target) From 1fb835c07128e33dfff2c2c1928cc8aa3c3d9513 Mon Sep 17 00:00:00 2001 From: Cyrille Pierre Henri Favreau Date: Wed, 17 Jan 2024 11:30:06 +0100 Subject: [PATCH 2/2] Renaming of widget methods --- .../MediaMaker/module/cuda/renderer/Albedo.cu | 1 + .../module/cuda/renderer/AmbientOcclusion.cu | 1 + .../MediaMaker/module/cuda/renderer/Depth.cu | 1 + .../module/cuda/renderer/GeometryNormal.cu | 2 + .../module/cuda/renderer/Radiance.cu | 2 + .../module/cuda/renderer/ShadingNormal.cu | 2 + .../MediaMaker/module/cuda/renderer/Shadow.cu | 1 + .../pythonsdk/bioexplorer/notebook_widgets.py | 38 +- .../widgets/BioExplorer_widgets.ipynb | 16 +- bioexplorer/pythonsdk/tests/test_widgets.py | 10 +- .../module/cuda/renderer/BlackHole.cu | 2 + .../dicom/module/cuda/renderer/DICOM.cu | 2 + .../notebooks/NuclearFusion.ipynb | 584 +++++++++--------- platform/engines/optix6/OptiXCommonStructs.h | 1 + platform/engines/optix6/OptiXContext.h | 1 + platform/engines/optix6/OptiXEngine.cpp | 7 +- platform/engines/optix6/OptiXFrameBuffer.cpp | 11 +- platform/engines/optix6/OptiXFrameBuffer.h | 12 +- platform/engines/optix6/OptiXRenderer.cpp | 38 +- platform/engines/optix6/OptiXRenderer.h | 3 + platform/engines/optix6/cuda/Context.cuh | 1 + .../optix6/cuda/camera/AnaglyphCamera.cu | 39 +- .../optix6/cuda/camera/OrthographicCamera.cu | 2 + .../optix6/cuda/camera/PerspectiveCamera.cu | 26 +- .../engines/optix6/cuda/renderer/Advanced.cu | 6 +- .../engines/optix6/cuda/renderer/Basic.cu | 3 + platform/engines/ospray/OSPRayRenderer.cpp | 3 + .../ospray/ispc/render/AdvancedRenderer.ispc | 2 +- 28 files changed, 461 insertions(+), 356 deletions(-) diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Albedo.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Albedo.cu index 26deec111..05782f4c1 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Albedo.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Albedo.cu @@ -86,6 +86,7 @@ static __device__ inline void shade(bool textured) } prd.result = make_float4(color, opacity); + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/AmbientOcclusion.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/AmbientOcclusion.cu index 34ad374c7..ed3c869d1 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/AmbientOcclusion.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/AmbientOcclusion.cu @@ -95,6 +95,7 @@ static __device__ inline void shade() } prd.result = make_float4(::optix::clamp(color, 0.f, 1.f), opacity); + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Depth.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Depth.cu index c7d7b7511..46cf725d0 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Depth.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Depth.cu @@ -30,6 +30,7 @@ static __device__ inline void shade() const float3 hit_point = ray.origin + t_hit * ray.direction; const float depth = 1.f - ::optix::length(eye - hit_point) / infinity; prd.result = make_float4(make_float3(depth), 1.f); + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/GeometryNormal.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/GeometryNormal.cu index cb62a6f1d..0aec14385 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/GeometryNormal.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/GeometryNormal.cu @@ -27,6 +27,8 @@ static __device__ inline void shade() { const float3 world_geometric_normal = optix::normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, geometric_normal)); prd.result = make_float4(0.5 + 0.5 * world_geometric_normal, 1.f); + const float3 hit_point = ray.origin + t_hit * ray.direction; + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Radiance.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Radiance.cu index d609a4256..d9dd4e9b4 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Radiance.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Radiance.cu @@ -26,6 +26,8 @@ static __device__ inline void shade() { prd.result = make_float4(Ka, 1.f); + const float3 hit_point = ray.origin + t_hit * ray.direction; + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/ShadingNormal.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/ShadingNormal.cu index ebb4acf62..f66f9c020 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/ShadingNormal.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/ShadingNormal.cu @@ -27,6 +27,8 @@ static __device__ inline void shade() { const float3 world_shading_normal = optix::normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shading_normal)); prd.result = make_float4(0.5 + 0.5 * world_shading_normal, 1.f); + const float3 hit_point = ray.origin + t_hit * ray.direction; + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Shadow.cu b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Shadow.cu index 71d749160..932fd1e9b 100644 --- a/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Shadow.cu +++ b/bioexplorer/backend/plugins/MediaMaker/module/cuda/renderer/Shadow.cu @@ -81,6 +81,7 @@ static __device__ inline void shade() } attenuation = ::optix::clamp(attenuation / float(shadowSamples), 0.f, 1.f); prd.result = make_float4(make_float3(attenuation), 1.f); + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py b/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py index 775b9f46b..c08279952 100644 --- a/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py +++ b/bioexplorer/pythonsdk/bioexplorer/notebook_widgets.py @@ -252,14 +252,14 @@ def __init__(self, bioexplorer): self._be = bioexplorer self._client = bioexplorer.core_api() - def display_focal_distance(self, with_preview=False): + def focal_distance(self, with_preview=False): """Display visual controls for setting camera focal distance""" - x_slider = FloatSlider(description="X", min=0, max=1, value=0.5) - y_slider = FloatSlider(description="Y", min=0, max=1, value=0.5) - a_slider = FloatSlider(description="Aperture", min=0, max=1, value=0) - f_slider = FloatSlider(description="Focus radius", min=0, max=1, value=0.01) + x_slider = FloatSlider(description="X", min=0.0, max=1.0, value=0.5) + y_slider = FloatSlider(description="Y", min=0.0, max=1.0, value=0.5) + a_slider = FloatSlider(description="Aperture", min=0.0, max=10.0, value=0.0) + f_slider = FloatSlider(description="Focus radius", min=0.0, max=1.0, value=0.01) d_slider = FloatSlider( - description="Focus distance", min=0, max=10000, value=0, disabled=True + description="Focus distance", min=0.0, max=10000.0, value=0.0, disabled=True ) f_button = Button(description="Refresh") f_target = Button(description="Target") @@ -423,7 +423,7 @@ def update_target(_): preview = Image(value=byte_io.getvalue(), format="png", width=1, height=1) display(preview) - def display_palette_for_models(self): + def model_material(self): """Display visual controls for color palettes applied to models""" def set_colormap(model_id, colormap_name, shading_mode): material_ids = self._be.get_material_ids(model_id)["ids"] @@ -546,7 +546,7 @@ def update_materials_from_chameleon_modes(_): ) display(vertical_box) - def display_model_visibility(self): + def model_visibility(self): """Display visual controls for setting visibility of models""" model_names = list() for model in self._client.scene.models: @@ -640,7 +640,7 @@ def adjust_camera(event): hbox = HBox([model_select, hbox_params], layout=Widgets.DEFAULT_GRID_LAYOUT) display(hbox) - def display_model_focus(self, max_number_of_instances=1e6): + def model_focus(self, max_number_of_instances=1e6): """Display visual controls for setting visibility of models""" directions = dict() directions["front"] = Vector3(0, 0, -1) @@ -699,7 +699,7 @@ def focus_on_instance(event): display(vbox) - def __display_advanced_settings(self, object_type, threaded): + def __advanced_settings(self, object_type, threaded): """Display visual controls for camera or renderer advanced settings""" class Updated: """Inner class that insures communication with the remote server""" @@ -845,15 +845,15 @@ def _create_widgets(self): hbox = VBox(vboxes, layout=Widgets.DEFAULT_GRID_LAYOUT) display(hbox) - def display_advanced_rendering_settings(self, is_threaded=True): + def advanced_rendering_settings(self, is_threaded=True): """Display visual controls for renderer advanced settings""" - self.__display_advanced_settings("renderer", is_threaded) + self.__advanced_settings("renderer", is_threaded) - def display_advanced_camera_settings(self, is_threaded=True): + def advanced_camera_settings(self, is_threaded=True): """Display visual controls for camera advanced settings""" - self.__display_advanced_settings("camera", is_threaded) + self.__advanced_settings("camera", is_threaded) - def display_rendering_settings(self): + def rendering_settings(self): """Display visual controls for renderer settings""" def update_params(_): """Update renderer params""" @@ -906,7 +906,7 @@ def update_params(_): ) display(VBox([hbox_1, hbox_2], layout=Widgets.DEFAULT_GRID_LAYOUT)) - def display_environment_maps(self, folder): + def environment_maps(self, folder): """Display visual controls for setting environment map""" supported_extensions = ["jpg", "jpeg", "png"] hdri_files = list() @@ -925,7 +925,7 @@ def update_envmap(value): cb_names.observe(update_envmap, "value") display(cb_names) - def show_amino_acid_on_protein( + def protein_amino_acids( self, assembly_name, name, sequence_id=0, palette_name="Set1", palette_size=2 ): """ @@ -969,7 +969,7 @@ def update_slider(value): display(irs) display(lbl) - def display_clipping_planes(self, value_range=[0, 128]): + def clipping_planes(self, value_range=[0, 128]): """ Add and manipulate clip planes in a 3D space @@ -1058,7 +1058,7 @@ def update_z(value): hbox = HBox([w_x, w_y, w_z], layout=Widgets.DEFAULT_GRID_LAYOUT) display(hbox) - def display_model_transformation(self, model_id): + def model_transformation(self, model_id): """ Manipulate and transform models within a 3D scene diff --git a/bioexplorer/pythonsdk/notebooks/widgets/BioExplorer_widgets.ipynb b/bioexplorer/pythonsdk/notebooks/widgets/BioExplorer_widgets.ipynb index 7373d22a1..cf48e868b 100644 --- a/bioexplorer/pythonsdk/notebooks/widgets/BioExplorer_widgets.ipynb +++ b/bioexplorer/pythonsdk/notebooks/widgets/BioExplorer_widgets.ipynb @@ -27,7 +27,7 @@ "metadata": {}, "outputs": [], "source": [ - "w.display_palette_for_models()" + "w.model_material()" ] }, { @@ -38,7 +38,7 @@ }, "outputs": [], "source": [ - "w.display_focal_distance(with_preview=True)" + "w.focal_distance(with_preview=False)" ] }, { @@ -47,7 +47,7 @@ "metadata": {}, "outputs": [], "source": [ - "w.display_model_visibility()" + "w.model_visibility()" ] }, { @@ -56,7 +56,7 @@ "metadata": {}, "outputs": [], "source": [ - "w.display_advanced_camera_settings()" + "w.advanced_camera_settings()" ] }, { @@ -68,8 +68,8 @@ "outputs": [], "source": [ "be.core_api().set_renderer(current='advanced')\n", - "w.display_rendering_settings()\n", - "w.display_advanced_rendering_settings()" + "w.rendering_settings()\n", + "w.advanced_rendering_settings()" ] }, { @@ -78,7 +78,7 @@ "metadata": {}, "outputs": [], "source": [ - "w.display_model_focus(max_number_of_instances=10)" + "w.model_focus(max_number_of_instances=10)" ] }, { @@ -87,7 +87,7 @@ "metadata": {}, "outputs": [], "source": [ - "w.display_clipping_planes([-50, 50])" + "w.clipping_planes([-50, 50])" ] } ], diff --git a/bioexplorer/pythonsdk/tests/test_widgets.py b/bioexplorer/pythonsdk/tests/test_widgets.py index 9ee3922af..5b9401bcc 100644 --- a/bioexplorer/pythonsdk/tests/test_widgets.py +++ b/bioexplorer/pythonsdk/tests/test_widgets.py @@ -29,23 +29,23 @@ def test_widgets_environment_maps(): - widgets.display_environment_maps('') + widgets.environment_maps('') def test_widgets_advanced_camera_settings(): - widgets.display_advanced_camera_settings(is_threaded=False) + widgets.advanced_camera_settings(is_threaded=False) def test_widgets_display_rendering_settings(): - widgets.display_rendering_settings() + widgets.rendering_settings() def test_widgets_advanced_rendering_settings(): - widgets.display_advanced_rendering_settings(is_threaded=False) + widgets.advanced_rendering_settings(is_threaded=False) def test_widgets_focal_distance(): - widgets.display_focal_distance() + widgets.focal_distance() if __name__ == '__main__': diff --git a/extensions/cosmology/blackhole/module/cuda/renderer/BlackHole.cu b/extensions/cosmology/blackhole/module/cuda/renderer/BlackHole.cu index 7fd796748..b50ff652b 100644 --- a/extensions/cosmology/blackhole/module/cuda/renderer/BlackHole.cu +++ b/extensions/cosmology/blackhole/module/cuda/renderer/BlackHole.cu @@ -217,6 +217,8 @@ static __device__ inline void shade() outCol = make_float4(make_float3(col) + make_float3(glow) * (col.w + glow.w), 1.f); prd.result = ::optix::clamp(outCol, 0.f, 1.f); + const float3 hit_point = ray.origin + t_hit * ray.direction; + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() diff --git a/extensions/medicalimaging/dicom/module/cuda/renderer/DICOM.cu b/extensions/medicalimaging/dicom/module/cuda/renderer/DICOM.cu index 176545b02..f935b1099 100644 --- a/extensions/medicalimaging/dicom/module/cuda/renderer/DICOM.cu +++ b/extensions/medicalimaging/dicom/module/cuda/renderer/DICOM.cu @@ -261,6 +261,7 @@ static __device__ void dicomShade(const bool textured) // Final result prd.result = make_float4(result, 1.f); + prd.zDepth = z; } RT_PROGRAM void any_hit_shadow() @@ -282,4 +283,5 @@ RT_PROGRAM void closest_hit_radiance_textured() RT_PROGRAM void exception() { output_buffer[launch_index] = make_color(make_float4(0.f, 1.f, 0.f, 1.f)); + depth_buffer[launch_index] = INFINITY; } diff --git a/extensions/physics/nuclearfusion/notebooks/NuclearFusion.ipynb b/extensions/physics/nuclearfusion/notebooks/NuclearFusion.ipynb index a33e6400a..4698e9020 100644 --- a/extensions/physics/nuclearfusion/notebooks/NuclearFusion.ipynb +++ b/extensions/physics/nuclearfusion/notebooks/NuclearFusion.ipynb @@ -1,293 +1,293 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "faad71d7", - "metadata": {}, - "source": [ - "# Nuclear Fusion Tokamak\n", - "![](./nuclearfusion_banner.png)" - ] - }, - { - "cell_type": "markdown", - "id": "9abd82ad", - "metadata": {}, - "source": [ - "### Connect to BioExplorer backend" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ecf1c452", - "metadata": {}, - "outputs": [], - "source": [ - "from bioexplorer import BioExplorer, Vector3\n", - "\n", - "be = BioExplorer('localhost:5000')\n", - "core = be.core_api()\n", - "be.reset_scene()\n", - "print('BioExplorer version ' + be.version())" - ] - }, - { - "cell_type": "markdown", - "id": "0ba057d7", - "metadata": {}, - "source": [ - "### Generate random data set:\n", - "Vectors composed of a position and a direction. The length of the vector is the value of the voltage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ce421549", - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "import random\n", - "import numpy as np\n", - "import time\n", - "\n", - "''' Settings '''\n", - "nb_particles = 2000\n", - "use_randomness = True\n", - "\n", - "def generate_random_point_in_torus(main_radius, tube_radius):\n", - " theta = 2 * math.pi * random.random()\n", - " phi = 2 * math.pi * random.random()\n", - " x = (main_radius + tube_radius * math.cos(phi)) * math.cos(theta)\n", - " y = tube_radius * math.sin(phi)\n", - " z = (main_radius + tube_radius * math.cos(phi)) * math.sin(theta)\n", - " return x, y, z\n", - "\n", - "origins = list()\n", - "targets = list()\n", - "origins_radii = list()\n", - "targets_radii = list()\n", - "\n", - "seed = int(time.time())\n", - "random.seed(seed)\n", - "for i in range(nb_particles):\n", - " x = 0\n", - " y = 0\n", - " z = 0\n", - " x, y, z = generate_random_point_in_torus(10.0, 2.0)\n", - " origin = Vector3(x, y ,z)\n", - " \n", - "\n", - " length = 0.2\n", - " cp = np.cross([x, y, z], [0, 1, 0])\n", - " if use_randomness:\n", - " cp[0] += (random.random() - 0.5)\n", - " cp[1] += (random.random() - 0.5)\n", - " cp[2] += (random.random() - 0.5)\n", - " length = random.random() * 0.2\n", - "\n", - " target = Vector3(\n", - " origin.x + cp[0] * length,\n", - " origin.y + cp[1] * length,\n", - " origin.z + cp[2] * length\n", - " )\n", - " origins.append(origin)\n", - " targets.append(target)\n", - " origins_radii.append(0.1)\n", - " targets_radii.append(0.0)\n", - "\n", - "status = be.add_cones(\n", - " name='Particles',\n", - " origins=origins, origins_radii=origins_radii,\n", - " targets=targets, targets_radii=targets_radii,\n", - " color=Vector3(1.0, 1.0, 1.0), opacity=1.0)" - ] - }, - { - "cell_type": "markdown", - "id": "5a21827f", - "metadata": {}, - "source": [ - "## Generate new model containing the field" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a9f39aa3", - "metadata": {}, - "outputs": [], - "source": [ - "be.build_fields(\n", - " voxel_size=0.25, density=1.0,\n", - " data_type=be.FIELD_DATA_TYPE_VECTOR\n", - ")\n", - "\n", - "status = core.set_renderer(current='advanced')" - ] - }, - { - "cell_type": "markdown", - "id": "b751ad42", - "metadata": {}, - "source": [ - "### Volume settings" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9da4c165", - "metadata": {}, - "outputs": [], - "source": [ - "status = core.set_field_parameters(\n", - " distance=1, cutoff=200, epsilon=0.001,\n", - " gradient_shading=False, sampling_rate=0.25)" - ] - }, - { - "cell_type": "markdown", - "id": "f7c0c1a2", - "metadata": {}, - "source": [ - "### Attach transfer function to newly created model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2034dc01", - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "from bioexplorer import TransferFunction\n", - "model_ids = be.get_model_ids()['ids']\n", - "model_id = model_ids[len(model_ids)-1]\n", - "tf = TransferFunction(\n", - " bioexplorer=be, model_id=model_id,\n", - " filename='fusion.1dt',\n", - " value_range=[0.1, 5.0])" - ] - }, - { - "cell_type": "markdown", - "id": "aa04cb63", - "metadata": {}, - "source": [ - "## Fusion reactor Tokamak 3D model\n", - "Can be downloaded from: https://blendermarket.com/products/fusion-reactor-tokamak" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b69e7773", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "transformation={\n", - " 'rotation': [0.0, -0.25038000405444144, 0.0, 0.9681476403781076],\n", - " 'rotation_center': [0.0, 0.0, 0.0],\n", - " 'scale': [12.0, 12.0, 12.0],\n", - " 'translation': [0.0, -1.0, 0.0]\n", - "}\n", - "model_filename = 'Fusion_reactor_by_www_up3d_de_without_plasma.obj'\n", - "core.add_model(name='Fusion Reactor Tokamak', path=model_filename)\n", - "model_ids = be.get_model_ids()['ids']\n", - "status = core.update_model(id=model_ids[len(model_ids)-1], transformation=transformation)" - ] - }, - { - "cell_type": "markdown", - "id": "805cbbeb", - "metadata": {}, - "source": [ - "## Rendering settings" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8b48082a", - "metadata": {}, - "outputs": [], - "source": [ - "status = be.reset_camera()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "09f3a8ca", - "metadata": {}, - "outputs": [], - "source": [ - "status = core.set_renderer(\n", - " background_color=[0.25, 0.25, 0.25],\n", - " current='advanced', \n", - " samples_per_pixel=1,\n", - " subsampling=4,\n", - " max_accum_frames=1024)\n", - "params = core.AdvancedRendererParams()\n", - "params.gi_samples = 0\n", - "params.gi_strength = 0.0\n", - "params.gi_ray_length = 150.0\n", - "params.shadow_intensity = 0.5\n", - "params.soft_shadow_strength = 0.1\n", - "params.max_ray_depth = 3\n", - "params.show_background = True\n", - "params.fog_start = 100.0\n", - "params.fog_thickness = 20.0\n", - "status = core.set_renderer_params(params)\n", - "status = core.set_renderer()" - ] - }, - { - "cell_type": "markdown", - "id": "8713d0c5", - "metadata": {}, - "source": [ - "## Widgets to modify materials" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "afcf63a4", - "metadata": {}, - "outputs": [], - "source": [ - "from bioexplorer import Widgets\n", - "w = Widgets(be)\n", - "w.display_palette_for_models()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "faad71d7", + "metadata": {}, + "source": [ + "# Nuclear Fusion Tokamak\n", + "![](./nuclearfusion_banner.png)" + ] + }, + { + "cell_type": "markdown", + "id": "9abd82ad", + "metadata": {}, + "source": [ + "### Connect to BioExplorer backend" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ecf1c452", + "metadata": {}, + "outputs": [], + "source": [ + "from bioexplorer import BioExplorer, Vector3\n", + "\n", + "be = BioExplorer('localhost:5000')\n", + "core = be.core_api()\n", + "be.reset_scene()\n", + "print('BioExplorer version ' + be.version())" + ] + }, + { + "cell_type": "markdown", + "id": "0ba057d7", + "metadata": {}, + "source": [ + "### Generate random data set:\n", + "Vectors composed of a position and a direction. The length of the vector is the value of the voltage" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce421549", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "import numpy as np\n", + "import time\n", + "\n", + "''' Settings '''\n", + "nb_particles = 2000\n", + "use_randomness = True\n", + "\n", + "def generate_random_point_in_torus(main_radius, tube_radius):\n", + " theta = 2 * math.pi * random.random()\n", + " phi = 2 * math.pi * random.random()\n", + " x = (main_radius + tube_radius * math.cos(phi)) * math.cos(theta)\n", + " y = tube_radius * math.sin(phi)\n", + " z = (main_radius + tube_radius * math.cos(phi)) * math.sin(theta)\n", + " return x, y, z\n", + "\n", + "origins = list()\n", + "targets = list()\n", + "origins_radii = list()\n", + "targets_radii = list()\n", + "\n", + "seed = int(time.time())\n", + "random.seed(seed)\n", + "for i in range(nb_particles):\n", + " x = 0\n", + " y = 0\n", + " z = 0\n", + " x, y, z = generate_random_point_in_torus(10.0, 2.0)\n", + " origin = Vector3(x, y ,z)\n", + " \n", + "\n", + " length = 0.2\n", + " cp = np.cross([x, y, z], [0, 1, 0])\n", + " if use_randomness:\n", + " cp[0] += (random.random() - 0.5)\n", + " cp[1] += (random.random() - 0.5)\n", + " cp[2] += (random.random() - 0.5)\n", + " length = random.random() * 0.2\n", + "\n", + " target = Vector3(\n", + " origin.x + cp[0] * length,\n", + " origin.y + cp[1] * length,\n", + " origin.z + cp[2] * length\n", + " )\n", + " origins.append(origin)\n", + " targets.append(target)\n", + " origins_radii.append(0.1)\n", + " targets_radii.append(0.0)\n", + "\n", + "status = be.add_cones(\n", + " name='Particles',\n", + " origins=origins, origins_radii=origins_radii,\n", + " targets=targets, targets_radii=targets_radii,\n", + " color=Vector3(1.0, 1.0, 1.0), opacity=1.0)" + ] + }, + { + "cell_type": "markdown", + "id": "5a21827f", + "metadata": {}, + "source": [ + "## Generate new model containing the field" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9f39aa3", + "metadata": {}, + "outputs": [], + "source": [ + "be.build_fields(\n", + " voxel_size=0.25, density=1.0,\n", + " data_type=be.FIELD_DATA_TYPE_VECTOR\n", + ")\n", + "\n", + "status = core.set_renderer(current='advanced')" + ] + }, + { + "cell_type": "markdown", + "id": "b751ad42", + "metadata": {}, + "source": [ + "### Volume settings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9da4c165", + "metadata": {}, + "outputs": [], + "source": [ + "status = core.set_field_parameters(\n", + " distance=1, cutoff=200, epsilon=0.001,\n", + " gradient_shading=False, sampling_rate=0.25)" + ] + }, + { + "cell_type": "markdown", + "id": "f7c0c1a2", + "metadata": {}, + "source": [ + "### Attach transfer function to newly created model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2034dc01", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "from bioexplorer import TransferFunction\n", + "model_ids = be.get_model_ids()['ids']\n", + "model_id = model_ids[len(model_ids)-1]\n", + "tf = TransferFunction(\n", + " bioexplorer=be, model_id=model_id,\n", + " filename='fusion.1dt',\n", + " value_range=[0.1, 5.0])" + ] + }, + { + "cell_type": "markdown", + "id": "aa04cb63", + "metadata": {}, + "source": [ + "## Fusion reactor Tokamak 3D model\n", + "Can be downloaded from: https://blendermarket.com/products/fusion-reactor-tokamak" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b69e7773", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "transformation={\n", + " 'rotation': [0.0, -0.25038000405444144, 0.0, 0.9681476403781076],\n", + " 'rotation_center': [0.0, 0.0, 0.0],\n", + " 'scale': [12.0, 12.0, 12.0],\n", + " 'translation': [0.0, -1.0, 0.0]\n", + "}\n", + "model_filename = 'Fusion_reactor_by_www_up3d_de_without_plasma.obj'\n", + "core.add_model(name='Fusion Reactor Tokamak', path=model_filename)\n", + "model_ids = be.get_model_ids()['ids']\n", + "status = core.update_model(id=model_ids[len(model_ids)-1], transformation=transformation)" + ] + }, + { + "cell_type": "markdown", + "id": "805cbbeb", + "metadata": {}, + "source": [ + "## Rendering settings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b48082a", + "metadata": {}, + "outputs": [], + "source": [ + "status = be.reset_camera()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09f3a8ca", + "metadata": {}, + "outputs": [], + "source": [ + "status = core.set_renderer(\n", + " background_color=[0.25, 0.25, 0.25],\n", + " current='advanced', \n", + " samples_per_pixel=1,\n", + " subsampling=4,\n", + " max_accum_frames=1024)\n", + "params = core.AdvancedRendererParams()\n", + "params.gi_samples = 0\n", + "params.gi_strength = 0.0\n", + "params.gi_ray_length = 150.0\n", + "params.shadow_intensity = 0.5\n", + "params.soft_shadow_strength = 0.1\n", + "params.max_ray_depth = 3\n", + "params.show_background = True\n", + "params.fog_start = 100.0\n", + "params.fog_thickness = 20.0\n", + "status = core.set_renderer_params(params)\n", + "status = core.set_renderer()" + ] + }, + { + "cell_type": "markdown", + "id": "8713d0c5", + "metadata": {}, + "source": [ + "## Widgets to modify materials" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "afcf63a4", + "metadata": {}, + "outputs": [], + "source": [ + "from bioexplorer import Widgets\n", + "w = Widgets(be)\n", + "w.display_model_material()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/platform/engines/optix6/OptiXCommonStructs.h b/platform/engines/optix6/OptiXCommonStructs.h index a296b62ba..6d287ae88 100644 --- a/platform/engines/optix6/OptiXCommonStructs.h +++ b/platform/engines/optix6/OptiXCommonStructs.h @@ -48,6 +48,7 @@ struct PerRayData_radiance ::optix::float4 result; float importance; int depth; + float zDepth; ::optix::float3 rayDdx; ::optix::float3 rayDdy; }; diff --git a/platform/engines/optix6/OptiXContext.h b/platform/engines/optix6/OptiXContext.h index 7fa0d305d..de5bb5130 100644 --- a/platform/engines/optix6/OptiXContext.h +++ b/platform/engines/optix6/OptiXContext.h @@ -119,6 +119,7 @@ static const char* CONTEXT_STAGE_TONE_MAPPER = "TonemapperSimple"; static const char* CONTEXT_STAGE_DENOISER = "DLDenoiser"; static const char* CONTEXT_INPUT_BUFFER = "input_buffer"; static const char* CONTEXT_OUTPUT_BUFFER = "output_buffer"; +static const char* CONTEXT_DEPTH_BUFFER = "depth_buffer"; static const char* CONTEXT_INPUT_ALBEDO_BUFFER = "input_albedo_buffer"; static const char* CONTEXT_INPUT_NORMAL_BUFFER = "input_normal_buffer"; static const char* CONTEXT_TONE_MAPPER_EXPOSURE = "exposure"; diff --git a/platform/engines/optix6/OptiXEngine.cpp b/platform/engines/optix6/OptiXEngine.cpp index cde2d8ed2..c7f6a81fb 100644 --- a/platform/engines/optix6/OptiXEngine.cpp +++ b/platform/engines/optix6/OptiXEngine.cpp @@ -55,12 +55,12 @@ OptiXEngine::OptiXEngine(ParametersManager& parametersManager) _parametersManager.getGeometryParameters(), _parametersManager.getVolumeParameters(), _parametersManager.getFieldParameters()); - PLUGIN_INFO("Initializing renderers"); - _createRenderers(); - PLUGIN_INFO("Initializing cameras"); _createCameras(); + PLUGIN_INFO("Initializing renderers"); + _createRenderers(); + PLUGIN_INFO("Engine initialization complete"); } @@ -148,6 +148,7 @@ void OptiXEngine::_createRenderers() _renderer = std::make_shared(_parametersManager.getAnimationParameters(), _parametersManager.getRenderingParameters()); _renderer->setEngine(this); + _renderer->setCamera(_camera); OptiXContext& context = OptiXContext::get(); { // Advanced renderer diff --git a/platform/engines/optix6/OptiXFrameBuffer.cpp b/platform/engines/optix6/OptiXFrameBuffer.cpp index dceb05ad7..e210984b9 100644 --- a/platform/engines/optix6/OptiXFrameBuffer.cpp +++ b/platform/engines/optix6/OptiXFrameBuffer.cpp @@ -56,6 +56,7 @@ void OptiXFrameBuffer::_cleanup() // Buffers RT_DESTROY(_outputBuffer); RT_DESTROY(_accumBuffer); + RT_DESTROY(_depthBuffer); RT_DESTROY(_tonemappedBuffer); RT_DESTROY(_denoisedBuffer); @@ -100,6 +101,9 @@ void OptiXFrameBuffer::resize(const Vector2ui& frameSize) _outputBuffer = context->createBuffer(RT_BUFFER_OUTPUT, format, _frameSize.x, _frameSize.y); context[CONTEXT_OUTPUT_BUFFER]->set(_outputBuffer); + _depthBuffer = context->createBuffer(RT_BUFFER_OUTPUT, RT_FORMAT_FLOAT, _frameSize.x, _frameSize.y); + context[CONTEXT_DEPTH_BUFFER]->set(_depthBuffer); + _accumBuffer = context->createBuffer(RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT4, _frameSize.x, _frameSize.y); context[CONTEXT_ACCUMULATION_BUFFER]->set(_accumBuffer); @@ -124,11 +128,13 @@ void OptiXFrameBuffer::_mapUnsafe() _initializePostProcessingStages(); rtBufferMap(_outputBuffer->get(), &_colorData); + rtBufferMap(_depthBuffer->get(), &_depthData); auto context = OptiXContext::get().getOptixContext(); context[CONTEXT_FRAME_NUMBER]->setUint(_accumulationFrameNumber); - _colorBuffer = (uint8_t*)(_colorData); + _colorDataBuffer = (uint8_t*)(_colorData); + _depthDataBuffer = (float*)(_depthData); // Post processing if (_accumulationType == AccumulationType::ai_denoised) @@ -140,7 +146,7 @@ void OptiXFrameBuffer::_mapUnsafe() else rtBufferMap(_tonemappedBuffer->get(), &_floatData); - _floatBuffer = (float*)_floatData; + _floatDataBuffer = (float*)_floatData; } ++_accumulationFrameNumber; } @@ -176,6 +182,7 @@ void OptiXFrameBuffer::_unmapUnsafe() } rtBufferUnmap(_outputBuffer->get()); + rtBufferUnmap(_depthBuffer->get()); if (_postprocessingStagesInitialized) { diff --git a/platform/engines/optix6/OptiXFrameBuffer.h b/platform/engines/optix6/OptiXFrameBuffer.h index 0fc052bbf..0f0eca967 100644 --- a/platform/engines/optix6/OptiXFrameBuffer.h +++ b/platform/engines/optix6/OptiXFrameBuffer.h @@ -51,8 +51,9 @@ class OptiXFrameBuffer : public FrameBuffer void setAccumulation(const bool accumulation) final; std::unique_lock getScopeLock() { return std::unique_lock(_mapMutex); } - const uint8_t* getColorBuffer() const final { return _colorBuffer; } - const float* getFloatBuffer() const final { return _floatBuffer; } + const uint8_t* getColorBuffer() const final { return _colorDataBuffer; } + const float* getFloatBuffer() const final { return _floatDataBuffer; } + const float* getDepthBuffer() const { return _depthDataBuffer; } private: void _cleanup(); @@ -61,14 +62,17 @@ class OptiXFrameBuffer : public FrameBuffer ::optix::Buffer _outputBuffer{nullptr}; ::optix::Buffer _accumBuffer{nullptr}; + ::optix::Buffer _depthBuffer{nullptr}; ::optix::Buffer _tonemappedBuffer{nullptr}; ::optix::Buffer _denoisedBuffer{nullptr}; - uint8_t* _colorBuffer{nullptr}; - float* _floatBuffer{nullptr}; + uint8_t* _colorDataBuffer{nullptr}; + float* _floatDataBuffer{nullptr}; + float* _depthDataBuffer{nullptr}; void* _imageData{nullptr}; void* _colorData{nullptr}; void* _floatData{nullptr}; + void* _depthData{nullptr}; // Post processing void _initializePostProcessingStages(); diff --git a/platform/engines/optix6/OptiXRenderer.cpp b/platform/engines/optix6/OptiXRenderer.cpp index eb7baafca..f258e646f 100644 --- a/platform/engines/optix6/OptiXRenderer.cpp +++ b/platform/engines/optix6/OptiXRenderer.cpp @@ -114,7 +114,43 @@ void OptiXRenderer::commit() toOptiXProperties(getPropertyMap()); } -void OptiXRenderer::setCamera(CameraPtr /*camera*/) {} +void OptiXRenderer::setCamera(CameraPtr camera) +{ + _camera = static_cast(camera.get()); + assert(_camera); + markModified(); +} + +Renderer::PickResult OptiXRenderer::pick(const Vector2f& pickPos) +{ + PickResult result; + if (_camera) + { + auto context = OptiXContext::get().getOptixContext(); + auto& frameBuffer = _engine->getFrameBuffer(); + OptiXFrameBuffer* optixFrameBuffer = dynamic_cast(&frameBuffer); + if (optixFrameBuffer) + { + const auto frameSize = optixFrameBuffer->getSize(); + const size_t indexX = static_cast(pickPos.x * frameSize.x); + const size_t indexY = static_cast(pickPos.y * frameSize.y); + const size_t index = indexY * frameSize.x + indexX; + if (index >= frameSize.x * frameSize.y) + return result; + const float* depthBuffer = optixFrameBuffer->getDepthBuffer(); + const float depth = depthBuffer[index]; + if (depth < INFINITY) + { + const Vector3f pos = _camera->getPosition(); + const Vector3f dir = normalize(_camera->getTarget() - _camera->getPosition()); + result.pos = pos + dir * depth; + result.hit = true; + } + } + } + return result; +} + } // namespace optix } // namespace engine } // namespace core \ No newline at end of file diff --git a/platform/engines/optix6/OptiXRenderer.h b/platform/engines/optix6/OptiXRenderer.h index b2672d71f..d0f73a9b7 100644 --- a/platform/engines/optix6/OptiXRenderer.h +++ b/platform/engines/optix6/OptiXRenderer.h @@ -49,7 +49,10 @@ class OptiXRenderer : public Renderer void setCamera(CameraPtr camera) final; + PickResult pick(const Vector2f& pickPos) final; + private: + OptiXCamera* _camera{nullptr}; Timer _timer; }; } // namespace optix diff --git a/platform/engines/optix6/cuda/Context.cuh b/platform/engines/optix6/cuda/Context.cuh index 502b21be6..cfc14d205 100644 --- a/platform/engines/optix6/cuda/Context.cuh +++ b/platform/engines/optix6/cuda/Context.cuh @@ -49,6 +49,7 @@ rtDeclareVariable(uint2, launch_index, rtLaunchIndex, ); rtBuffer output_buffer; rtBuffer accum_buffer; +rtBuffer depth_buffer; rtDeclareVariable(float, height, , ); rtDeclareVariable(float4, jitter4, , ); diff --git a/platform/engines/optix6/cuda/camera/AnaglyphCamera.cu b/platform/engines/optix6/cuda/camera/AnaglyphCamera.cu index 2210d26f9..817561018 100644 --- a/platform/engines/optix6/cuda/camera/AnaglyphCamera.cu +++ b/platform/engines/optix6/cuda/camera/AnaglyphCamera.cu @@ -24,7 +24,8 @@ using namespace optix; -__device__ float4 trace(const float3 ray_origin, const float3 offset, const float2 screen, const float2 subpixel_jitter) +__device__ void trace(const float3 ray_origin, const float3 offset, const float2 screen, const float2 subpixel_jitter, + float4& result, float& depth) { float2 p = (make_float2(launch_index) + subpixel_jitter) / screen * 2.f - 1.f; float3 origin = ray_origin + offset; @@ -41,6 +42,7 @@ __device__ float4 trace(const float3 ray_origin, const float3 offset, const floa prd.depth = 0; prd.rayDdx = (dotD * U - dot(d, U) * d) / (denom * screen.x); prd.rayDdy = (dotD * V - dot(d, V) * d) / (denom * screen.y); + prd.zDepth = INFINITY; if (apertureRadius > 0.f) { @@ -61,11 +63,12 @@ __device__ float4 trace(const float3 ray_origin, const float3 offset, const floa const optix::Ray ray(origin, ray_direction, radiance_ray_type, near, far); rtTrace(top_object, ray, prd); - return prd.result; + result = make_float4(make_float3(prd.result) * mainExposure, prd.result.w); + depth = prd.zDepth; } // Pass 'seed' by reference to keep randomness state -__device__ float4 launch(uint& seed, const float2 screen, const bool use_randomness) +__device__ void launch(uint& seed, const float2 screen, const bool use_randomness, float4& result, float& depth) { float3 ray_origin = eye; @@ -73,15 +76,17 @@ __device__ float4 launch(uint& seed, const float2 screen, const bool use_randomn const float2 subpixel_jitter = use_randomness ? make_float2(rnd(seed) - 0.5f, rnd(seed) - 0.5f) : make_float2(0.f, 0.f); - const float4 colorLeft = trace(ray_origin, -ipd_offset, screen, subpixel_jitter); + float4 colorLeft; + trace(ray_origin, -ipd_offset, screen, subpixel_jitter, colorLeft, depth); const float4 leftAnaglyphColor = make_float4(colorLeft.x * 0.299f + colorLeft.y * 0.587f + colorLeft.z * 0.114f, 0.f, 0.f, colorLeft.w); - const float4 colorRight = trace(ray_origin, ipd_offset, screen, subpixel_jitter); + float4 colorRight; + trace(ray_origin, ipd_offset, screen, subpixel_jitter, colorRight, depth); const float4 rightAnaglyphColor = make_float4(0.f, colorRight.y, colorRight.z, colorRight.w); - const float4 result = leftAnaglyphColor + rightAnaglyphColor; - return make_float4(make_float3(result) * mainExposure, result.w); + result = leftAnaglyphColor + rightAnaglyphColor; + result = make_float4(make_float3(result) * mainExposure, result.w); } RT_PROGRAM void perspectiveCamera() @@ -93,21 +98,30 @@ RT_PROGRAM void perspectiveCamera() const int num_samples = max(1, samples_per_pixel); const bool use_randomness = frame > 0 || num_samples > 1; - float4 result = make_float4(0.f); + float4 color = make_float4(0.f); + float depth = 0.f; for (int i = 0; i < num_samples; i++) - result += launch(seed, screen_f, use_randomness); - result /= num_samples; + { + float4 result; + float d; + launch(seed, screen_f, use_randomness, result, d); + color += result; + depth += d; + } + color /= num_samples; + depth /= num_samples; float4 acc_val; if (frame > 0) { acc_val = accum_buffer[launch_index]; - acc_val = lerp(acc_val, result, 1.0f / static_cast(frame + 1)); + acc_val = lerp(acc_val, color, 1.0f / static_cast(frame + 1)); } else - acc_val = result; + acc_val = color; output_buffer[launch_index] = make_color(acc_val); + depth_buffer[launch_index] = depth; if (accum_buffer.size().x > 1 && accum_buffer.size().y > 1) accum_buffer[launch_index] = acc_val; @@ -116,4 +130,5 @@ RT_PROGRAM void perspectiveCamera() RT_PROGRAM void exception() { output_buffer[launch_index] = make_color(bad_color); + depth_buffer[launch_index] = INFINITY; } diff --git a/platform/engines/optix6/cuda/camera/OrthographicCamera.cu b/platform/engines/optix6/cuda/camera/OrthographicCamera.cu index 527ac9823..c88b0c663 100644 --- a/platform/engines/optix6/cuda/camera/OrthographicCamera.cu +++ b/platform/engines/optix6/cuda/camera/OrthographicCamera.cu @@ -41,6 +41,7 @@ __device__ float4 launch(uint& seed, const float2 screen, const bool use_randomn PerRayData_radiance prd; prd.importance = 1.f; prd.depth = 0; + prd.zDepth = INFINITY; float near = sceneEpsilon; float far = INFINITY; @@ -88,4 +89,5 @@ RT_PROGRAM void orthographicCamera() RT_PROGRAM void exception() { output_buffer[launch_index] = make_color(bad_color); + depth_buffer[launch_index] = INFINITY; } diff --git a/platform/engines/optix6/cuda/camera/PerspectiveCamera.cu b/platform/engines/optix6/cuda/camera/PerspectiveCamera.cu index 08bf5a267..e81401725 100644 --- a/platform/engines/optix6/cuda/camera/PerspectiveCamera.cu +++ b/platform/engines/optix6/cuda/camera/PerspectiveCamera.cu @@ -25,7 +25,7 @@ using namespace optix; // Pass 'seed' by reference to keep randomness state -__device__ float4 launch(uint& seed, const float2 screen, const bool use_randomness) +__device__ void launch(uint& seed, const float2 screen, const bool use_randomness, float4& result, float& depth) { float3 ray_origin = eye; @@ -63,6 +63,7 @@ __device__ float4 launch(uint& seed, const float2 screen, const bool use_randomn prd.depth = 0; prd.rayDdx = (dotD * U - dot(d, U) * d) / (denom * screen.x); prd.rayDdy = (dotD * V - dot(d, V) * d) / (denom * screen.y); + prd.zDepth = INFINITY; if (apertureRadius > 0.f) { @@ -83,7 +84,8 @@ __device__ float4 launch(uint& seed, const float2 screen, const bool use_randomn optix::Ray ray(ray_origin, ray_direction, radiance_ray_type, near, far); rtTrace(top_object, ray, prd); - return make_float4(make_float3(prd.result) * mainExposure, prd.result.w); + result = make_float4(make_float3(prd.result) * mainExposure, prd.result.w); + depth = prd.zDepth; } RT_PROGRAM void perspectiveCamera() @@ -95,21 +97,30 @@ RT_PROGRAM void perspectiveCamera() const int num_samples = max(1, samples_per_pixel); const bool use_randomness = frame > 0 || num_samples > 1; - float4 result = make_float4(0.f); + float4 color = make_float4(0.f); + float depth = 0.f; for (int i = 0; i < num_samples; i++) - result += launch(seed, screen_f, use_randomness); - result /= num_samples; + { + float4 result; + float d; + launch(seed, screen_f, use_randomness, result, d); + color += result; + depth += d; + } + color /= num_samples; + depth /= num_samples; float4 acc_val; if (frame > 0) { acc_val = accum_buffer[launch_index]; - acc_val = lerp(acc_val, result, 1.0f / static_cast(frame + 1)); + acc_val = lerp(acc_val, color, 1.0f / static_cast(frame + 1)); } else - acc_val = result; + acc_val = color; output_buffer[launch_index] = make_color(acc_val); + depth_buffer[launch_index] = depth; if (accum_buffer.size().x > 1 && accum_buffer.size().y > 1) accum_buffer[launch_index] = acc_val; @@ -118,4 +129,5 @@ RT_PROGRAM void perspectiveCamera() RT_PROGRAM void exception() { output_buffer[launch_index] = make_color(bad_color); + depth_buffer[launch_index] = INFINITY; } diff --git a/platform/engines/optix6/cuda/renderer/Advanced.cu b/platform/engines/optix6/cuda/renderer/Advanced.cu index 3b6eee3e7..2f9a90d2c 100644 --- a/platform/engines/optix6/cuda/renderer/Advanced.cu +++ b/platform/engines/optix6/cuda/renderer/Advanced.cu @@ -284,8 +284,9 @@ static __device__ void phongShade(float3 p_Kd, float3 p_Ka, float3 p_Ks, float3 result = make_float3(result.x * 0.666f, result.y * 0.8f, result.z * 0.666f); // Fog attenuation - const float z = optix::length(eye - hit_point); - const float fogAttenuation = z > fogStart ? optix::clamp((z - fogStart) / fogThickness, 0.f, 1.f) : 0.f; + prd.zDepth = optix::length(eye - hit_point); + const float fogAttenuation = + prd.zDepth > fogStart ? optix::clamp((prd.zDepth - fogStart) / fogThickness, 0.f, 1.f) : 0.f; result = result * (1.f - fogAttenuation) + fogAttenuation * getEnvironmentColor(ray.direction); prd.result = make_float4(result, finalColor.w); @@ -340,4 +341,5 @@ RT_PROGRAM void closest_hit_radiance_textured() RT_PROGRAM void exception() { output_buffer[launch_index] = make_color(bad_color); + depth_buffer[launch_index] = INFINITY; } diff --git a/platform/engines/optix6/cuda/renderer/Basic.cu b/platform/engines/optix6/cuda/renderer/Basic.cu index 7f0d7626d..d885c3edd 100644 --- a/platform/engines/optix6/cuda/renderer/Basic.cu +++ b/platform/engines/optix6/cuda/renderer/Basic.cu @@ -38,6 +38,8 @@ static __device__ inline void shade(bool textured) color = Kd; prd.result = make_float4(color * max(0.f, optix::dot(-ray.direction, normal)), 1.f); + const float3 hit_point = ray.origin + t_hit * ray.direction; + prd.zDepth = optix::length(eye - hit_point); } RT_PROGRAM void any_hit_shadow() @@ -58,4 +60,5 @@ RT_PROGRAM void closest_hit_radiance_textured() RT_PROGRAM void exception() { output_buffer[launch_index] = make_color(bad_color); + depth_buffer[launch_index] = INFINITY; } diff --git a/platform/engines/ospray/OSPRayRenderer.cpp b/platform/engines/ospray/OSPRayRenderer.cpp index 95bf9b047..8062a7997 100644 --- a/platform/engines/ospray/OSPRayRenderer.cpp +++ b/platform/engines/ospray/OSPRayRenderer.cpp @@ -203,7 +203,10 @@ Renderer::PickResult OSPRayRenderer::pick(const Vector2f& pickPos) PickResult result; result.hit = ospResult.hit; if (result.hit) + { result.pos = {ospResult.position.x, ospResult.position.y, ospResult.position.z}; + CORE_INFO("OSPRAY Depth: " << pickPos << " - " << result.pos); + } return result; } diff --git a/platform/engines/ospray/ispc/render/AdvancedRenderer.ispc b/platform/engines/ospray/ispc/render/AdvancedRenderer.ispc index acd960798..2fc7e83f6 100644 --- a/platform/engines/ospray/ispc/render/AdvancedRenderer.ispc +++ b/platform/engines/ospray/ispc/render/AdvancedRenderer.ispc @@ -203,7 +203,7 @@ inline void setGeometryShadingAttributes(const uniform AdvancedRenderer* uniform if (valid(mat->map_d)) attributes.opacity = mat->d * get1f(mat->map_d, dg); else - attributes.opacity = dg.color.w; + attributes.opacity = min(dg.color.w, mat->d); // Diffuse color attributes.diffuseColor = mat->Kd * make_vec3f(dg.color);