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);
}
Example #2
0
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;
}