diff --git a/demos/optical_bench/src/Optix Files/glass_iterative_camera.cu b/demos/optical_bench/src/Optix Files/glass_iterative_camera.cu index 44bbcaa9cfa725a94d8aea1de6e1da46349a84ef..7522a7d81a3360f13b06c3321a27ec50446ec492 100644 --- a/demos/optical_bench/src/Optix Files/glass_iterative_camera.cu +++ b/demos/optical_bench/src/Optix Files/glass_iterative_camera.cu @@ -101,7 +101,6 @@ RT_PROGRAM void closest_hit_radiance() const float3 fhp = rtTransformPoint(RT_OBJECT_TO_WORLD, front_hit_point); prd_radiance.origin = fhp; prd_radiance.direction = w_in; - prd_radiance.reflectance *= reflection_color*transmittance; }else{ prd_radiance.done = true; } @@ -110,8 +109,7 @@ RT_PROGRAM void closest_hit_radiance() const float3 w_in = w_t; const float3 bhp = rtTransformPoint(RT_OBJECT_TO_WORLD, back_hit_point); prd_radiance.origin = bhp; - prd_radiance.direction = w_in; - prd_radiance.reflectance *= refraction_color*transmittance; + prd_radiance.direction = w_in; } // Note: we do not trace the ray for the next bounce here, we just set it up for diff --git a/demos/optical_bench/src/Optix Files/laser_caster.cu b/demos/optical_bench/src/Optix Files/laser_caster.cu index 11316aa2f4521202ffbaa4853be1f80a4b42f81c..4eb8721443614d178d23ee8229e62a6a923d0ae7 100644 --- a/demos/optical_bench/src/Optix Files/laser_caster.cu +++ b/demos/optical_bench/src/Optix Files/laser_caster.cu @@ -6,8 +6,8 @@ using namespace optix; -rtDeclareVariable(uint2, launch_index, rtLaunchIndex, ); -rtDeclareVariable(uint2, launch_dim, rtLaunchDim, ); +rtDeclareVariable(uint3, launch_index, rtLaunchIndex, ); +rtDeclareVariable(uint3, launch_dim, rtLaunchDim, ); rtDeclareVariable(rtObject, top_object, , ); rtDeclareVariable(float, scene_epsilon, , ); rtDeclareVariable(int, max_depth_laser, , ); @@ -23,51 +23,50 @@ rtDeclareVariable(float3, laser_up, , ); rtBuffer<int, 2> laserIndex; rtBuffer<float3, 1> result_laser; + RT_PROGRAM void laser_caster() { const float laserSize = 0.04; - const float laserBeamWidth = 0.005; - - unsigned int seed = tea<16>(launch_dim.x*launch_index.y+launch_index.x, random_frame_seed); + float2 d = make_float2(launch_index.x, launch_index.y) / make_float2(launch_dim.x, launch_dim.y) - make_float2(0.5f, 0.5f); + float3 ray_origin = laser_origin + laser_right * laserSize * d.x + laser_up * laserSize * d.y; + + const float laserBeamWidth = 0.025; + unsigned int seed = tea<16>(launch_dim.x*launch_index.y+launch_index.x*launch_index.z, random_frame_seed); float2 random = make_float2(rnd(seed), rnd(seed)); - float r = sqrt(-2*log(random.x)); + float r = sqrtf(-2*log(random.x)); float theta = 2*3.141592654f*random.y; - random = clamp(make_float2(r*cos(theta), r*sin(theta)), -4.5f, 4.5f) * laserBeamWidth/4.5f; + random = clamp(make_float2(r*cosf(theta), r*sinf(theta)), -4.5f, 4.5f) * laserBeamWidth/4.5f; + if(launch_index.z != 0) ray_origin += laser_right * random.x + laser_up * random.y; - float2 d = make_float2(launch_index) / make_float2(launch_dim) - make_float2(0.5f, 0.5f); - float3 ray_origin = laser_origin + laser_right * laserSize * d.x + laser_up * laserSize * d.y + laser_right * random.x + laser_up * random.y; - float3 ray_direction = laser_forward; - PerRayData_radiance_iterative prd; + optix::Ray ray(ray_origin, laser_forward, /*ray type*/ 1, scene_epsilon ); prd.depth = 0; - prd.seed = launch_index.y + launch_index.x; prd.done = false; prd.hit_lens = false; //track if the ray ever hit the lens - prd.radiance = make_float3(1) * (1 - length(random)/laserBeamWidth); + prd.power = (launch_index.z > 0) * 1; //No power for launch index 0 // next ray to be traced prd.origin = ray_origin; - prd.direction = ray_direction; + prd.direction = laser_forward; unsigned int startIndex = (launch_index.y * 50 + launch_index.x) * max_depth_laser * 2; + bool cast_ray = laserIndex[make_uint2(launch_index)] < 0; for(int i = 0; i < max_depth_laser * 2; i += 2){ //Determine if this launch_index, depth or last ray should trigger new cast - if(laserIndex[launch_index] < 0 || prd.done || prd.depth >= max_depth_laser){ // just write rest of data as "invalid" - result_laser[startIndex + i] = make_float3(0,-1,0); - result_laser[startIndex + i + 1] = make_float3(0,-1,0); + if(cast_ray || prd.done || prd.depth >= max_depth_laser){ // just write rest of data as "invalid" + if(launch_index.z == 0) result_laser[startIndex + i] = make_float3(0,-1,0); + if(launch_index.z == 0) result_laser[startIndex + i + 1] = make_float3(0,-1,0); continue; } - result_laser[startIndex + i] = ray_origin; + if(launch_index.z == 0) result_laser[startIndex + i] = prd.origin; - optix::Ray ray(ray_origin, ray_direction, /*ray type*/ 1, scene_epsilon ); + ray.origin = prd.origin; + ray.direction = prd.direction; rtTrace(top_object, ray, prd); - // Update ray data for the next path segment prd.depth++; - ray_origin = prd.origin; - ray_direction = prd.direction; - result_laser[startIndex + i + 1] = ray_origin; - } + if(launch_index.z == 0) result_laser[startIndex + i + 1] = prd.origin; + } } \ No newline at end of file diff --git a/demos/optical_bench/src/Optix Files/laser_target_material.cu b/demos/optical_bench/src/Optix Files/laser_target_material.cu index 38ba778b1da13a2bb1066334dcb8c239cbd06024..669e5d1f872147d2bdb5b5ce5185c219c7394001 100644 --- a/demos/optical_bench/src/Optix Files/laser_target_material.cu +++ b/demos/optical_bench/src/Optix Files/laser_target_material.cu @@ -27,12 +27,27 @@ rtDeclareVariable(PerRayData_radiance_iterative, prd_radiance_it, rtPayload, ); rtDeclareVariable(float2, texture_coord, attribute texture_coord, ); rtDeclareVariable(int, writeable_surface, attribute writeable_surface, ); rtDeclareVariable(float, hit_depth, rtIntersectionDistance, ); + +rtDeclareVariable(float, max_power, , ); rtDeclareVariable(optix::Ray, ray, rtCurrentRay, ); -rtBuffer<float3, 2> targetBuffer; +rtBuffer<float, 1> targetBufferMax; +rtBuffer<float, 2> targetBuffer; rtDeclareVariable(float2, targetBufferDim, , ); rtDeclareVariable(int, targetBufferWrite, , ); +//thanks stackoverflow! +__device__ static float atomicMax(float* address, float val){ + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fmaxf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); +} + RT_PROGRAM void any_hit_radiance(){ rtIgnoreIntersection(); } @@ -42,5 +57,9 @@ RT_PROGRAM void closest_hit_iterative() float3 hit_point = ray.origin + hit_depth * ray.direction; prd_radiance_it.origin = hit_point; prd_radiance_it.done = true; - if(targetBufferWrite && writeable_surface) targetBuffer[make_uint2(texture_coord * targetBufferDim)] = prd_radiance_it.radiance; + + if(targetBufferWrite && writeable_surface){ + atomicAdd(&targetBuffer[make_uint2(texture_coord * targetBufferDim)], prd_radiance_it.power); + atomicMax(&targetBufferMax[0], targetBuffer[make_uint2(texture_coord * targetBufferDim)]); + } } diff --git a/demos/optical_bench/src/Optix Files/normal_shader_new.cu b/demos/optical_bench/src/Optix Files/normal_shader_new.cu index 68da742d718f875d88cc381e9911bf4b9b6cba6e..6c5906e8af21a826bbc2e51c87e12ccc6b983eb0 100644 --- a/demos/optical_bench/src/Optix Files/normal_shader_new.cu +++ b/demos/optical_bench/src/Optix Files/normal_shader_new.cu @@ -38,6 +38,6 @@ rtDeclareVariable(PerRayData_radiance_iterative, prd_radiance, rtPayload, ); RT_PROGRAM void closest_hit_radiance() { - prd_radiance.radiance = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shading_normal))*0.5f + 0.5f; + prd_radiance.power = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shading_normal)).x * 0.5f + 0.5f; prd_radiance.done = true; } diff --git a/demos/optical_bench/src/Optix Files/prd.h b/demos/optical_bench/src/Optix Files/prd.h index 8c818de9237e5c3205805d98be693b003c88e8b9..9a3b97f68f118c6a0b26797d8f0ed2ecfa35a646 100644 --- a/demos/optical_bench/src/Optix Files/prd.h +++ b/demos/optical_bench/src/Optix Files/prd.h @@ -30,33 +30,26 @@ #include <optixu/optixu_vector_types.h> -struct PerRayData_radiance_iterative -{ - int depth; - unsigned int seed; - - // shading state - bool done; - float3 reflectance; - float3 radiance; - float3 origin; - float3 direction; - - bool hit_lens; +struct PerRayData_radiance_iterative{ + float3 origin; + float3 direction; + float power; + int depth; + + bool done; + bool hit_lens; }; -struct PerRayData_radiance -{ +struct PerRayData_radiance{ float3 result; float hit_depth; float importance; int depth; bool miss; - bool hit_lens; + bool hit_lens; }; -struct PerRayData_shadow -{ +struct PerRayData_shadow{ float3 attenuation; }; diff --git a/demos/optical_bench/src/laser_menu.cpp b/demos/optical_bench/src/laser_menu.cpp index e050af0a1d47abb531ae073ba0042f1a0e07b87f..b40b7a6d2d02a659d923971616474b75c7c53441 100644 --- a/demos/optical_bench/src/laser_menu.cpp +++ b/demos/optical_bench/src/laser_menu.cpp @@ -106,7 +106,7 @@ LaserMenu::LaserMenu(phx::Scene* scene, phx::Engine* engine) { clear_target_->GetTransform()->SetLocalTranslation(glm::vec3(0)); clear_target_->SetHoldable(false); clear_target_->SetOnPress( - [this, rayPass](phx::Transform*, glm::mat4) { rayPass->clearTarget(); }); + [this, rayPass](phx::Transform*, glm::mat4) { rayPass->clearTargetBuffers(); }); } LaserMenu::~LaserMenu() { diff --git a/demos/optical_bench/src/optix_context_manager.cpp b/demos/optical_bench/src/optix_context_manager.cpp index 2195007fd7a09b660a2e05cdc4d517a46e745545..6e350088caf41d499de4e045c3869824dcb7f747 100644 --- a/demos/optical_bench/src/optix_context_manager.cpp +++ b/demos/optical_bench/src/optix_context_manager.cpp @@ -39,7 +39,7 @@ OptixContextManager::OptixContextManager() { // context_->setPrintEnabled(true); // context_->setPrintBufferSize(1024); - context_->setStackSize(5000); + context_->setStackSize(5000l); context_["max_depth"]->setInt(10); context_["scene_epsilon"]->setFloat(1.e-4f); diff --git a/demos/optical_bench/src/ray_pass.cpp b/demos/optical_bench/src/ray_pass.cpp index 55e98214041a1ef851f86ddfb3d22ca8e5d0c1f9..cc1e7a6fc68b3e3daa72be1496674205c9789669 100644 --- a/demos/optical_bench/src/ray_pass.cpp +++ b/demos/optical_bench/src/ray_pass.cpp @@ -26,6 +26,7 @@ #include <stdlib.h> #include <cassert> +#include <cstdlib> #include <iostream> #include <memory> #include <string> @@ -70,19 +71,21 @@ RayPass::~RayPass() { // delete openGL resources glDeleteBuffers(1, &bufferOpenGLLaserVertices); glDeleteBuffers(1, &bufferOpenGLLaserColors); - glDeleteBuffers(1, &targetBufferOpenGL); glDeleteVertexArrays(1, &vaoOpenGL); bufferLaserOptix->destroy(); bufferLaserIndexOptix->destroy(); targetBuffer->destroy(); + targetMaxBuffer->destroy(); targetGroup->destroy(); targetGeometry->destroy(); targetTransform->destroy(); targetMaterial->destroy(); targetAcc->destroy(); + free(textureDataBuffer); + delete rod_; } @@ -210,16 +213,14 @@ void RayPass::launchLaser() { optixContextManager_->getContext()["random_frame_seed"]->setUint( random_seed++); // totally "random" (only used as seed) try { - optixContextManager_->getContext()->launch(laser_entry, 50, 50); + optixContextManager_->getContext()->launch(laser_entry, 50, 50, + laser_traces_per_frame); } catch (optix::Exception e) { phx::error(e.getErrorString().c_str()); } - // copy buffer from optix - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, targetBufferOpenGL); - target_texture->set_sub_image(0, 0, 0, target_res, target_res, GL_RGB, - GL_FLOAT, nullptr); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + // copy retrieved intersection data to texture + copyAndScaleTargetData(); } void RayPass::createLaser() { @@ -280,16 +281,15 @@ void RayPass::createTarget() { } target_texture = target_screen_->GetMaterial()->GetAmbientTexture(); - glGenBuffers(1, &targetBufferOpenGL); - glBindBuffer(GL_ARRAY_BUFFER, targetBufferOpenGL); - glBufferData(GL_ARRAY_BUFFER, target_res * target_res * sizeof(float) * 3l, - nullptr, GL_STREAM_DRAW); + // used to expand the data in RAM and map back to GPU + textureDataBuffer = + (float*)std::malloc(target_res * target_res * sizeof(float) * 3l); - targetBuffer = - context->createBufferFromGLBO(RT_BUFFER_INPUT_OUTPUT, targetBufferOpenGL); - targetBuffer->setFormat(RT_FORMAT_FLOAT3); - targetBuffer->setSize(target_res, target_res); - clearTarget(); + targetBuffer = context->createBuffer(RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, + target_res, target_res); + targetMaxBuffer = + context->createBuffer(RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1); + clearTargetBuffers(); // Material std::string ptx = @@ -329,6 +329,7 @@ void RayPass::createTarget() { targetGeometry["targetBufferWrite"]->setInt(1); targetGeometry["targetBuffer"]->setBuffer(targetBuffer); + targetGeometry["targetBufferMax"]->setBuffer(targetMaxBuffer); targetGeometry["targetBufferDim"]->setFloat((float)target_res, (float)target_res); @@ -357,16 +358,42 @@ void RayPass::createTarget() { targetSupportRod = new SupportRod(engine_->GetScene().get(), selector); } -void RayPass::clearTarget() { +void RayPass::copyAndScaleTargetData() { + // fetch max + float max = + *(static_cast<float*>(targetMaxBuffer->map(0, RT_BUFFER_MAP_READ))); + targetMaxBuffer->unmap(); + if (max == 0) max = 1; + + // expand & scale buffer + float curr_val = 0; + float* buffer_data = + static_cast<float*>(targetBuffer->map(0, RT_BUFFER_MAP_READ)); + for (unsigned long i = 0; i < target_res * target_res; i++) { + curr_val = buffer_data[i] / max; + textureDataBuffer[i * 3] = curr_val; + textureDataBuffer[i * 3 + 1] = curr_val; + textureDataBuffer[i * 3 + 2] = curr_val; + } + targetBuffer->unmap(); + + // copy to texture + target_texture->set_sub_image(0, 0, 0, target_res, target_res, GL_RGB, + GL_FLOAT, textureDataBuffer); +} + +void RayPass::clearTargetBuffers() { // null initially float* buffer_data = static_cast<float*>(targetBuffer->map(0, RT_BUFFER_MAP_WRITE_DISCARD)); - for (unsigned long i = 0; i < target_res * target_res * 3; i = i + 3) { + for (unsigned long i = 0; i < target_res * target_res; i++) { buffer_data[i] = 0.0f; - buffer_data[i + 1] = 0.0f; - buffer_data[i + 2] = 0.0f; } targetBuffer->unmap(); + + *(static_cast<float*>(targetMaxBuffer->map(0, RT_BUFFER_MAP_WRITE_DISCARD))) = + 0.0f; + targetMaxBuffer->unmap(); } void RayPass::moveLaser(glm::mat4 transform) { diff --git a/demos/optical_bench/src/ray_pass.hpp b/demos/optical_bench/src/ray_pass.hpp index ff15e6ddc7c0722b9e754e8b2389a66852607250..d3069b24a7fa587e5bc080a6b4e3bcb9512c2b4f 100644 --- a/demos/optical_bench/src/ray_pass.hpp +++ b/demos/optical_bench/src/ray_pass.hpp @@ -81,7 +81,7 @@ class RayPass : public RenderPass { std::string GetCurrentPatternName(); - void clearTarget(); + void clearTargetBuffers(); private: const unsigned int laser_max_depth = 20; @@ -113,23 +113,31 @@ class RayPass : public RenderPass { std::vector<phx::ResourcePointer<phx::Image>> patterns_; unsigned int current_pattern_index_; - // The resource image needs to be adjusted to set the right texture size + // target buffer + // The resource image needs to be adjusted to set the right texture resolution const unsigned long target_res = 512l; - gl::texture_2d* target_texture; - GLuint targetBufferOpenGL = 0; - phx::MaterialHandle* target_screen_; - void createLaser(); - void createTarget(); optix::Buffer targetBuffer; + optix::Buffer targetMaxBuffer; + + // target object + void createTarget(); optix::GeometryGroup targetGroup; optix::GeometryInstance targetGeometry; optix::Transform targetTransform; optix::Material targetMaterial; optix::Acceleration targetAcc; + gl::texture_2d* target_texture; + phx::MaterialHandle* target_screen_; phx::Entity* targetEntity; SupportRod* targetSupportRod; + const unsigned int laser_traces_per_frame = 300u; + + // used to copy and expand data + float* textureDataBuffer = nullptr; + void copyAndScaleTargetData(); // laser object + void createLaser(); phx::Entity* laser_object_; SupportRod* rod_; };