void CRBX_ModelViewCtrl::SetFitModel() { if(!m_pEntity) return; m_fFovV = hkvMathHelpers::getFovY(m_fFovH, GetSize().x / GetSize().y); VisRenderContext_cl::GetMainRenderContext()->SetFOV(m_fFovH,m_fFovV); hkvAlignedBBox modelbox; m_pEntity->GetMesh()->GetVisibilityBoundingBox(modelbox); float fAngleH,fAngleV; VisRenderContext_cl::GetMainRenderContext()->GetFOV(fAngleH,fAngleV); float dx = hkvMath::Max(modelbox.getSizeX(),modelbox.getSizeY()); float zx = 0.5f*dx / hkvMath::tanDeg (fAngleH*0.5f); float zy = 0.5f*modelbox.getSizeZ() / hkvMath::tanDeg (fAngleV*0.5f); float Dist = (hkvMath::Max(zx,zy) + dx*0.5f); VisContextCamera_cl* pMainCamera = Vision::Camera.GetMainCamera(); hkvMat3 vMat; vMat.setFromEulerAngles(0,20,180); m_vCamPos.Set(Dist,0,modelbox.GetSizeZ()); pMainCamera->Set(vMat,m_vCamPos); if( m_pLight == NULL ) { m_pLight = new VisLightSource_cl( VisLightSourceType_e::VIS_LIGHT_DIRECTED , 10.0f ); } m_pLight->SetPosition(pMainCamera->GetPosition()); m_pLight->AttachToParent(pMainCamera); m_pLight->SetDirection(pMainCamera->GetDirection()); m_pLight->SetIntensity(50.0f); /// << 빛의 강도를 조절함. 나중에콜백이나 업데이트 함수에서 조절하시면됩니다. UpdateWorldAxisSystem(); }
void VShadowMapGenSpotDir::Update(bool force) { VisContextCamera_cl *pMainCam = m_pRendererNode->GetReferenceContext()->GetCamera(); VASSERT(pMainCam); float fCamAngle = hkvMath::Abs (hkvMath::acosDeg (pMainCam->GetDirection().dot (m_vLastCameraDir))); hkvVec3 vCamMove = pMainCam->GetPosition() - m_vLastCameraPos; m_pRendererNode->GetReferenceContext()->GetViewFrustum(m_MainViewFrustum); float fFovX, fFovY; m_pRendererNode->GetReferenceContext()->GetFinalFOV(fFovX, fFovY); float fNear, fFar; m_pRendererNode->GetReferenceContext()->GetClipPlanes(fNear, fFar); VBaseShadowMapComponentSpotDirectional* pComponent = static_cast<VBaseShadowMapComponentSpotDirectional*>(m_pShadowComponent); if (m_eProjectionType == SHADOW_PROJECTION_ORTHOGRAPHIC) { bool bOverestimateCascades = pComponent->GetOverestimateCascades() ? true : false; if (bOverestimateCascades) { if (m_fFovX != fFovX || m_fFovY != fFovY || m_fNear != fNear) { // In case user switches the FOV at runtime we need to update it here float fStartDistance = fNear; for (int iCascade = 0; iCascade < m_iNumParts; iCascade++) { float fEndDistance = pComponent->GetCascadeRange(iCascade) + fNear; m_pParts[iCascade].ComputeOffset(fStartDistance, fEndDistance); fStartDistance = fEndDistance; } m_fFovX = fFovX; m_fFovY = fFovY; m_fNear = fNear; force = true; } if (force || m_vLastLightPos != m_pLightSource->GetPosition() || m_vLastLightDir != m_pLightSource->GetDirection() || vCamMove.getLength() > pComponent->GetShadowMapCameraUpdateInterval() || fCamAngle > pComponent->GetShadowMapCameraUpdateAngle()) { for (int iCascade = 0; iCascade < m_iNumParts; iCascade++) { VShadowMapPart& part = m_pParts[iCascade]; VisContextCamera_cl* pCam = part.GetRenderContext()->GetCamera(); VisContextCamera_cl *pReferenceCam = m_pRendererNode->GetReferenceContext()->GetCamera(); hkvVec3 vCascadeCenter = pReferenceCam->GetPosition() + pReferenceCam->GetDirection() * part.m_fCenterOffset; pCam->SetDirection(GetDirection()); float fRadius = part.m_fRadius + pComponent->GetShadowMapCameraUpdateInterval(); float fCameraDistanceFromCenter = fFar; hkvVec3 vCamPos = vCascadeCenter - GetDirection() * fCameraDistanceFromCenter; pCam->SetPosition(vCamPos); //snapping hkvVec3 offset = pCam->GetWorldToCameraTransformation().getColumn(3).getAsVec3(); float fPixelSize = (fRadius * 2) / (float)m_pShadowComponent->GetShadowMapSize(); offset.x -= floorf(offset.x / fPixelSize) * fPixelSize; offset.y -= floorf(offset.y / fPixelSize) * fPixelSize; vCamPos -= pCam->GetObjDir_Right() * offset.x - pCam->GetObjDir_Up() * offset.y; pCam->SetPosition(vCamPos); // Set far clip plane so that we have z = 1 at the far side of the sphere - the shader expects this when using the BoundingBox cascade selection method. part.GetRenderContext()->SetClipPlanes(0.0f, fCameraDistanceFromCenter + fRadius); part.GetRenderContext()->SetOrthographicSize(fRadius * 2, fRadius * 2); part.Update(); } m_vLastLightPos = m_pLightSource->GetPosition(); m_vLastLightDir = m_pLightSource->GetDirection(); m_vLastCameraPos = pMainCam->GetPosition(); m_vLastCameraDir = pMainCam->GetDirection(); } } else { float fStartDistance = 0.0f; for (int iCascade = 0; iCascade < m_iNumParts; iCascade++) { VShadowMapPart& part = m_pParts[iCascade]; VisContextCamera_cl* pCam = part.GetRenderContext()->GetCamera(); // TODO: Performance // Compute the extremes of the view frustum fragment for this cascade hkvVec3 vCorners[8]; float fEndDistance = pComponent->GetCascadeRange(iCascade); part.m_fCullDistance = fEndDistance; part.GetViewFrustumCornersAtDistance(m_pRendererNode->GetReferenceContext(), fStartDistance, &vCorners[0]); part.GetViewFrustumCornersAtDistance(m_pRendererNode->GetReferenceContext(), fEndDistance, &vCorners[4]); fStartDistance = fEndDistance; pCam->SetDirection(GetDirection()); float fMinRight = FLT_MAX; float fMinUp = FLT_MAX; float fMaxRight = -FLT_MAX; float fMaxUp = -FLT_MAX; float fMinDist = FLT_MAX; float fMaxDist = -FLT_MAX; for (int iCorner = 0; iCorner < 8; iCorner ++ ) { float fRight = pCam->GetObjDir_Right().dot (vCorners[iCorner]); if (fRight < fMinRight) fMinRight = fRight; if (fRight > fMaxRight) fMaxRight = fRight; float fUp = pCam->GetObjDir_Up().dot (vCorners[iCorner]); if (fUp < fMinUp) fMinUp = fUp; if (fUp > fMaxUp) fMaxUp = fUp; float fDist = pCam->GetDirection().dot (vCorners[iCorner]); if (fDist < fMinDist) fMinDist = fDist; if (fDist > fMaxDist) fMaxDist = fDist; } // Since we need to take geometry into account which lies in front of the view frustum, we need to // offset the near clip plane (in this case, the camera position) away from the view frustum fMinDist -= (fFar - fNear); hkvVec3 vCamPos = pCam->GetObjDir_Right() * ((fMinRight + fMaxRight)*0.5f) + pCam->GetObjDir_Up() * ((fMinUp + fMaxUp)*0.5f) + pCam->GetDirection() * fMinDist; float fPadding = pComponent->GetShadowMapCameraUpdateInterval(); pCam->SetPosition(vCamPos); part.GetRenderContext()->SetClipPlanes(0.0f, fMaxDist - fMinDist); part.GetRenderContext()->SetOrthographicSize(fMaxRight - fMinRight + fPadding, fMaxUp - fMinUp + fPadding); part.Update(); } } } else if (m_eProjectionType == SHADOW_PROJECTION_PERSPECTIVE) { if (m_pLightSource->GetRadius() <= 0) //this is the case if triggered is set to false for the light { return; //do render the light at all } if (force || m_vLastLightPos != m_pLightSource->GetPosition() || m_vLastLightDir != m_pLightSource->GetDirection() || m_fLastRadius != m_pLightSource->GetRadius() || m_fLastAngle != m_pLightSource->GetProjectionAngle()) { VShadowMapPart& part = m_pParts[0]; VisContextCamera_cl* pCam = part.GetRenderContext()->GetCamera(); pCam->SetDirection(GetDirection()); pCam->SetPosition(GetPosition()); part.GetRenderContext()->SetClipPlanes(m_pShadowComponent->GetNearClip(), m_pLightSource->GetRadius()); float fAngle = m_pLightSource->GetProjectionAngle(); part.GetRenderContext()->SetFOV(fAngle, fAngle); part.Update(); m_vLastLightPos = m_pLightSource->GetPosition(); m_vLastLightDir = m_pLightSource->GetDirection(); m_fLastRadius = m_pLightSource->GetRadius(); m_fLastAngle = fAngle; } } m_iPartsRendered = 0; }