bool LightScheme::GetLightIter(TracingInstance* pLocalData, const KVec2& samplePos, UINT32 lightIdx, const ShadingContext* shadingCtx, const IntersectContext* hit_ctx, LightIterator& out_iter) const { const ILightObject* pLightObj = GetLightPtr(lightIdx); KVec3 lightPos_f; KVec3d lightPos; KColor litClr; if (pLightObj->EvaluateLighting(samplePos, shadingCtx->position, lightPos_f, out_iter)) { lightPos = ToVec3d(lightPos_f); bool isOccluded = false; KColor transmission(out_iter.intensity); { KVec3d adjustedPos = ToVec3d(shadingCtx->position); KVec3d lightDir = lightPos - adjustedPos; float l_n = ToVec3f(lightDir) * shadingCtx->normal; float l_fn = ToVec3f(lightDir) * shadingCtx->face_normal; if (l_n > 0 && l_fn < 0) AdjustHitPos(pLocalData, *hit_ctx, *shadingCtx, adjustedPos); KVec3d temp_light_pos(lightPos); lightDir = adjustedPos - temp_light_pos; KRay ray; lightDir = temp_light_pos - adjustedPos; ray.Init(adjustedPos, lightDir, NULL); ray.mExcludeBBoxNode = hit_ctx->bbox_node_idx; ray.mExcludeTriID = hit_ctx->tri_id; KColor trans_coefficent; pLocalData->ComputeLightTransimission(ray, 1.0f, trans_coefficent); transmission.Modulate(trans_coefficent); } if (transmission.Luminance() > 0) { out_iter.intensity = transmission; return true; } } return false; }
bool LightScheme::GetLightIter(TracingInstance* pLocalData, const KVec2& samplePos, UINT32 lightIdx, const ShadingContext* shadingCtx, const IntersectContext* hit_ctx, LightIterator& out_iter) const { const ILightObject* pLightObj = GetLightPtr(lightIdx); KVec3 lightPos_f; KVec3d lightPos; KColor litClr; if (pLightObj->EvaluateLighting(samplePos, shadingCtx->position, lightPos_f, out_iter)) { lightPos = ToVec3d(lightPos_f); bool isOccluded = false; KColor transmission(out_iter.intensity); { KVec3d adjustedPos = ToVec3d(shadingCtx->position); KVec3d lightDir = lightPos - adjustedPos; float l_n = ToVec3f(lightDir) * shadingCtx->normal; float l_fn = ToVec3f(lightDir) * shadingCtx->face_normal; if (l_n > 0) { if (l_fn < 0) AdjustHitPos(pLocalData, *hit_ctx, *shadingCtx, adjustedPos); KVec3d temp_light_pos(lightPos); lightDir = adjustedPos - temp_light_pos; // Clamp the shadow ray if the light source is out of the scene's bounding box. // Doing so can improve the floating point precision. const KBBox& sceneBBox = pLocalData->GetScenePtr()->GetSceneBBox(); bool needClampRay = !sceneBBox.IsInside(ToVec3f(temp_light_pos)); if (needClampRay) { KRay ray; ray.Init(temp_light_pos, lightDir, NULL); double t0, t1; if (IntersectBBox(ray, sceneBBox, t0, t1)) { temp_light_pos = ray.GetOrg() + ray.GetDir() * t0; } } KRay ray; lightDir = adjustedPos - temp_light_pos; ray.Init(temp_light_pos, lightDir, NULL); ray.mExcludeBBoxNode = INVALID_INDEX; ray.mExcludeTriID = INVALID_INDEX; float lum = 1.0f; while (lum > 0) { IntersectContext test_ctx; test_ctx.ray_t = 1.0; isOccluded = pLocalData->CastRay(ray, test_ctx); if (isOccluded) { if (test_ctx.bbox_node_idx == hit_ctx->bbox_node_idx && test_ctx.tri_id == hit_ctx->tri_id) break; // Calculate how much light can pass through the hit surface KColor temp_trans; ShadingContext shading_context; pLocalData->CalcuShadingContext(ray, test_ctx, shading_context); TransContext& transCtx = pLocalData->GetCurrentTransCtxStorage(); pLocalData->ConvertToTransContext(test_ctx, shading_context, transCtx); shading_context.surface_shader->ShaderTransmission(transCtx, temp_trans); transmission.Modulate(temp_trans); lum = transmission.Luminance(); if (lum > 0.001f) { KVec3d go_dis = lightDir*test_ctx.ray_t; temp_light_pos += (go_dis * 1.00001); lightDir -= (go_dis * 0.9999); ray.Init(temp_light_pos, lightDir, NULL); ray.mExcludeBBoxNode = test_ctx.bbox_node_idx; ray.mExcludeTriID = test_ctx.tri_id; } else { transmission.Clear(); break; } } else break; } } else transmission.Clear(); } if (transmission.Luminance() > 0) { out_iter.intensity = transmission; return true; } } return false; }