From 33071285835bb519557ca3dbb39ac1d541b103f2 Mon Sep 17 00:00:00 2001 From: frol-msu-white-linux Date: Mon, 4 Feb 2019 17:19:37 +0300 Subject: [PATCH] fix assymetrical light transport for glass (refraction) --- hydra_app/input.cpp | 6 ++++-- hydra_drv/CPUExp_IntegratorSSS.cpp | 6 +++--- hydra_drv/CPUExp_Integrators.h | 2 +- hydra_drv/CPUExp_Integrators_Common.cpp | 4 ++-- hydra_drv/CPUExp_Integrators_MMLT.cpp | 4 ++-- hydra_drv/CPUExp_bxdf.h | 2 +- hydra_drv/cmaterial.h | 22 +++++++++++++++------- hydra_drv/shaders/material.cl | 2 +- hydra_drv/shaders/mlt.cl | 4 ++-- 9 files changed, 31 insertions(+), 21 deletions(-) diff --git a/hydra_app/input.cpp b/hydra_app/input.cpp index a3030ce..650cd15 100644 --- a/hydra_app/input.cpp +++ b/hydra_app/input.cpp @@ -13,7 +13,7 @@ Input::Input() //noWindow = false; ///< run 'console_main', else run 'window_main' //inLibraryPath = "tests/test_42"; ///< cornell box with teapot //inLibraryPath = "tests/test_223_small"; ///< cornell box with sphere - inLibraryPath = "tests/test_224_sphere"; + //inLibraryPath = "tests/test_224_sphere"; //inLibraryPath = "tests/test_224_sphere_microfacet"; //inLibraryPath = "/media/frol/886234F06234E49A/scenes/benchmark4"; ///< cornell box with mirror glossy back wall //inLibraryPath = "/media/frol/886234F06234E49A/scenes/phong_test/torspar1"; @@ -31,13 +31,15 @@ Input::Input() //inLibraryPath = "D:/[archive]/2017/HydraAPP/hydra_app/tests/hydra_benchmark_07"; //inLibraryPath = "D:/[archive]/2017/HydraOldRepo/HydraAPP/home/frol/hydra/rendered_images/a_3602.png/hydra_app/tests/hydra_benchmark_07"; //inLibraryPath = "/home/frol/PROG/HydraAPI/main/tests/test_77"; - //inLibraryPath = "/home/frol/PROG/HydraAPI/main/tests_f/test_202"; + inLibraryPath = "/home/frol/PROG/HydraAPI/main/tests_f/test_403"; //inLibraryPath = "C:/[Hydra]/pluginFiles/scenelib"; //inLibraryPath = "/media/frol/6E0467C0046789C3/[Hydra]/pluginFiles/scenelib"; //inLibraryPath = "D:/temp/scenelib/"; //inLibraryPath = "/home/frol/PROG/HydraAPI/main/tests/test_76"; //inLibraryPath = "/home/frol/temp/scenelib"; + //inLibraryPath = "/home/frol/temp/scenelib_thinSphere"; + //inLibraryPath = "/home/frol/PROG/HydraCore/hydra_app/tests/test_pool"; inDevelopment = true; ///< recompile shaders each time; note that nvidia have their own shader cache! inDeviceId = 0; ///< opencl device id diff --git a/hydra_drv/CPUExp_IntegratorSSS.cpp b/hydra_drv/CPUExp_IntegratorSSS.cpp index 09d4a4d..7528dbf 100644 --- a/hydra_drv/CPUExp_IntegratorSSS.cpp +++ b/hydra_drv/CPUExp_IntegratorSSS.cpp @@ -103,7 +103,7 @@ std::tuple IntegratorStupidPTSSS::sampleAndEvalBxDF(floa return std::make_tuple(res, 0, float3(1, 1, 1)); } else - return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, shadow); + return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, false, shadow); } float3 SampleHenyeyGreenstein(const float g, const float e1, const float e2) @@ -303,7 +303,7 @@ std::tuple IntegratorShadowPTSSS::sampleAndEvalBxDF(floa return std::make_tuple(res, 0, float3(1, 1, 1)); } else - return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, shadow); + return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, false, shadow); } @@ -537,7 +537,7 @@ std::tuple IntegratorShadowPTSSS::sampleAndEvalBxDF(floa return std::make_tuple(res, 0, float3(1, 1, 1)); } else - return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, shadow); + return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, false, shadow); } float3 IntegratorShadowPTSSS::PathTrace(float3 ray_pos, float3 ray_dir, MisData misPrev, int a_currDepth, uint flags) diff --git a/hydra_drv/CPUExp_Integrators.h b/hydra_drv/CPUExp_Integrators.h index 3f90950..912945d 100644 --- a/hydra_drv/CPUExp_Integrators.h +++ b/hydra_drv/CPUExp_Integrators.h @@ -250,7 +250,7 @@ class IntegratorCommon : public Integrator virtual std::tuple makeEyeRay3(float4 lensOffs); float3 emissionEval(float3 ray_pos, float3 ray_dir, const SurfaceHit& surfElem, uint flags, const MisData misPrev, const int a_instId); - virtual std::tuple sampleAndEvalBxDF(float3 ray_dir, const SurfaceHit& surfElem, uint flags = 0, float3 shadow = float3(0,0,0), bool mmltMode = false); + virtual std::tuple sampleAndEvalBxDF(float3 ray_dir, const SurfaceHit& surfElem, uint flags = 0, bool a_fwdDir = false, float3 shadow = float3(0,0,0), bool mmltMode = false); GBufferAll gbufferSample(float3 ray_pos, float3 ray_dir); diff --git a/hydra_drv/CPUExp_Integrators_Common.cpp b/hydra_drv/CPUExp_Integrators_Common.cpp index 143df7f..4217b7b 100644 --- a/hydra_drv/CPUExp_Integrators_Common.cpp +++ b/hydra_drv/CPUExp_Integrators_Common.cpp @@ -532,7 +532,7 @@ RandomGen& IntegratorCommon::randomGen() return m_perThread[omp_get_thread_num()].gen; } -std::tuple IntegratorCommon::sampleAndEvalBxDF(float3 ray_dir, const SurfaceHit& surfElem, uint flags, float3 shadow, bool a_mmltMode) +std::tuple IntegratorCommon::sampleAndEvalBxDF(float3 ray_dir, const SurfaceHit& surfElem, uint flags, bool a_fwdDir, float3 shadow, bool a_mmltMode) { const PlainMaterial* pHitMaterial = materialAt(m_pGlobals, m_matStorage, surfElem.matId); auto& gen = randomGen(); @@ -552,7 +552,7 @@ std::tuple IntegratorCommon::sampleAndEvalBxDF(float3 ra allRands); MatSample brdfSample; int matOffset; - MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfElem, ray_dir, shadow, flags, + MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfElem, ray_dir, shadow, flags, a_fwdDir, m_pGlobals, m_texStorage, m_texStorageAux, &m_ptlDummy, &brdfSample, &matOffset); diff --git a/hydra_drv/CPUExp_Integrators_MMLT.cpp b/hydra_drv/CPUExp_Integrators_MMLT.cpp index 64fcd0a..bfa7bf6 100644 --- a/hydra_drv/CPUExp_Integrators_MMLT.cpp +++ b/hydra_drv/CPUExp_Integrators_MMLT.cpp @@ -703,7 +703,7 @@ void IntegratorMMLT::TraceLightPath(float3 ray_pos, float3 ray_dir, int a_currDe a_perThread->pdfArray[a_currDepth].pdfFwd = -1.0f*GTermPrev; const PlainMaterial* pHitMaterial = materialAt(m_pGlobals, m_matStorage, surfElem.matId); - const MatSample matSam = std::get<0>(sampleAndEvalBxDF(ray_dir, surfElem, packBounceNum(0, a_currDepth - 1), float3(0, 0, 0), true)); + const MatSample matSam = std::get<0>(sampleAndEvalBxDF(ray_dir, surfElem, packBounceNum(0, a_currDepth - 1), true, float3(0, 0, 0), true)); // calc new ray // @@ -869,7 +869,7 @@ PathVertex IntegratorMMLT::CameraPath(float3 ray_pos, float3 ray_dir, MisData a_ // (3) eval reverse and forward pdfs // const PlainMaterial* pHitMaterial = materialAt(m_pGlobals, m_matStorage, surfElem.matId); - const MatSample matSam = std::get<0>(sampleAndEvalBxDF(ray_dir, surfElem, packBounceNum(0, a_currDepth - 1), float3(0, 0, 0), true)); + const MatSample matSam = std::get<0>(sampleAndEvalBxDF(ray_dir, surfElem, packBounceNum(0, a_currDepth - 1), false, float3(0, 0, 0), true)); const float3 bxdfVal = matSam.color; // *(1.0f / fmaxf(matSam.pdf, 1e-20f)); const float cosNext = fabs(dot(matSam.direction, surfElem.normal)); diff --git a/hydra_drv/CPUExp_bxdf.h b/hydra_drv/CPUExp_bxdf.h index cad823f..ea3ef11 100644 --- a/hydra_drv/CPUExp_bxdf.h +++ b/hydra_drv/CPUExp_bxdf.h @@ -323,7 +323,7 @@ std::tuple IntegratorShadowPTSSS::sampleAndEvalGGXBxDF(f return std::make_tuple(res, 0, float3(1, 1, 1)); } else - return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, shadow); + return IntegratorCommon::sampleAndEvalBxDF(ray_dir, surfElem, flags, false, shadow); } diff --git a/hydra_drv/cmaterial.h b/hydra_drv/cmaterial.h index 66ea96c..30e1943 100644 --- a/hydra_drv/cmaterial.h +++ b/hydra_drv/cmaterial.h @@ -490,6 +490,7 @@ typedef struct RefractResultT float3 ray_dir; bool success; + float eta; }RefractResult; @@ -522,11 +523,15 @@ static inline RefractResult myrefract(float3 ray_dir, float3 a_normal, float a_m RefractResult res; res.ray_dir = ray_dir; res.success = refrSuccess; + if (refrSuccess) + res.eta = eta; + else + res.eta = 1.0f; return res; } -static inline void GlassSampleAndEvalBRDF(__global const PlainMaterial* a_pMat, const float3 rands, const float3 ray_dir, float3 a_normal, const float2 a_texCoord, const bool a_hitFromInside, - __global const EngineGlobals* a_globals, texture2d_t a_tex, __private const ProcTextureList* a_ptList, +static inline void GlassSampleAndEvalBRDF(__global const PlainMaterial* a_pMat, const float3 rands, const float3 ray_dir, float3 a_normal, const float2 a_texCoord, const bool a_hitFromInside, + __global const EngineGlobals* a_globals, texture2d_t a_tex, __private const ProcTextureList* a_ptList, const bool a_isFwdDir, __private MatSample* a_out) { const float3 normal2 = a_hitFromInside ? (-1.0f)*a_normal : a_normal; @@ -555,10 +560,13 @@ static inline void GlassSampleAndEvalBRDF(__global const PlainMaterial* a_pMat, const float cosThetaOut = dot(refractData.ray_dir, a_normal); const float cosMult = 1.0f / fmax(fabs(cosThetaOut), 1e-6f); + // only camera paths are multiplied by this factor, and etas + // are swapped because radiance flows in the opposite direction + const float adjointBsdfMult = a_isFwdDir ? 1.0f : refractData.eta*refractData.eta; // see SmallVCM and or Veach adjoint bsdf a_out->direction = refractData.ray_dir; a_out->pdf = pdf; - a_out->color = refractData.success ? fVal*clamp(glassGetColor(a_pMat)*texColor, 0.0f, 1.0f)*cosMult : make_float3(1.0f, 1.0f, 1.0f)*cosMult; + a_out->color = refractData.success ? fVal*clamp(glassGetColor(a_pMat)*texColor, 0.0f, 1.0f)*cosMult*adjointBsdfMult : make_float3(1.0f, 1.0f, 1.0f)*cosMult; if(spec) a_out->flags = (RAY_EVENT_S | RAY_EVENT_T); @@ -1304,7 +1312,7 @@ static inline float3 BumpMapping(const float3 tangent, const float3 bitangent, c return normalize(mul3x3x3(inverse(tangentTransform), normalTS)); } -static inline void MaterialLeafSampleAndEvalBRDF(__global const PlainMaterial* pMat, __private const SurfaceHit* pSurfHit, const float3 ray_dir, const float3 rands, const float3 a_shadow, +static inline void MaterialLeafSampleAndEvalBRDF(__global const PlainMaterial* pMat, __private const SurfaceHit* pSurfHit, const float3 ray_dir, const float3 rands, const float3 a_shadow, const bool a_isFwdDir, __global const EngineGlobals* a_globals, texture2d_t a_tex, texture2d_t a_texNormal, __private const ProcTextureList* a_ptList, __private MatSample* a_out) { @@ -1348,7 +1356,7 @@ static inline void MaterialLeafSampleAndEvalBRDF(__global const PlainMaterial* p a_out); break; case PLAIN_MAT_CLASS_GLASS: - GlassSampleAndEvalBRDF(pMat, rands, ray_dir, hitNorm, pSurfHit->texCoord, pSurfHit->hfi, a_globals, a_tex, a_ptList, + GlassSampleAndEvalBRDF(pMat, rands, ray_dir, hitNorm, pSurfHit->texCoord, pSurfHit->hfi, a_globals, a_tex, a_ptList, a_isFwdDir, a_out); break; @@ -1399,7 +1407,7 @@ Sample and eval layered material (with blends). Store result in a_out. */ static inline void MaterialSampleAndEvalBxDF(__global const PlainMaterial* pMat, __private float a_rands[MMLT_FLOATS_PER_BOUNCE], - __private const SurfaceHit* pSurfHit, const float3 a_rayDir, const float3 a_shadow, const uint rayFlags, + __private const SurfaceHit* pSurfHit, const float3 a_rayDir, const float3 a_shadow, const uint rayFlags, const bool a_isFwdDir, __global const EngineGlobals* a_globals, texture2d_t a_tex, texture2d_t a_texNormal, __private const ProcTextureList* a_ptList, __private MatSample* a_out, __private int* pLocalOffset) { @@ -1413,7 +1421,7 @@ static inline void MaterialSampleAndEvalBxDF(__global const PlainMaterial* pMat, __global const PlainMaterial* pMatLeaf = pMat + mixSelector.localOffs; (*pLocalOffset) = mixSelector.localOffs; - MaterialLeafSampleAndEvalBRDF(pMatLeaf, pSurfHit, a_rayDir, make_float3(a_rands[0], a_rands[1], a_rands[2]), a_shadow, + MaterialLeafSampleAndEvalBRDF(pMatLeaf, pSurfHit, a_rayDir, make_float3(a_rands[0], a_rands[1], a_rands[2]), a_shadow, a_isFwdDir, a_globals, a_tex, a_texNormal, a_ptList, a_out); diff --git a/hydra_drv/shaders/material.cl b/hydra_drv/shaders/material.cl index 2049482..c4ac32a 100644 --- a/hydra_drv/shaders/material.cl +++ b/hydra_drv/shaders/material.cl @@ -831,7 +831,7 @@ __kernel void NextBounce(__global float4* restrict a_rpos, const float3 shadowVal = decompressShadow(in_shadow[tid]); MatSample brdfSample; int localOffset = 0; - MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfHit, ray_dir, shadowVal, flags, + MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfHit, ray_dir, shadowVal, flags, ((a_globals->g_flags & HRT_FORWARD_TRACING) != 0), a_globals, in_texStorage1, in_texStorage2, &ptl, &brdfSample, &localOffset); diff --git a/hydra_drv/shaders/mlt.cl b/hydra_drv/shaders/mlt.cl index 31d64a5..24a1a21 100644 --- a/hydra_drv/shaders/mlt.cl +++ b/hydra_drv/shaders/mlt.cl @@ -819,7 +819,7 @@ __kernel void MMLTCameraPathBounce(__global float4* restrict a_rpos, int matOffset = materialOffset(a_globals, surfElem.matId); MatSample matSam; int localOffset = 0; - MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfElem, ray_dir, make_float3(1,1,1), flags, + MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfElem, ray_dir, make_float3(1,1,1), flags, false, a_globals, in_texStorage1, in_texStorage2, &ptl, &matSam, &localOffset); @@ -1101,7 +1101,7 @@ __kernel void MMLTLightPathBounce (__global float4* restrict a_rpos, int matOffset = materialOffset(a_globals, surfElem.matId); MatSample matSam; int localOffset = 0; - MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfElem, ray_dir, make_float3(1,1,1), flags, + MaterialSampleAndEvalBxDF(pHitMaterial, allRands, &surfElem, ray_dir, make_float3(1,1,1), flags, true, a_globals, in_texStorage1, in_texStorage2, &ptl, &matSam, &localOffset);