Skip to content

Commit f9b3236

Browse files
committed
Some BDPT work
1 parent 75e3e51 commit f9b3236

File tree

3 files changed

+247
-23
lines changed

3 files changed

+247
-23
lines changed

App/CL/integrator_bdpt.cl

Lines changed: 167 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,24 +160,24 @@ KERNEL void GenerateLightVertices(
160160
n,
161161
n,
162162
0.f,
163+
selection_pdf * light_pdf,
163164
1.f,
164-
1.f,
165-
ke / (selection_pdf * light_pdf),
165+
100.f,//ke * fabs(dot(n, my_ray->d.xyz)) / selection_pdf * light_pdf,
166166
kLight,
167167
-1);
168168

169169
*my_count = 1;
170170
*my_vertex = v;
171171

172172
// Initlize path data
173-
my_path->throughput = make_float3(1.f, 1.f, 1.f);
173+
my_path->throughput = ke * fabs(dot(n, my_ray->d.xyz)) / selection_pdf * light_pdf;
174174
my_path->volume = -1;
175175
my_path->flags = 0;
176176
my_path->active = 0xFF;
177177
}
178178
}
179179

180-
KERNEL void SampleSurface(
180+
KERNEL void SampleSurface(
181181
// Ray batch
182182
GLOBAL ray const* rays,
183183
// Intersection data
@@ -361,7 +361,7 @@ KERNEL void SampleSurface(
361361
diffgeo.uv,
362362
pdf_fwd,
363363
0.f,
364-
throughput * t / bxdfpdf,
364+
my_prev_vertex->flow * t / bxdfpdf,
365365
kSurface,
366366
diffgeo.material_index);
367367

@@ -508,8 +508,8 @@ KERNEL void SampleSurface(
508508

509509
bool singular_light = Light_IsSingular(&scene.lights[light_idx]);
510510
bool singular_bxdf = Bxdf_IsSingular(&diffgeo);
511-
lightweight = singular_light ? 1.f : BalanceHeuristic(1, lightpdf, 1, lightbxdfpdf);
512-
bxdfweight = singular_bxdf ? 1.f : BalanceHeuristic(1, bxdfpdf, 1, bxdflightpdf);
511+
lightweight = singular_light ? 1.f : BalanceHeuristic(1, lightpdf * selection_pdf, 1, lightbxdfpdf);
512+
bxdfweight = singular_bxdf ? 1.f : BalanceHeuristic(1, bxdfpdf, 1, bxdflightpdf * selection_pdf);
513513

514514
float3 radiance = 0.f;
515515
float3 wo;
@@ -518,7 +518,7 @@ KERNEL void SampleSurface(
518518
{
519519
// Otherwise save some intersector cycles
520520
Ray_SetInactive(shadowrays + global_id);
521-
lightsamples[global_id] = 0;
521+
lightsamples[global_id] = 0;
522522
return;
523523
}
524524

@@ -527,15 +527,15 @@ KERNEL void SampleSurface(
527527
if (((singular_bxdf && !singular_light) || split < 0.5f) && bxdfpdf > 0.f)
528528
{
529529
wo = CRAZY_HIGH_DISTANCE * bxdfwo;
530-
le = Light_GetLe(light_idx, &scene, &diffgeo, &wo, TEXTURE_ARGS);
531530
float ndotwo = fabs(dot(diffgeo.n, normalize(wo)));
532-
radiance = 2.f * le * bxdfweight * throughput * bxdf * ndotwo / bxdfpdf;
531+
le = Light_GetLe(light_idx, &scene, &diffgeo, &wo, TEXTURE_ARGS);
532+
radiance = 2.f * bxdfweight * le * throughput * bxdf * ndotwo / bxdfpdf;
533533
}
534534

535535
if (((!singular_bxdf && singular_light) || split >= 0.5f) && lightpdf > 0.f)
536536
{
537537
wo = lightwo;
538-
float ndotwo = fabs(dot(diffgeo.n, normalize(wo)));
538+
float ndotwo = fabs(dot(diffgeo.n, normalize(wo)));
539539
radiance = 2.f * lightweight * le * Bxdf_Evaluate(&diffgeo, wi, normalize(wo), TEXTURE_ARGS) * throughput * ndotwo / lightpdf / selection_pdf;
540540
}
541541

@@ -546,7 +546,7 @@ KERNEL void SampleSurface(
546546
float3 shadow_ray_o = diffgeo.p + CRAZY_LOW_DISTANCE * diffgeo.n;
547547
float3 temp = diffgeo.p + wo - shadow_ray_o;
548548
float3 shadow_ray_dir = normalize(temp);
549-
float shadow_ray_length = length(temp);
549+
float shadow_ray_length = 0.999f * length(temp);
550550
int shadow_ray_mask = 0xFFFFFFFF;
551551

552552
Ray_Init(shadowrays + global_id, shadow_ray_o, shadow_ray_dir, shadow_ray_length, 0.f, shadow_ray_mask);
@@ -722,7 +722,7 @@ KERNEL void SampleSurface(
722722

723723
float3 connect_ray_o = eye_dg.p + CRAZY_LOW_DISTANCE * eye_dg.n;
724724
float3 temp = light_dg.p - connect_ray_o;
725-
float connect_ray_length = length(temp);
725+
float connect_ray_length = 0.999f * length(temp);
726726
float3 connect_ray_dir = eye_wo;
727727

728728
Ray_Init(&connection_rays[global_id], connect_ray_o, connect_ray_dir, connect_ray_length, 0.f, 0xFFFFFFFF);
@@ -863,6 +863,36 @@ KERNEL void GatherContributions(
863863
}
864864
}
865865

866+
KERNEL void GatherCausticContributions(
867+
int num_items,
868+
int width,
869+
int height,
870+
GLOBAL int const* restrict shadow_hits,
871+
GLOBAL float3 const* restrict contributions,
872+
GLOBAL float2 const* restrict image_plane_positions,
873+
GLOBAL float4* restrict output
874+
)
875+
{
876+
int global_id = get_global_id(0);
877+
878+
if (global_id < num_items)
879+
{
880+
// Start collecting samples
881+
{
882+
// If shadow ray didn't hit anything and reached skydome
883+
if (shadow_hits[global_id] == -1)
884+
{
885+
// Add its contribution to radiance accumulator
886+
float3 radiance = contributions[global_id];
887+
float2 uv = image_plane_positions[global_id];
888+
int x = clamp((int)(uv.x * width), 0, width - 1);
889+
int y = clamp((int)(uv.y * height), 0, height - 1);
890+
output[y * width + x].xyz += radiance;
891+
}
892+
}
893+
}
894+
}
895+
866896
// Restore pixel indices after compaction
867897
KERNEL void RestorePixelIndices(
868898
// Compacted indices
@@ -907,3 +937,127 @@ KERNEL void ApplyGammaAndCopyData(
907937
}
908938

909939

940+
INLINE void atomic_add_float(volatile __global float* addr, float val)
941+
{
942+
union {
943+
unsigned int u32;
944+
float f32;
945+
} next, expected, current;
946+
current.f32 = *addr;
947+
do {
948+
expected.f32 = current.f32;
949+
next.f32 = expected.f32 + val;
950+
current.u32 = atomic_cmpxchg((volatile __global unsigned int *)addr,
951+
expected.u32, next.u32);
952+
} while (current.u32 != expected.u32);
953+
}
954+
955+
KERNEL void ConnectCaustics(
956+
int num_items,
957+
int eye_vertex_index,
958+
GLOBAL PathVertex const* restrict light_subpath,
959+
GLOBAL int const* restrict light_subpath_length,
960+
GLOBAL Camera const* restrict camera,
961+
GLOBAL Material const* restrict materials,
962+
TEXTURE_ARG_LIST,
963+
GLOBAL ray* restrict connection_rays,
964+
GLOBAL float4* restrict contributions,
965+
GLOBAL float2* restrict image_plane_positions
966+
)
967+
{
968+
int global_id = get_global_id(0);
969+
970+
if (global_id >= num_items)
971+
return;
972+
973+
if (eye_vertex_index >= light_subpath_length[global_id])
974+
{
975+
contributions[global_id].xyz = 0.f;
976+
Ray_SetInactive(connection_rays + global_id);
977+
return;
978+
}
979+
980+
GLOBAL PathVertex const* my_light_vertex = light_subpath + BDPT_MAX_SUBPATH_LEN * global_id + eye_vertex_index;
981+
GLOBAL PathVertex const* my_prev_light_vertex = light_subpath + BDPT_MAX_SUBPATH_LEN * global_id + eye_vertex_index - 1;
982+
983+
DifferentialGeometry eye_dg;
984+
eye_dg.p = camera->p;
985+
eye_dg.n = camera->forward;
986+
eye_dg.ng = camera->forward;
987+
eye_dg.uv = 0.f;
988+
eye_dg.dpdu = GetOrthoVector(eye_dg.n);
989+
eye_dg.dpdv = cross(eye_dg.n, eye_dg.dpdu);
990+
DifferentialGeometry_CalculateTangentTransforms(&eye_dg);
991+
992+
DifferentialGeometry light_dg;
993+
light_dg.p = my_light_vertex->position;
994+
light_dg.n = my_light_vertex->shading_normal;
995+
light_dg.ng = my_light_vertex->geometric_normal;
996+
light_dg.uv = my_light_vertex->uv;
997+
light_dg.dpdu = GetOrthoVector(light_dg.n);
998+
light_dg.dpdv = cross(light_dg.dpdu, light_dg.n);
999+
light_dg.mat = materials[my_light_vertex->material_index];
1000+
light_dg.mat.fresnel = 1.f;
1001+
DifferentialGeometry_CalculateTangentTransforms(&light_dg);
1002+
1003+
float3 eye_wo = normalize(light_dg.p - eye_dg.p);
1004+
float3 light_wi = normalize(my_prev_light_vertex->position - light_dg.p);
1005+
float3 light_wo = -eye_wo;
1006+
1007+
float3 light_bxdf = Bxdf_Evaluate(&light_dg, light_wi, light_wo, TEXTURE_ARGS);
1008+
float light_pdf = Bxdf_GetPdf(&light_dg, light_wi, light_wo, TEXTURE_ARGS);
1009+
float light_dotnl = max(dot(light_dg.n, light_wo), 0.f);
1010+
1011+
float3 light_contribution = my_prev_light_vertex->flow * (light_bxdf) / my_light_vertex->pdf_forward;
1012+
1013+
//float w0 = camera_pdf / (camera_pdf + light_pdf);
1014+
//float w1 = light_pdf / (camera_pdf + light_pdf);
1015+
1016+
float dist = length(light_dg.p - eye_dg.p);
1017+
float3 val = (light_contribution) / (dist * dist);
1018+
contributions[global_id].xyz = REASONABLE_RADIANCE(val);
1019+
1020+
float connect_ray_length = 0.99f * length(light_dg.p - eye_dg.p);
1021+
float3 connect_ray_dir = eye_wo;
1022+
float3 connect_ray_o = eye_dg.p;
1023+
1024+
Ray_Init(connection_rays + global_id, connect_ray_o, connect_ray_dir, connect_ray_length, 0.f, 0xFFFFFFFF);
1025+
1026+
ray r;
1027+
r.o.xyz = eye_dg.p;
1028+
r.o.w = CRAZY_HIGH_DISTANCE;
1029+
r.d.xyz = eye_wo;
1030+
1031+
float3 v0, v1, v2, v3;
1032+
float2 ext = 0.5f * camera->dim;
1033+
v0 = camera->p + camera->focal_length * camera->forward - ext.x * camera->right - ext.y * camera->up;
1034+
v1 = camera->p + camera->focal_length * camera->forward + ext.x * camera->right - ext.y * camera->up;
1035+
v2 = camera->p + camera->focal_length * camera->forward + ext.x * camera->right + ext.y * camera->up;
1036+
v3 = camera->p + camera->focal_length * camera->forward - ext.x * camera->right + ext.y * camera->up;
1037+
1038+
float a, b;
1039+
float3 p;
1040+
if (IntersectTriangle(&r, v0, v1, v2, &a, &b))
1041+
{
1042+
p = (1.f - a - b) * v0 + a * v1 + b * v2;
1043+
}
1044+
else if (IntersectTriangle(&r, v0, v2, v3, &a, &b))
1045+
{
1046+
p = (1.f - a - b) * v0 + a * v2 + b * v3;
1047+
}
1048+
else
1049+
{
1050+
contributions[global_id].xyz = 0.f;
1051+
Ray_SetInactive(connection_rays + global_id);
1052+
return;
1053+
}
1054+
1055+
float3 imgp = p - v0;
1056+
float2 impuv;
1057+
impuv.x = clamp(dot(imgp, v1 - v0) / dot(v1 - v0, v1 - v0), 0.f, 1.f);
1058+
impuv.y = clamp(dot(imgp, v3 - v0) / dot(v3 - v0, v3 - v0), 0.f, 1.f);
1059+
image_plane_positions[global_id] = impuv;
1060+
}
1061+
1062+
1063+

App/Renderers/BDPT/bdptrenderer.cpp

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ namespace Baikal
113113
// Light samples collected
114114
// after surface shading
115115
CLWBuffer<float3> lightsamples;
116+
// Image plane coordinates for splatting
117+
CLWBuffer<float2> image_plane_positions;
116118
// RNG data
117119
CLWBuffer<std::uint32_t> random;
118120
CLWBuffer<std::uint32_t> sobolmat;
@@ -356,21 +358,28 @@ namespace Baikal
356358

357359
// Generate tile domain
358360
GenerateTileDomain(output_size, tile_origin, tile_size, tile_size);
359-
//std::vector<PathVertex> light_vertices(num_rays);
360-
//std::vector<int> light_length(num_rays);
361-
//m_context.ReadBuffer(0, m_render_data->light_subpath, &light_vertices[0], num_rays).Wait();
362-
//m_context.ReadBuffer(0, m_render_data->light_subpath_length, &light_length[0], num_rays).Wait();
361+
std::vector<PathVertex> light_vertices(num_rays);
362+
std::vector<int> light_length(num_rays);
363+
m_context.ReadBuffer(0, m_render_data->light_subpath, &light_vertices[0], num_rays).Wait();
364+
m_context.ReadBuffer(0, m_render_data->light_subpath_length, &light_length[0], num_rays).Wait();
365+
366+
//for (int c = 1; c < kMaxRandomWalkLength; ++c)
367+
{
368+
//ConnectDirect(clwscene, c, tile_size);
369+
}
363370

364371
for (int c = 1; c < kMaxRandomWalkLength; ++c)
372+
{
373+
for (int l = 1; l < kMaxRandomWalkLength; ++l)
365374
{
366-
ConnectDirect(clwscene, c, tile_size);
375+
Connect(clwscene, c, l, tile_size);
367376
}
377+
}
368378

369-
for (int c = 1; c < kMaxRandomWalkLength; ++c)
370-
for (int l = 1; l < kMaxRandomWalkLength; ++l)
371-
{
372-
Connect(clwscene, c, l, tile_size);
373-
}
379+
//for (int l = 1; l < 2; ++l)
380+
//{
381+
// ConnectCaustic(clwscene, l, tile_size);
382+
//}
374383

375384
IncrementSampleCounter(clwscene, tile_size);
376385

@@ -531,6 +540,62 @@ namespace Baikal
531540
}
532541
}
533542

543+
void BdptRenderer::ConnectCaustic(ClwScene const& scene, int light_vertex_index, int2 const& tile_size)
544+
{
545+
m_context.FillBuffer(0, m_render_data->shadowhits, 1, m_render_data->shadowhits.GetElementCount());
546+
547+
548+
int num_rays = tile_size.x * tile_size.y;
549+
auto output = static_cast<ClwOutput*>(GetOutput(OutputType::kColor));
550+
551+
{
552+
// Fetch kernel
553+
CLWKernel connect_kernel = m_render_data->program.GetKernel("ConnectCaustics");
554+
555+
int argc = 0;
556+
connect_kernel.SetArg(argc++, num_rays);
557+
connect_kernel.SetArg(argc++, light_vertex_index);
558+
connect_kernel.SetArg(argc++, m_render_data->light_subpath);
559+
connect_kernel.SetArg(argc++, m_render_data->light_subpath_length);
560+
connect_kernel.SetArg(argc++, scene.camera);
561+
connect_kernel.SetArg(argc++, scene.materials);
562+
connect_kernel.SetArg(argc++, scene.textures);
563+
connect_kernel.SetArg(argc++, scene.texturedata);
564+
connect_kernel.SetArg(argc++, m_render_data->shadowrays);
565+
connect_kernel.SetArg(argc++, m_render_data->lightsamples);
566+
connect_kernel.SetArg(argc++, m_render_data->image_plane_positions);
567+
568+
// Run generation kernel
569+
{
570+
int globalsize = num_rays;
571+
m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, connect_kernel);
572+
}
573+
}
574+
575+
m_scene_controller.GetIntersectionApi()
576+
->QueryOcclusion(m_render_data->fr_shadowrays, num_rays, m_render_data->fr_shadowhits, nullptr, nullptr);
577+
578+
579+
{
580+
CLWKernel gather_kernel = m_render_data->program.GetKernel("GatherCausticContributions");
581+
582+
int argc = 0;
583+
gather_kernel.SetArg(argc++, num_rays);
584+
gather_kernel.SetArg(argc++, output->width());
585+
gather_kernel.SetArg(argc++, output->height());
586+
gather_kernel.SetArg(argc++, m_render_data->shadowhits);
587+
gather_kernel.SetArg(argc++, m_render_data->lightsamples);
588+
gather_kernel.SetArg(argc++, m_render_data->image_plane_positions);
589+
gather_kernel.SetArg(argc++, output->data());
590+
591+
// Run generation kernel
592+
{
593+
int globalsize = num_rays;
594+
m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, gather_kernel);
595+
}
596+
}
597+
}
598+
534599
void BdptRenderer::GenerateTileDomain(int2 const& output_size, int2 const& tile_origin,
535600
int2 const& tile_size, int2 const& subtile_size)
536601
{
@@ -702,6 +767,9 @@ namespace Baikal
702767
m_render_data->lightsamples = m_context.CreateBuffer<float3>(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE);
703768
m_vidmemws += output.width() * output.height() * sizeof(float3)* kMaxLightSamples;
704769

770+
m_render_data->image_plane_positions = m_context.CreateBuffer<float2>(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE);
771+
m_vidmemws += output.width() * output.height() * sizeof(float2)* kMaxLightSamples;
772+
705773
m_render_data->paths = m_context.CreateBuffer<PathState>(output.width() * output.height(), CL_MEM_READ_WRITE);
706774
m_vidmemws += output.width() * output.height() * sizeof(PathState);
707775

App/Renderers/BDPT/bdptrenderer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ namespace Baikal
110110
void Connect(ClwScene const& scene, int eye_vertex_index, int light_vertex_index, int2 const& tile_size);
111111
// Connect eye vetices directly to light sources
112112
void ConnectDirect(ClwScene const& scene, int eye_vertex_index, int2 const& tile_size);
113+
// Connect light vetices directly to the eye
114+
void ConnectCaustic(ClwScene const& scene, int light_vertex_index, int2 const& tile_size);
113115
// Increment sample counter for a tile
114116
void IncrementSampleCounter(ClwScene const& scene, int2 const& tile_size);
115117

0 commit comments

Comments
 (0)