void LocalTRSFrame::TransformRay(KRay& out_ray, const KRay& in_ray, const LocalTRSFrame::LclTRS& trs) { KMatrix4 inv_trs = trs.trs.getInverse(); KVec3d newOrig; Vec3TransformCoord(newOrig, in_ray.GetOrg(), inv_trs); KVec3d oldDst = in_ray.GetOrg() + in_ray.GetDir(); KVec3d newDst; Vec3TransformCoord(newDst, oldDst, inv_trs); KVec3d newDir = newDst - newOrig; out_ray.Init(newOrig, newDir, NULL); }
bool CalcuShadingByRay(TracingInstance* pLocalData, const KRay& ray, KColor& out_clr, IntersectContext* out_ctx/* = NULL*/) { const LightScheme* pLightScheme = LightScheme::GetInstance(); const KAccelStruct_BVH* pScene = pLocalData->GetScenePtr(); UINT32 rayBounceDepth = pLocalData->GetBoundDepth(); // Check the maximum bounce depth if (rayBounceDepth >= MAX_REFLECTION_BOUNCE) { out_clr = pLocalData->GetBackGroundColor(ToVec3f(ray.GetDir())); return false; } pLocalData->IncBounceDepth(); IntersectContext hit_ctx; if (out_ctx) { hit_ctx.bbox_node_idx = out_ctx->bbox_node_idx; hit_ctx.kd_leaf_idx = out_ctx->kd_leaf_idx; } bool res = false; bool isHit = false; KColor irradiance; if ((pLocalData->CastRay(ray, hit_ctx))) isHit = true; out_clr.Clear(); if (isHit) { // This ray hits something, shade the ray sample by surface shader of the hit object. // if (out_ctx) *out_ctx = hit_ctx; // Calculate the data in shading context ShadingContext shadingCtx; pLocalData->CalcuShadingContext(ray, hit_ctx, shadingCtx); if (shadingCtx.surface_shader) { if (shadingCtx.surface_shader->mNormalMap && shadingCtx.hasUV) { KVec4 samp_res; samp_res = shadingCtx.surface_shader->mNormalMap->SampleBilinear(shadingCtx.uv.uv); KVec3 normal = shadingCtx.tangent.tangent * (samp_res[0] *2.0f - 1.0f); normal += (shadingCtx.tangent.binormal * (samp_res[1] * 2.0f - 1.0f)); normal += (shadingCtx.normal * (samp_res[2] * 2.0f - 1.0f)); nvmath::normalize(normal); float irrad_scale = 1.0f; irrad_scale = normal * shadingCtx.normal; irradiance.Scale(irrad_scale); shadingCtx.normal = normal; } out_clr = irradiance; pLightScheme->Shade(pLocalData, shadingCtx, hit_ctx, out_clr); res = true; } else { // No surface shader? just output its normal out_clr.r = shadingCtx.normal[0] * 0.5f + 0.5f; out_clr.g = shadingCtx.normal[1] * 0.5f + 0.5f; out_clr.b = shadingCtx.normal[2] * 0.5f + 0.5f; } } else { // This ray hits nothing, so it should evaluate the environment shader to determine current color of the ray sample. // const KEnvShader* pEnvShader = KEnvShader::GetEnvShader(); if (pEnvShader) { KVec3 n_ray_dir = ToVec3f(ray.GetDir()); n_ray_dir.normalize(); *pLocalData->mEvnContext.pos = ToVec3f(ray.GetOrg()); *pLocalData->mEvnContext.dir = n_ray_dir; pEnvShader->Sample(pLocalData->mEvnContext, out_clr); } } pLocalData->DecBounceDepth(); return res; }
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; }