bool CalcRefractedRay(TracingInstance* pLocalData, const ShadingContext& shadingCtx, float refractRatio, KColor& refractColor) { KRay transRay; // TODO: implement the refraction computation transRay.InitTranslucentRay(shadingCtx, NULL); return CalcuShadingByRay(pLocalData, transRay, refractColor, NULL); }
bool CalcSecondaryRay(TracingInstance* pLocalData, const KVec3& org, UINT32 excludingBBox, UINT32 excludingTri, const KVec3& ray_dir, KColor& out_clr) { KRay secondaryRay; secondaryRay.Init(ToVec3d(org), ToVec3d(ray_dir), NULL); secondaryRay.mExcludeBBoxNode = excludingBBox; secondaryRay.mExcludeTriID = excludingTri; return CalcuShadingByRay(pLocalData, secondaryRay, out_clr, NULL); }
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 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; }
void TracingInstance::CalcuShadingContext(const KRay& hitRay, const IntersectContext& hit_ctx, ShadingContext& out_shading_ctx) const { const KSceneSet* pPlainScene = mpScene->GetSource(); const KScene* pKDScene = pPlainScene->GetNodeKDScene(hit_ctx.bbox_node_idx); KAnimation::LocalTRSFrame::LclTRS nodeTRS; pPlainScene->GetNodeTransform(nodeTRS, hit_ctx.bbox_node_idx, mCameraContext.inMotionTime); const nvmath::Mat33f scene_rot = nodeTRS.trs.getRotation(); const nvmath::Mat44f scene_trans = nodeTRS.trs.getMatrix(); const KTriDesc* pTri = mpScene->GetAccelTriData(hit_ctx.bbox_node_idx, hit_ctx.tri_id); UINT32 mesh_idx = pTri->GetMeshIdx(); UINT32 node_idx = pTri->GetNodeIdx(); UINT32 tri_idx = pTri->mTriIdx; const KTriMesh* pMesh = pKDScene->GetMesh(mesh_idx); const KNode* pNode = pKDScene->GetNode(node_idx); const UINT32* pn_idx = pMesh->mFaces[tri_idx].pn_idx; out_shading_ctx.tracing_instance = this; out_shading_ctx.excluding_bbox = hit_ctx.bbox_node_idx; out_shading_ctx.excluding_tri = hit_ctx.tri_id; assert(out_shading_ctx.excluding_bbox < NOT_HIT_INDEX); assert(out_shading_ctx.excluding_tri < NOT_HIT_INDEX); KTriMesh::PN_Data pn_vert[3]; pMesh->ComputePN_Data(pn_vert[0], pMesh->mFaces[tri_idx].pn_idx[0], mCameraContext.inMotionTime); pMesh->ComputePN_Data(pn_vert[1], pMesh->mFaces[tri_idx].pn_idx[1], mCameraContext.inMotionTime); pMesh->ComputePN_Data(pn_vert[2], pMesh->mFaces[tri_idx].pn_idx[2], mCameraContext.inMotionTime); if (!pMesh->mTexFaces.empty()) { KTriMesh::TT_Data tt_data; pMesh->InterpolateTT(tri_idx, hit_ctx, tt_data, mCameraContext.inMotionTime); out_shading_ctx.uv.uv = tt_data.texcoord; out_shading_ctx.tangent.tangent = tt_data.tangent; out_shading_ctx.tangent.binormal = tt_data.binormal; out_shading_ctx.hasUV = 1; } else out_shading_ctx.hasUV = 0; KVec3 temp_vec; // interpolate the normal temp_vec = pn_vert[0].nor * hit_ctx.w + pn_vert[1].nor * hit_ctx.u + pn_vert[2].nor * hit_ctx.v; out_shading_ctx.normal = temp_vec * pNode->GetObjectRot(); temp_vec = out_shading_ctx.normal * scene_rot; out_shading_ctx.normal = temp_vec; float rcp_len_nor = 1.0f / nvmath::length(temp_vec); out_shading_ctx.normal *= rcp_len_nor; // interpolate the position out_shading_ctx.position = pn_vert[0].pos * hit_ctx.w + pn_vert[1].pos * hit_ctx.u + pn_vert[2].pos * hit_ctx.v; Vec3TransformCoord(temp_vec, out_shading_ctx.position, pNode->GetObjectTM()); Vec3TransformCoord(out_shading_ctx.position, temp_vec, scene_trans); const nvmath::Mat33f world_rot = nvmath::Mat33f(pNode->GetObjectRot()) * scene_rot; KVec3 edge[3]; edge[0] = (pn_vert[1].pos - pn_vert[0].pos) * world_rot; edge[1] = (pn_vert[2].pos - pn_vert[1].pos) * world_rot; edge[2] = (pn_vert[0].pos - pn_vert[2].pos) * world_rot; float edge_len_sqr[3]; edge_len_sqr[0] = nvmath::lengthSquared(edge[0]); edge_len_sqr[1] = nvmath::lengthSquared(edge[1]); edge_len_sqr[2] = nvmath::lengthSquared(edge[2]); float edge_len[3]; edge_len[0] = sqrt(edge_len_sqr[0]); edge_len[1] = sqrt(edge_len_sqr[1]); edge_len[2] = sqrt(edge_len_sqr[2]); // Calculate the face normal and triangle size out_shading_ctx.face_size = edge_len[0] + edge_len[1] + edge_len[2]; out_shading_ctx.face_size *= 0.05f; // Move the shading position along it normal for a epsilon distance. out_shading_ctx.position += (out_shading_ctx.normal * out_shading_ctx.face_size * 0.0001f); KVec3 face_nor; face_nor = edge[0] ^ edge[1]; out_shading_ctx.face_normal = face_nor; out_shading_ctx.face_normal.normalize(); KVec3d rayDir = hitRay.GetDir(); rayDir.normalize(); // Normalize the ray direction because it's not normalized // Get the surface shader ISurfaceShader* pSurfShader = pNode->mpSurfShader; out_shading_ctx.surface_shader = pSurfShader; out_shading_ctx.out_vec = ToVec3f(-rayDir); }
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 CalcReflectedRay(TracingInstance* pLocalData, const ShadingContext& shadingCtx, KColor& reflectColor) { KRay reflectRay; reflectRay.InitReflectionRay(shadingCtx, shadingCtx.out_vec, NULL); return CalcuShadingByRay(pLocalData, reflectRay, reflectColor, NULL); }
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; }