// `計算點光源, 它和頂點位置, 頂點面向, 光源位置, 光源方向, 光柱交角有關.` void CalculateSpotLight(Vertex_VCN *pVertices, int num_vertices) { float fSpotLightCutoffCos = FastMath::Cos( FastMath::DegreeToRadian(g_fSpotLightCutoff) ); for ( int i=0; i<num_vertices; i++ ) { // `求出轉換後在世界座標系的頂點位置` Vector4 vPosition = pVertices[i].m_Position * g_world_matrix; // `求出轉換後在世界座標系的頂點面向, RotateVector函式只做旋轉, 忽略位移.` Vector4 vNormal = g_world_matrix.RotateVector(pVertices[i].m_Normal); // `計算出頂點位置到光源的方向跟長度` Vector4 vVertex_to_Light = g_vLightPosition - vPosition; float light_distance = vVertex_to_Light.NormalizeAndGetLength(); // `頂點面向跟光線方向的交角, 可以決定反射光的強度.` Vector4 vCosine = Vector3Dot(g_vLightDirection, vVertex_to_Light); // `把vCosine局限在永遠大於0的范圍` vCosine.Clamp_to_0(); float fCosine = vCosine.GetX(); if ( fCosine >= fSpotLightCutoffCos ) { // `頂點跟光線的交角小於fSpotightCutoffCos時, 才落在光柱范圍內.` Vector4 vDistance(1.0f, light_distance, light_distance * light_distance); // `g_vLightAttenuation里記錄了計算衰減公式1/(a + b*d + c*d^2)里的(a,b,c)` // `Vector3Dot(vDistance, g_vLightAttenuation) = (a,b,c) dot (1,d,d^2) = (a + b*d + c*d^2)` Vector4 vAttenuation = Vector3Dot(vDistance, g_vLightAttenuation); // `比較靠近光柱外圍部分的頂點, 光線會衰減.` float fFalloff = pow(fCosine, g_fSpotLightExponent); Vector4 vIntensity = Vector3Dot(vNormal, vVertex_to_Light); pVertices[i].m_Color += fFalloff * vIntensity * g_vLightColor / vAttenuation; pVertices[i].m_Color.Clamp_to_1(); } } }
// `計算點光源, 它和頂點位置, 頂點面向, 光源位置有關.` void CalculatePointLight(Vertex_VCN *pVertices, int num_vertices) { for ( int i=0; i<num_vertices; i++ ) { // `求出轉換後在世界座標系的頂點位置` Vector4 vPosition = pVertices[i].m_Position * g_world_matrix; // `求出轉換後在世界座標系的頂點面向, RotateVector函式只做旋轉, 忽略位移.` Vector4 vNormal = g_world_matrix.RotateVector(pVertices[i].m_Normal); // `計算出頂點位置到光源的方向跟長度` Vector4 vVertex_to_Light = g_vLightPosition - vPosition; float light_distance = vVertex_to_Light.NormalizeAndGetLength(); // `vDistance用來計算光線隨距離衰減公式中1/(a*1 + b*d + c*d^2)分母的(1, d, d^2)` Vector4 vDistance(1.0f, light_distance, light_distance * light_distance); // `g_vLightAttenuation里記錄了計算衰減公式1/(a + b*d + c*d^2)里的(a,b,c)` // `Vector3Dot(vDistance, g_vLightAttenuation) = (a,b,c) dot (1,d,d^2) = (a + b*d + c*d^2)` Vector4 vAttenuation = Vector3Dot(vDistance, g_vLightAttenuation); // `頂點面向跟光線方向的交角, 決定反射光的強度.` Vector4 vIntensity = Vector3Dot(vNormal, vVertex_to_Light); // `把intensity局限在永遠大於0的范圍` vIntensity.Clamp_to_0(); // `累加上隨距離衰減的光線強度` pVertices[i].m_Color += vIntensity * g_vLightColor / vAttenuation; pVertices[i].m_Color.Clamp_to_1(); } }
int KFixedTrackMissileProcessor::Start(double fTime, KRLMissile* pRLMissile) { HRESULT hr = E_FAIL; int nRetCode = false; KSkill const* pSkill = NULL; float fDistance = 0.0f; float fBulletVelocity = 0.0f; D3DXVECTOR3 vDistance(0.0f, 0.0f, 0.0f); D3DXVECTOR3 vPositionTarget(0.0f, 0.0f, 0.0f); D3DXQUATERNION qRotationTarget; D3DXQUATERNION qRotationCaster; ASSERT(m_pRLMissile); ASSERT(m_pMissilePhaseModel); pSkill = g_pRL->m_pSO3WorldClient->GetSkill(m_pRLMissile->m_Param.Result.dwSkillID, m_pRLMissile->m_Param.Result.dwSkillLevel); KGLOG_PROCESS_ERROR(pSkill); // Track Parameter m_fTotalModelScale = m_pMissilePhaseModel->fModelScaleEnd - m_pMissilePhaseModel->fModelScaleBegin; // Velocity fBulletVelocity = ToSceneVelocity(pSkill->m_nBulletVelocity); nRetCode = abs(fBulletVelocity) > FLT_EPSILON; KG_PROCESS_SUCCESS(!nRetCode); hr = GetTargetOrientation(vPositionTarget, qRotationTarget); KGLOG_COM_PROCESS_ERROR(hr); YawToQuatLH(qRotationCaster, m_fAngleCaster); vDistance = vPositionTarget - m_vPositionCaster; fDistance = D3DXVec3Length(&vDistance); KGLOG_PROCESS_ERROR(fDistance >= FLT_EPSILON); hr = PrepareFixedTrackMissileOrientationInitialData(); KGLOG_COM_PROCESS_ERROR(hr); SetTimeTotal(fDistance / fBulletVelocity); nRetCode = KTimelineMissileProcessor::OnStart(fTime); KGLOG_PROCESS_ERROR(nRetCode); Exit1: return true; Exit0: return false; }