void VImageState::OnPaint(VGraphicsInfo &Graphics, const VItemRenderInfo &parentState) { VTextureObject *pTex = GetCurrentTexture(); if (!pTex) return; VASSERT(parentState.m_pWindow); VRectanglef rect = parentState.m_pWindow->GetBoundingBox(); VSimpleRenderState_t state = VGUIManager::DefaultGUIRenderState(m_eTranspType); VColorRef iColor = parentState.iFadeColor*m_iColor; state.SetFlag(m_iAdditionalStateFlags); // apply filtering for instance if (m_eStretchMode==BORDER) { hkvVec2 v1 = rect.m_vMin; hkvVec2 v2 = rect.m_vMax; float bx = (float)pTex->GetTextureWidth()*0.5f; float by = (float)pTex->GetTextureHeight()*0.5f; float hx = 1.f / bx; float hy = 1.f / by; bx -= 1.f; by -= 1.f; Overlay2DVertex_t v[(4+4+1)*6]; // 9 quads int iVertexCount = 0; // corners IVRender2DInterface::CreateQuadVertices(v1.x,v1.y, v1.x+bx,v1.y+by, 0,0,0.5f-hx,0.5f-hy, iColor, &v[iVertexCount]); iVertexCount+=6; IVRender2DInterface::CreateQuadVertices(v2.x-bx,v1.y, v2.x,v1.y+by, 0.5f+hx,0,1,0.5f-hy, iColor, &v[iVertexCount]); iVertexCount+=6; IVRender2DInterface::CreateQuadVertices(v2.x-bx,v2.y-by, v2.x,v2.y, 0.5f+hx,0.5f+hy,1,1, iColor, &v[iVertexCount]); iVertexCount+=6; IVRender2DInterface::CreateQuadVertices(v1.x,v2.y-by, v1.x+bx,v2.y, 0,0.5f+hy,0.5f-hx,1, iColor, &v[iVertexCount]); iVertexCount+=6; // edges IVRender2DInterface::CreateQuadVertices(v1.x+bx,v1.y, v2.x-bx,v1.y+by, 0.5f-hx,0,0.5f+hx,0.5f-hy, iColor, &v[iVertexCount]); iVertexCount+=6; IVRender2DInterface::CreateQuadVertices(v1.x+bx,v2.y-by, v2.x-bx,v2.y, 0.5f-hx,0.5f+hy,0.5f+hx,1, iColor, &v[iVertexCount]); iVertexCount+=6; IVRender2DInterface::CreateQuadVertices(v1.x,v1.y+by, v1.x+bx,v2.y-by, 0,0.5f-hy,0.5f-hx,0.5f+hy, iColor, &v[iVertexCount]); iVertexCount+=6; IVRender2DInterface::CreateQuadVertices(v2.x-bx,v1.y+by, v2.x,v2.y-by, 0.5f+hx,0.5f-hy,1,0.5f+hy, iColor, &v[iVertexCount]); iVertexCount+=6; // inner rect IVRender2DInterface::CreateQuadVertices(v1.x+bx,v1.y+by, v2.x-bx,v2.y-by, 0.5f-hx,0.5f-hy,0.5f+hx,0.5f+hy, iColor, &v[iVertexCount]); iVertexCount+=6; RENDER_VERTICES(iVertexCount); } else if (m_eStretchMode==STRETCHED) { Overlay2DVertex_t v[6]; IVRender2DInterface::CreateQuadVertices(rect.m_vMin.x,rect.m_vMin.y,rect.m_vMax.x,rect.m_vMax.y,texCoord.m_vMin.x,texCoord.m_vMin.y,texCoord.m_vMax.x,texCoord.m_vMax.y,iColor,v); RENDER_VERTICES(6); } else // actual texture size { Overlay2DVertex_t v[6]; rect.m_vMax.x = rect.m_vMin.x + (float)pTex->GetTextureWidth(); rect.m_vMax.y = rect.m_vMin.y + (float)pTex->GetTextureHeight(); IVRender2DInterface::CreateQuadVertices(rect.m_vMin.x,rect.m_vMin.y,rect.m_vMax.x,rect.m_vMax.y,texCoord.m_vMin.x,texCoord.m_vMin.y,texCoord.m_vMax.x,texCoord.m_vMax.y,iColor,v); RENDER_VERTICES(6); } }
void VCoronaManager::RenderCorona (VCoronaCandidate& coronaCandidate, VTextureObject*& pTexture) { #ifdef SUPPORTS_CORONAS VCoronaComponent *pCorona = coronaCandidate.m_pCorona; VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext(); VisLightSource_cl* pLight = (VisLightSource_cl*)pCorona->GetOwner(); hkvVec3 vLightPos(hkvNoInitialization); pLight->GetVirtualPosition(vLightPos, pContext); hkvVec3 vEyePos(hkvNoInitialization); pContext->GetCamera()->GetPosition(vEyePos); hkvVec3 vDir = pContext->GetCamera()->GetDirection(); // Corona texture VTextureObject *pTex = pCorona->GetCoronaTexture(); if (pTex == NULL) return; if (pTexture != pTex) { pTexture = pTex; Vision::RenderLoopHelper.BindMeshTexture(pTexture,0); } // Get light color VColorRef color = pLight->GetColor(); hkvVec3 vDist = vLightPos - vEyePos; float fEyeDist = vDir.dot(vDist); //determine if camera is in light cone if the light is directional float fDirectionalDampening = 1.0f; if ( pLight->GetType() == VIS_LIGHT_SPOTLIGHT && pCorona->GetOnlyVisibleInSpotLight() ) { fDirectionalDampening = 0.0f; float fConeAngle = pLight->GetProjectionAngle(); float fConeLength = pLight->GetRadius(); hkvVec3 fConeDirection = pLight->GetDirection(); fConeDirection.normalize(); hkvVec3 vLightEyeDist = vEyePos - vLightPos; //#2 check if the camera is inside the angle of the cone float cosinusAngle = (vLightEyeDist/vLightEyeDist.getLength()).dot(fConeDirection); float fDegree = hkvMath::acosDeg(cosinusAngle); float normRadius = fDegree / (fConeAngle/2.0f); if (normRadius < 1.0f) { //hardcoded falloff. For better performance, we avoid sampling the projection texture here. const float fEpsilon = 64.0f/256.0f; const float fQuadFactor = 1.0f/fEpsilon - 1.0f; fDirectionalDampening = 1.0f / (1.0f + fQuadFactor*normRadius*normRadius); // scale the function so that the value is exactly 0.0 at the edge and 1.0 in the center fDirectionalDampening = (fDirectionalDampening - fEpsilon) / (1.0f - fEpsilon); } } // Fog params float fFogDampening = 1.0f; if (pLight->GetType() != VIS_LIGHT_DIRECTED && Vision::World.IsLinearDepthFogEnabled()) { const VFogParameters &fog = Vision::World.GetFogParameters(); float fFogStart = fog.fDepthStart; float fFogEnd = fog.fDepthEnd; float fFogFactor = (fFogEnd > fFogStart) ? ((fEyeDist - fFogStart) / (fFogEnd - fFogStart)) : 0.f; fFogDampening = 1.0f - hkvMath::clamp(fFogFactor, 0.0f, 1.0f); } // Get corona rotation float fRotation = 0.0f; hkvVec4 vRotation(1.0f, 0.0f, 0.0f, 1.0f); if (pCorona->CoronaFlags & VIS_CORONASCALE_ROTATING) { fRotation = hkvMath::mod (fEyeDist * 0.5f, 360.f); vRotation.x = hkvMath::cosDeg (fRotation); vRotation.y = -hkvMath::sinDeg (fRotation); vRotation.z = -vRotation.y; vRotation.w = vRotation.x; } // Texture dimensions int iSizeX, iSizeY, depth; pTex->GetTextureDimensions(iSizeX, iSizeY, depth); hkvVec4 vScale(0.0f, 0.0f, 0.0f, 0.0f); int iMainWidth, iMainHeight, iWidth, iHeight; pContext->GetSize(iWidth, iHeight); VisRenderContext_cl::GetMainRenderContext()->GetSize(iMainWidth, iMainHeight); // Preserve texture aspect ratio int iTexHeight = pTex->GetTextureHeight(); int iTexWidth = pTex->GetTextureWidth(); // Perspective scaling // This scaling ensures roughly the same size on 720p as the old implementation. vScale.z = iTexWidth * pCorona->CoronaScaling * 0.25f; vScale.w = iTexHeight * pCorona->CoronaScaling * 0.25f; // Screen-space scaling // This scaling ensures roughly the same size on 720p as the old implementation. const float fScaleFactor = pCorona->CoronaScaling * iMainHeight / 11.0f; vScale.x = ((float)iTexWidth / 128.0f) * fScaleFactor * (float(iWidth) / float(iMainWidth)); vScale.y = ((float)iTexHeight / 128.0f) * fScaleFactor * (float(iHeight) / float(iMainHeight)); vScale.x *= 2.0f / iWidth; vScale.y *= 2.0f / iHeight; // Scale by visibility if (pCorona->CoronaFlags & VIS_CORONASCALE_VISIBLEAREA) { vScale.x *= coronaCandidate.m_fCurrentVisibility; vScale.y *= coronaCandidate.m_fCurrentVisibility; vScale.z *= coronaCandidate.m_fCurrentVisibility; vScale.w *= coronaCandidate.m_fCurrentVisibility; } VCompiledShaderPass* pShader = m_spCoronaTechnique->GetShader(0); VShaderConstantBuffer *pVertexConstBuffer = pShader->GetConstantBuffer(VSS_VertexShader); // xyz = worldspace position, w = 1.0 if VIS_CORONASCALE_DISTANCE is true, otherwise zero. pVertexConstBuffer->SetSingleParameterF("coronaPosition", vLightPos.x, vLightPos.y, vLightPos.z, (pCorona->CoronaFlags & VIS_CORONASCALE_DISTANCE) ? 1.0f : 0.0f); // xyz = light color, w = corona visibility. pVertexConstBuffer->SetSingleParameterF("coronaColor", color.r/255.0f, color.g/255.0f, color.b/255.0f, coronaCandidate.m_fCurrentVisibility * fFogDampening * fDirectionalDampening); // xyzw = 2x2 rotation matrix. float2x2 is not supported in shader model 2, so a float4 is used and multiplication is done manually in the shader. pVertexConstBuffer->SetSingleParameterF("coronaRotation", vRotation.x, vRotation.y, vRotation.z, vRotation.w); // xy = screen-space scaling. zw = view-space scaling. pVertexConstBuffer->SetSingleParameterF("coronaScale", vScale.x, vScale.y, vScale.z, vScale.w); Vision::RenderLoopHelper.RenderMeshes(pShader, VisMeshBuffer_cl::MB_PRIMTYPE_TRILIST, 0, 2, 6); #endif }