1536 lines
40 KiB
C++
1536 lines
40 KiB
C++
/*=============================================================================
|
|
GLRenderRE.cpp : implementation of the Rendering RenderElements pipeline.
|
|
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honitch Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#include "RenderPCH.h"
|
|
#include "GL_Renderer.h"
|
|
#include "I3dengine.h"
|
|
|
|
// tiago:added
|
|
#include "GLCGPShader.h"
|
|
#include "GLCGVProgram.h"
|
|
#include "../Common/RendElements/CREScreenCommon.h"
|
|
|
|
//#include "../cry3dengine/StatObj.h"
|
|
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
//=======================================================================
|
|
|
|
void CREFlareGeom::mfCheckVis(CFColor &col, CCObject *obj)
|
|
{
|
|
float Depth;
|
|
float ft, f;
|
|
|
|
CGLRenderer *rd = gcpOGL;
|
|
|
|
int re = 0;//rd->GetRecurseLevel();
|
|
SFlareFrame *ff = &mFlareFr[re];
|
|
|
|
glReadPixels(ff->mX, ff->mY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &Depth);
|
|
Depth = (Depth-rd->mMinDepth) / (rd->mMaxDepth-rd->mMinDepth);
|
|
|
|
f = gRenDev->m_ProjMatrix(3,2)/((Depth+Depth-1.0f)*gRenDev->m_ProjMatrix(2,3)-gRenDev->m_ProjMatrix(2,2)) - ff->mDepth;
|
|
if (f < 24)
|
|
{
|
|
if (!ff->mbVis)
|
|
{
|
|
ff->mbVis = true;
|
|
ff->mDecayTime = gRenDev->m_RP.m_RealTime-0.001f;
|
|
}
|
|
ft = (gRenDev->m_RP.m_RealTime - ff->mDecayTime) * CRenderer::CV_r_coronafade;
|
|
}
|
|
else
|
|
{
|
|
if (ff->mbVis)
|
|
{
|
|
ff->mbVis = false;
|
|
ff->mDecayTime = gRenDev->m_RP.m_RealTime-0.001f;
|
|
}
|
|
ft = 1.0f - (gRenDev->m_RP.m_RealTime - ff->mDecayTime) * CRenderer::CV_r_coronafade;
|
|
}
|
|
col = ff->mColor;
|
|
col.a = ft;
|
|
col.ClampAlpha();
|
|
}
|
|
|
|
//#include "..\common\shadow_renderer.h"
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
CREOcclusionQuery::~CREOcclusionQuery()
|
|
{
|
|
mfReset();
|
|
}
|
|
|
|
void CREOcclusionQuery::mfReset()
|
|
{
|
|
if (m_nOcclusionID)
|
|
glDeleteOcclusionQueriesNV(1, &m_nOcclusionID);
|
|
m_nOcclusionID = 0;
|
|
}
|
|
|
|
void CGLRenderer__Draw3dBBoxSolid(const Vec3d &mins,const Vec3d &maxs);
|
|
|
|
bool CREOcclusionQuery::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
CGLRenderer *r = gcpOGL;
|
|
int nFrame = r->GetFrameID();
|
|
|
|
// if(nFrame&1)
|
|
// return true;
|
|
|
|
if (SUPPORTS_GL_NV_occlusion_query && CGLRenderer::CV_gl_hp_occlusion_test)
|
|
{
|
|
if ( m_nCheckFrame != nFrame )
|
|
{
|
|
if(m_nCheckFrame)
|
|
{
|
|
double time = sCycles2();
|
|
m_nVisSamples=0;
|
|
glGetOcclusionQueryuivNV(m_nOcclusionID, GL_PIXEL_COUNT_NV, &m_nVisSamples);
|
|
r->m_RP.m_PS.m_fOcclusionTime += (float)((sCycles2()+34-time)*1000.0*g_SecondsPerCycle);
|
|
}
|
|
m_nCheckFrame = nFrame;
|
|
}
|
|
|
|
if (!m_nOcclusionID)
|
|
glGenOcclusionQueriesNV(1, &m_nOcclusionID);
|
|
|
|
if (m_nDrawFrame != nFrame)
|
|
{ // draw bbox
|
|
glBeginOcclusionQueryNV(m_nOcclusionID);
|
|
CGLRenderer__Draw3dBBoxSolid(m_vBoxMin-Vec3d(0.05f,0.05f,0.05f),m_vBoxMax+Vec3d(0.05f,0.05f,0.05f));
|
|
glEndOcclusionQueryNV();
|
|
m_nDrawFrame = nFrame;
|
|
}
|
|
}
|
|
else
|
|
if (SUPPORTS_GL_HP_occlusion_test && CGLRenderer::CV_gl_hp_occlusion_test)
|
|
{
|
|
if ( m_nCheckFrame != nFrame )
|
|
{
|
|
if(m_nCheckFrame)
|
|
glGetIntegerv(GL_OCCLUSION_TEST_RESULT_HP, &m_nVisSamples);
|
|
m_nCheckFrame = nFrame;
|
|
m_nVisSamples *= r->GetWidth()*r->GetHeight();
|
|
}
|
|
// Enable the occlusion test and render the geometry.
|
|
if (m_nDrawFrame != nFrame)
|
|
{ // draw bbox
|
|
glBeginOcclusionQueryNV(m_nOcclusionID);
|
|
CGLRenderer__Draw3dBBoxSolid(m_vBoxMin-Vec3d(0.05f,0.05f,0.05f),m_vBoxMax+Vec3d(0.05f,0.05f,0.05f));
|
|
glEndOcclusionQueryNV();
|
|
m_nDrawFrame = nFrame;
|
|
}
|
|
}
|
|
else
|
|
m_nVisSamples = r->GetWidth()*r->GetHeight();
|
|
|
|
return true;
|
|
}
|
|
|
|
// ===============================================================
|
|
// FlashBang fx
|
|
// Last Update: 24/04/2003
|
|
|
|
// render flashbang
|
|
bool CREFlashBang::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
// sincronize
|
|
ITimer *pTimer=iSystem->GetITimer();
|
|
m_fFlashTimeOut-= (0.00009f*m_fTimeScale*(pTimer->GetFrameTime()*1000.0f));
|
|
|
|
// reset animation
|
|
if(m_fFlashTimeOut<=0.01f)
|
|
{
|
|
m_bIsActive=0;
|
|
m_fFlashTimeOut=1.0f;
|
|
}
|
|
|
|
// screen aligned quad
|
|
static struct_VERTEX_FORMAT_P3F_TEX2F pData[]=
|
|
{
|
|
Vec3(800, 600, 0), 1,1.f-1,
|
|
Vec3(800, 0, 0), 1,1.f-0,
|
|
Vec3(0, 600, 0), 0,1.f-1,
|
|
Vec3(0, 0, 0), 0,1.f-0,
|
|
};
|
|
|
|
// render quad
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CREOcLeaf::mfPreDraw(SShaderPass *sl)
|
|
{
|
|
CLeafBuffer *lb = m_pBuffer->GetVertexContainer();
|
|
|
|
assert(!lb->m_pVertexBuffer->m_VS[VSF_GENERAL].m_bLocked);
|
|
assert(!lb->m_pVertexBuffer->m_VS[VSF_TANGENTS].m_bLocked);
|
|
|
|
if (SUPPORTS_GL_ARB_vertex_buffer_object)
|
|
{
|
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_pBuffer->m_Indices.m_VertBuf.m_nID);
|
|
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_INDEXSTREAM;
|
|
gRenDev->m_RP.m_RendIndices = NULL;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CRE2DQuad::mfPrepare()
|
|
{
|
|
gRenDev->EF_CheckOverflow(0, 0, this);
|
|
|
|
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_DRAWAS2D;
|
|
|
|
gRenDev->m_RP.m_pRE = this;
|
|
gRenDev->m_RP.m_RendNumIndices = 0;
|
|
gRenDev->m_RP.m_FirstVertex = 0;
|
|
gRenDev->m_RP.m_RendNumVerts = 4;
|
|
|
|
float w=800;
|
|
float h=600;
|
|
bool bRect = gRenDev->m_RP.m_pCurObject->m_nTemplId != 0;
|
|
|
|
m_arrVerts[0].xyz.x = w;
|
|
m_arrVerts[0].xyz.y = 0;
|
|
m_arrVerts[0].xyz.z = 0;
|
|
m_arrVerts[0].st[0] = bRect ? w : 1;
|
|
m_arrVerts[0].st[1] = bRect ? h : 1;
|
|
|
|
m_arrVerts[1].xyz.x = 0;
|
|
m_arrVerts[1].xyz.y = 0;
|
|
m_arrVerts[1].xyz.z = 0;
|
|
m_arrVerts[1].st[0] = 0;
|
|
m_arrVerts[1].st[1] = bRect ? h : 1;
|
|
|
|
m_arrVerts[2].xyz.x = w;
|
|
m_arrVerts[2].xyz.y = h;
|
|
m_arrVerts[2].xyz.z = 0;
|
|
m_arrVerts[2].st[0] = bRect ? w : 1;
|
|
m_arrVerts[2].st[1] = 0;
|
|
|
|
m_arrVerts[3].xyz.x = 0;
|
|
m_arrVerts[3].xyz.y = h;
|
|
m_arrVerts[3].xyz.z = 0;
|
|
m_arrVerts[3].st[0] = 0;
|
|
m_arrVerts[3].st[1] = 0;
|
|
}
|
|
|
|
bool CRE2DQuad::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
// gRenDev->EnableDepthTest(false);
|
|
// gRenDev->EnableDepthWrites(false);
|
|
/// gRenDev->EnableBlend(true);
|
|
// gRenDev->SetBlendMode(R_BLEND_MODE__DST_COLOR__SRC_COLOR);
|
|
|
|
bool bRect = gRenDev->m_RP.m_pCurObject->m_nTemplId != 0;
|
|
|
|
STexPic *tx = gRenDev->m_TexMan->m_Text_EnvScr;
|
|
|
|
m_arrVerts[0].st[0] = bRect ? (float)tx->m_Width : 1;
|
|
m_arrVerts[0].st[1] = bRect ? (float)tx->m_Height : 1;
|
|
|
|
m_arrVerts[1].st[0] = 0;
|
|
m_arrVerts[1].st[1] = bRect ? (float)tx->m_Height : 1;
|
|
|
|
m_arrVerts[2].st[0] = bRect ? (float)tx->m_Width : 1;
|
|
m_arrVerts[2].st[1] = 0;
|
|
|
|
m_arrVerts[3].st[0] = 0;
|
|
m_arrVerts[3].st[1] = 0;
|
|
|
|
//gRenDev->SetColorMask(0,0,0,1);
|
|
gRenDev->DrawTriStrip(&CVertexBuffer(m_arrVerts,VERTEX_FORMAT_P3F_TEX2F),4);
|
|
//gRenDev->SetColorMask(1,1,1,1);
|
|
|
|
return true;
|
|
}
|
|
|
|
#define GLARE_OFS 1.0/32
|
|
|
|
void GlareQuad()
|
|
{
|
|
glBegin (GL_QUADS);
|
|
glTexCoord2f(-1, 1);
|
|
glVertex3f (0.1f, 1, 1);
|
|
glTexCoord2f(0, 1);
|
|
glVertex3f (0.1f, -1, 1);
|
|
glTexCoord2f(0, 0);
|
|
glVertex3f (0.1f, -1, -1);
|
|
glTexCoord2f(-1, 0);
|
|
glVertex3f (0.1f, 1, -1);
|
|
glEnd ();
|
|
}
|
|
|
|
// ===============================================================
|
|
// Glare fx
|
|
// Last Update: 05/05/2003
|
|
|
|
bool CREGlare::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
gRenDev->Set2DMode(true, 800, 600);
|
|
|
|
// screen aligned quad
|
|
static struct_VERTEX_FORMAT_P3F_TEX2F pData[]=
|
|
{
|
|
Vec3(800, 600, 0), 1, 0,
|
|
Vec3(800, 0, 0), 1, 1,
|
|
Vec3( 0, 600, 0), 0, 0,
|
|
Vec3( 0, 0, 0), 0, 1,
|
|
};
|
|
|
|
// render quad
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
gRenDev->Set2DMode(false, 800, 600);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CGLRenderer__Draw3dBBoxSolid(const Vec3d &mins,const Vec3d &maxs)
|
|
{
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(mins.x,mins.y,mins.z); //0
|
|
glVertex3f(mins.x,mins.y,maxs.z); //1
|
|
glVertex3f(maxs.x,mins.y,maxs.z); //2
|
|
glVertex3f(maxs.x,mins.y,mins.z); //3
|
|
glEnd();
|
|
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(mins.x,mins.y,mins.z); //0
|
|
glVertex3f(mins.x,mins.y,maxs.z); //1
|
|
glVertex3f(mins.x,maxs.y,maxs.z); //6
|
|
glVertex3f(mins.x,maxs.y,mins.z); //4
|
|
glEnd();
|
|
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(mins.x,maxs.y,mins.z); //4
|
|
glVertex3f(mins.x,maxs.y,maxs.z); //6
|
|
glVertex3f(maxs.x,maxs.y,maxs.z); //7
|
|
glVertex3f(maxs.x,maxs.y,mins.z); //5
|
|
glEnd();
|
|
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(maxs.x,maxs.y,mins.z); //5
|
|
glVertex3f(maxs.x,maxs.y,maxs.z); //7
|
|
glVertex3f(maxs.x,mins.y,maxs.z); //2
|
|
glVertex3f(maxs.x,mins.y,mins.z); //3
|
|
glEnd();
|
|
|
|
// top
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(maxs.x,maxs.y,maxs.z); //5
|
|
glVertex3f(mins.x,maxs.y,maxs.z); //7
|
|
glVertex3f(mins.x,mins.y,maxs.z); //3
|
|
glVertex3f(maxs.x,mins.y,maxs.z); //2
|
|
glEnd();
|
|
|
|
// bottom
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(maxs.x,mins.y,mins.z); //2
|
|
glVertex3f(mins.x,mins.y,mins.z); //3
|
|
glVertex3f(mins.x,maxs.y,mins.z); //7
|
|
glVertex3f(maxs.x,maxs.y,mins.z); //5
|
|
glEnd();
|
|
|
|
gRenDev->m_nPolygons+=12;
|
|
}
|
|
|
|
bool CREOcLeaf::mfDraw(SShader *ef, SShaderPass *sl)
|
|
{
|
|
CGLRenderer *r = gcpOGL;
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
|
|
// modify fog far/near dist if requested
|
|
float fFogStart, fFogEnd;
|
|
if(m_fFogScale)
|
|
{
|
|
fFogStart = gRenDev->m_FS.m_FogStart;
|
|
fFogEnd = gRenDev->m_FS.m_FogEnd;
|
|
glFogf(GL_FOG_START, fFogStart*m_fFogScale);
|
|
glFogf(GL_FOG_END , fFogEnd *m_fFogScale);
|
|
}
|
|
|
|
// Hardware effector
|
|
if (ef->m_HWTechniques.Num())
|
|
{
|
|
assert(m_pChunk->nFirstIndexId<60000);
|
|
|
|
ushort *pInds;
|
|
int nInds;
|
|
int nPrimType;
|
|
SShaderPassHW *slw = (SShaderPassHW *)sl;
|
|
if (CRenderer::CV_r_cullgeometryforlights && r->EF_IsOnlyLightPass(slw) && r->m_RP.m_pCurLightIndices != &r->m_RP.m_FakeLightIndices)
|
|
{
|
|
pInds = r->m_RP.m_pCurLightIndices->GetIndices(nInds);
|
|
nPrimType = R_PRIMV_TRIANGLES;
|
|
}
|
|
else
|
|
{
|
|
if(!lb->m_SecIndices.Num())
|
|
return true; // todo: check that this is never happend, do not add such render elements
|
|
|
|
if (r->m_RP.m_FlagsPerFlush & RBSI_INDEXSTREAM)
|
|
pInds = r->m_RP.m_RendIndices;
|
|
else
|
|
pInds = (ushort *)lb->m_Indices.m_VData;
|
|
pInds = &pInds[m_pChunk->nFirstIndexId];
|
|
nInds = m_pChunk->nNumIndices;
|
|
nPrimType = lb->m_nPrimetiveType;
|
|
}
|
|
if (nInds)
|
|
{
|
|
ushort *pSaveInds = r->m_RP.m_RendIndices;
|
|
r->m_RP.m_RendIndices = pInds;
|
|
r->m_RP.m_RendNumIndices = nInds;
|
|
r->EF_DrawIndexedMesh(nPrimType);
|
|
r->m_RP.m_RendNumIndices = 0;
|
|
r->m_RP.m_RendIndices = pSaveInds;
|
|
}
|
|
lb = lb->GetVertexContainer();
|
|
if(!lb->m_pVertexBuffer->m_bFenceSet || lb->m_bDynamic)
|
|
{
|
|
if (SUPPORTS_GL_NV_vertex_array_range)
|
|
glSetFenceNV(lb->m_pVertexBuffer->m_fence, GL_ALL_COMPLETED_NV);
|
|
lb->m_pVertexBuffer->m_bFenceSet = true;
|
|
}
|
|
|
|
// restore fog
|
|
if(m_fFogScale)
|
|
{
|
|
glFogf(GL_FOG_START, fFogStart);
|
|
glFogf(GL_FOG_END , fFogEnd );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
lb = lb->GetVertexContainer();
|
|
if(!lb->m_pVertexBuffer)
|
|
{
|
|
iLog->Log("Warning: CREOcLeaf::mfDraw m_pBuffer->m_pVertexBuffer==0 '%s'",lb->m_sSource!=0?lb->m_sSource:"<NULL>");return(true);
|
|
}
|
|
|
|
assert(lb->m_pVertexBuffer);
|
|
r->DrawBuffer(lb->m_pVertexBuffer, &lb->m_Indices, m_pChunk->nNumIndices, m_pChunk->nFirstIndexId, lb->m_nPrimetiveType, m_pChunk->nFirstVertId, m_pChunk->nNumVerts, m_pChunk);
|
|
|
|
// restore fog
|
|
if(m_fFogScale)
|
|
{
|
|
glFogf(GL_FOG_START, fFogStart);
|
|
glFogf(GL_FOG_END , fFogEnd );
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
void CREOcLeaf::mfEndFlush(void)
|
|
{
|
|
}
|
|
|
|
//===============================================================================
|
|
|
|
bool CRETempMesh::mfPreDraw(SShaderPass *sl)
|
|
{
|
|
if (SUPPORTS_GL_ARB_vertex_buffer_object)
|
|
{
|
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_Inds.m_VertBuf.m_nID);
|
|
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_INDEXSTREAM;
|
|
gRenDev->m_RP.m_RendIndices = NULL;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
void CRETempMesh::mfReset()
|
|
{
|
|
}
|
|
|
|
bool CRETempMesh::mfDraw(SShader *ef, SShaderPass *sl)
|
|
{
|
|
CGLRenderer *r = gcpOGL;
|
|
CVertexBuffer *vb = m_VBuffer;
|
|
if (!vb)
|
|
return false;
|
|
|
|
// Hardware effector
|
|
ushort *pInds;
|
|
if (r->m_RP.m_FlagsPerFlush & RBSI_INDEXSTREAM)
|
|
pInds = r->m_RP.m_RendIndices;
|
|
else
|
|
pInds = (ushort *)m_Inds.m_VData;
|
|
int nPrimType = R_PRIMV_TRIANGLES;
|
|
r->m_RP.m_RendIndices = pInds;
|
|
r->EF_DrawIndexedMesh(nPrimType);
|
|
r->m_RP.m_RendNumIndices = 0;
|
|
|
|
if (SUPPORTS_GL_NV_vertex_array_range)
|
|
glSetFenceNV(vb->m_fence, GL_ALL_COMPLETED_NV);
|
|
vb->m_bFenceSet = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
//=========================================================================================
|
|
|
|
bool CREFlare::mfCheckVis(CCObject *obj)
|
|
{
|
|
if (!obj)
|
|
return false;
|
|
|
|
Vec3d or = obj->GetTranslation();
|
|
//bool bVis = false;
|
|
bool bSun = false;
|
|
CGLRenderer *rd = gcpOGL;
|
|
|
|
|
|
//if (SRendItem::m_RecurseLevel <= 1)
|
|
if (m_Importance <= CRenderer::CV_r_coronas)
|
|
{
|
|
float fScaleCorona = m_fScaleCorona;
|
|
if (m_pScaleCoronaParams)
|
|
fScaleCorona = m_pScaleCoronaParams->mfGet();
|
|
if (obj->m_ObjFlags & FOB_DRSUN)
|
|
{
|
|
bSun = true;
|
|
//or.Normalize();
|
|
//or *= 500.0f;
|
|
//or += gRenDev->m_RP.m_ViewOrg;
|
|
}
|
|
if (bSun && (gRenDev->m_RP.m_PersFlags & RBPF_DONTDRAWSUN))
|
|
return false;
|
|
|
|
Matrix44 projMatr, camMatr;
|
|
camMatr = rd->m_prevCamera.GetVCMatrixD3D9();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
// camera.fov is for horizontal -> GL needs it vertical
|
|
// projection.ratio is height/width -> GL needs width/height
|
|
gluPerspective(rd->m_prevCamera.GetFov()/(gf_PI/180.0f)*rd->m_prevCamera.GetProjRatio(), 1.0f/rd->m_prevCamera.GetProjRatio(), rd->m_prevCamera.GetZMin(), rd->m_prevCamera.GetZMax());
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
glLoadMatrixf(camMatr.GetData());
|
|
rd->GetProjectionMatrix(projMatr.GetData());
|
|
|
|
Vec3 camVecs[3];
|
|
camVecs[1][0] = camMatr(0,1);
|
|
camVecs[1][1] = camMatr(1,1);
|
|
camVecs[1][2] = camMatr(2,1);
|
|
|
|
camVecs[2][0] = camMatr(0,0);
|
|
camVecs[2][1] = camMatr(1,0);
|
|
camVecs[2][2] = camMatr(2,0);
|
|
|
|
if (CRenderer::CV_r_SunStyleCoronas)
|
|
bSun = true;
|
|
float fFade = 1.0f;
|
|
bool bRays = bSun && CRenderer::CV_r_checkSunVis == 2;
|
|
if (!bSun)
|
|
{
|
|
float fFogEnd = rd->m_FS.m_FogEnd;
|
|
float fDist = (rd->m_RP.m_ViewOrg-or).Length();
|
|
float fStartFade = fFogEnd/3.0f*2.0f;
|
|
float fEndFade = fStartFade*1.5f;
|
|
if (fDist > fEndFade)
|
|
fFade = 0;
|
|
else
|
|
if (fDist < fStartFade)
|
|
fFade = 1.0f;
|
|
else
|
|
fFade = (fEndFade-fDist) / (fEndFade-fStartFade);
|
|
}
|
|
obj->m_TempVars[2] = 0;
|
|
float fsx, fsy, fsz;
|
|
float fDepth;
|
|
int vp[4];
|
|
gRenDev->GetViewport(&vp[0], &vp[1], &vp[2], &vp[3]);
|
|
SGLFuncs::gluProject(or.x, or.y, or.z, camMatr.GetData(), projMatr.GetData(), vp, &fsx, &fsy, &fsz);
|
|
obj->m_Trans2[0] = fsx;
|
|
obj->m_Trans2[1] = fsy;
|
|
obj->m_Trans2[2] = fsz;
|
|
float fCheckInterval = CRenderer::CV_r_coronafade*0.125f;
|
|
if (bRays)
|
|
fCheckInterval *= 0.5f;
|
|
if (obj->m_fLightFadeTime-1.0f > rd->m_RP.m_RealTime)
|
|
obj->m_fLightFadeTime = rd->m_RP.m_RealTime;
|
|
if (gRenDev->m_RP.m_RealTime-obj->m_fLightFadeTime < fCheckInterval)
|
|
{
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
return true;
|
|
}
|
|
obj->m_fLightFadeTime = gRenDev->m_RP.m_RealTime;
|
|
fsx = obj->m_Trans2[0];
|
|
fsy = obj->m_Trans2[1];
|
|
fsz = obj->m_Trans2[2];
|
|
float fIntens = 0;
|
|
if (fsx>=0 && fsy>=0 && fsx<vp[2] && fsy<vp[3] && fFade)
|
|
{
|
|
// Lock back surface.
|
|
int minx, miny, maxx, maxy;
|
|
int wdt = rd->GetWidth();
|
|
int hgt = rd->GetHeight();
|
|
int sx = (int)fsx;
|
|
int sy = (int)fsy;
|
|
if (sx-2 < 0)
|
|
minx = 0;
|
|
else
|
|
minx = sx-2;
|
|
if (sy-2 < 0)
|
|
miny = 0;
|
|
else
|
|
miny = sy-2;
|
|
if (sx+2 > wdt)
|
|
maxx = wdt;
|
|
else
|
|
maxx = sx+2;
|
|
if (sy+2 > hgt)
|
|
maxy = hgt;
|
|
else
|
|
maxy = sy+2;
|
|
|
|
gRenDev->m_TexMan->m_Text_White->Set();
|
|
rd->GLSetCull(eCULL_None);
|
|
|
|
if (!(rd->m_Features & RFT_OCCLUSIONTEST))
|
|
{
|
|
glReadPixels((GLint)sx, (GLint)sy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &fDepth);
|
|
|
|
obj->m_AmbColor[0] = obj->m_AmbColor[1];
|
|
obj->m_AmbColor[1] = obj->m_AmbColor[2];
|
|
obj->m_AmbColor[2] = obj->m_TempVars[3];
|
|
obj->m_TempVars[3] = obj->m_Angs2[0];
|
|
obj->m_Angs2[0] = obj->m_Angs2[1];
|
|
obj->m_Angs2[1] = obj->m_Angs2[2];
|
|
obj->m_Angs2[2] = obj->m_TempVars[4];
|
|
obj->m_TempVars[4] = fDepth>fsz ? 1.0f : 0;
|
|
}
|
|
else
|
|
{
|
|
if (!obj->m_RE)
|
|
{
|
|
// Create visibility queries
|
|
obj->m_RE = rd->EF_CreateRE(eDATA_OcclusionQuery);
|
|
CREOcclusionQuery *pRE = (CREOcclusionQuery *)obj->m_RE;
|
|
glGenOcclusionQueriesNV(1, &pRE->m_nOcclusionID);
|
|
pRE->m_nVisSamples = 0;
|
|
}
|
|
else
|
|
{
|
|
CREOcclusionQuery *pRE = (CREOcclusionQuery *)obj->m_RE;
|
|
int nFrame = gRenDev->GetFrameID();
|
|
|
|
if ( pRE->m_nCheckFrame != nFrame )
|
|
{
|
|
if(pRE->m_nCheckFrame)
|
|
{
|
|
double time = sCycles2();
|
|
pRE->m_nVisSamples=0;
|
|
// Stupidly block until we have a query result
|
|
glGetOcclusionQueryuivNV(pRE->m_nOcclusionID, GL_PIXEL_COUNT_NV, &pRE->m_nVisSamples);
|
|
rd->m_RP.m_PS.m_fOcclusionTime += (float)((sCycles2()+34-time)*1000.0*g_SecondsPerCycle);
|
|
}
|
|
pRE->m_nCheckFrame = nFrame;
|
|
}
|
|
}
|
|
CREOcclusionQuery *pRE = (CREOcclusionQuery *)obj->m_RE;
|
|
uint nVizQuery = 0;
|
|
if (pRE)
|
|
nVizQuery = pRE->m_nOcclusionID;
|
|
Vec3d vx0, vy0, v;
|
|
v = or - rd->m_prevCamera.GetPos();
|
|
float dist = v.Length();
|
|
if (m_fDistSizeFactor != 1.0f)
|
|
dist = cry_powf(dist, m_fDistSizeFactor);
|
|
float fScaleCorona = m_fScaleCorona;
|
|
dist *= fScaleCorona * CRenderer::CV_r_coronasizescale;
|
|
vx0 = camVecs[1] * dist * 0.1f * m_fVisAreaScale;
|
|
vy0 = camVecs[2] * dist * 0.1f * m_fVisAreaScale;
|
|
rd->EF_SetState(GS_NOCOLMASK);
|
|
CGLTexMan::BindNULL(1);
|
|
rd->EF_SelectTMU(0);
|
|
|
|
glBeginOcclusionQueryNV(nVizQuery);
|
|
|
|
Vec3d ProjV[4];
|
|
Vec3d vQuad[4];
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
vQuad[0] = or + vx0 + vy0;
|
|
glTexCoord2f(0, 0);
|
|
glVertex3fv(&vQuad[0][0]);
|
|
|
|
vQuad[1] = or + vx0 - vy0;
|
|
glTexCoord2f(1, 0);
|
|
glVertex3fv(&vQuad[1][0]);
|
|
|
|
vQuad[2] = or - vx0 - vy0;
|
|
glTexCoord2f(1, 1);
|
|
glVertex3fv(&vQuad[2][0]);
|
|
|
|
vQuad[3] = or - vx0 + vy0;
|
|
glTexCoord2f(0, 1);
|
|
glVertex3fv(&vQuad[3][0]);
|
|
|
|
glEnd();
|
|
|
|
glEndOcclusionQueryNV();
|
|
|
|
for (int n=0; n<4; n++)
|
|
{
|
|
rd->ProjectToScreen(vQuad[n].x, vQuad[n].y, vQuad[n].z, &ProjV[n].x, &ProjV[n].y, &ProjV[n].z);
|
|
ProjV[n].x = ProjV[n].x / 100 * (float)vp[2];
|
|
ProjV[n].y = ProjV[n].y / 100 * (float)vp[3];
|
|
}
|
|
float nX = fabsf(ProjV[1].x - ProjV[0].x);
|
|
float nY = fabsf(ProjV[2].y - ProjV[0].y);
|
|
|
|
float area = nX * nY; //(float)(gRenDev->GetWidth() * gRenDev->GetHeight());
|
|
fIntens = (float)pRE->m_nVisSamples / area;
|
|
if (fIntens < 0.05f)
|
|
fIntens = 0;
|
|
else
|
|
if (bRays)
|
|
fIntens = max(0.75f, fIntens);
|
|
obj->m_AmbColor[0] = obj->m_AmbColor[1];
|
|
obj->m_AmbColor[1] = obj->m_AmbColor[2];
|
|
obj->m_AmbColor[2] = obj->m_TempVars[3];
|
|
obj->m_TempVars[3] = obj->m_Angs2[0];
|
|
obj->m_Angs2[0] = obj->m_Angs2[1];
|
|
obj->m_Angs2[1] = obj->m_Angs2[2];
|
|
obj->m_Angs2[2] = obj->m_TempVars[4];
|
|
obj->m_TempVars[4] = fIntens;
|
|
//obj->m_TempVars[0] = fIntens; //Min(1.0f, ((float)pRE->m_nVisSamples+50.0f) / 100.0f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
obj->m_AmbColor[0] = obj->m_AmbColor[1];
|
|
obj->m_AmbColor[1] = obj->m_AmbColor[2];
|
|
obj->m_AmbColor[2] = obj->m_TempVars[3];
|
|
obj->m_TempVars[3] = obj->m_Angs2[0];
|
|
obj->m_Angs2[0] = obj->m_Angs2[1];
|
|
obj->m_Angs2[1] = obj->m_Angs2[2];
|
|
obj->m_Angs2[2] = obj->m_TempVars[4];
|
|
obj->m_TempVars[4] = 0;
|
|
}
|
|
if (fIntens >= 0.05f && bRays)
|
|
{
|
|
int n = 1;
|
|
int sizeMask = 64;
|
|
int sizeMask2 = sizeMask/2;
|
|
int sizeTex = 128; //m_Map->GetWidth();
|
|
|
|
if (!obj->m_TexId0)
|
|
{
|
|
glGenTextures(1, (uint *)&obj->m_TexId0);
|
|
assert(obj->m_TexId0<14000);
|
|
rd->m_TexMan->SetTexture(obj->m_TexId0, eTT_Base);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, sizeMask, sizeMask, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
}
|
|
if (!obj->m_TexId1)
|
|
{
|
|
glGenTextures(1, (uint *)&obj->m_TexId1);
|
|
assert(obj->m_TexId0<14000);
|
|
rd->m_TexMan->SetTexture(obj->m_TexId1, eTT_Base);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, sizeTex, sizeTex, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
}
|
|
bool bFog = rd->m_FS.m_bEnable;
|
|
rd->EnableFog(false);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0.0, rd->GetWidth(), 0.0, rd->GetHeight(), -20.0, 0.0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
rd->SetCullMode(R_CULL_NONE);
|
|
rd->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
|
|
|
|
gRenDev->m_TexMan->m_Text_White->Set();
|
|
|
|
float fsizeMask2 = (float)sizeMask2;
|
|
|
|
// set alpha to 0
|
|
{
|
|
rd->EF_SetState(GS_COLMASKONLYALPHA | GS_NODEPTHTEST);
|
|
|
|
glColor4f(0,0,0,0);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
|
glVertex2f(fsx-fsizeMask2, fsy-fsizeMask2);
|
|
|
|
glTexCoord2f(1, 0);
|
|
glVertex2f(fsx+fsizeMask2, fsy-fsizeMask2);
|
|
|
|
glTexCoord2f(1, 1);
|
|
glVertex2f(fsx+fsizeMask2, fsy+fsizeMask2);
|
|
|
|
glTexCoord2f(0, 1);
|
|
glVertex2f(fsx-fsizeMask2, fsy+fsizeMask2);
|
|
|
|
glEnd();
|
|
|
|
rd->m_nPolygons += 2;
|
|
}
|
|
|
|
// Set alpha mask of visible areas (1 is visible)
|
|
{
|
|
rd->EF_SetState(GS_COLMASKONLYALPHA);
|
|
|
|
glColor4f(1,1,1,1);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
|
glVertex2f(fsx-fsizeMask2, fsy-fsizeMask2);
|
|
|
|
glTexCoord2f(1, 0);
|
|
glVertex2f(fsx+fsizeMask2, fsy-fsizeMask2);
|
|
|
|
glTexCoord2f(1, 1);
|
|
glVertex2f(fsx+fsizeMask2, fsy+fsizeMask2);
|
|
|
|
glTexCoord2f(0, 1);
|
|
glVertex2f(fsx-fsizeMask2, fsy+fsizeMask2);
|
|
|
|
glEnd();
|
|
|
|
rd->m_nPolygons += 2;
|
|
}
|
|
|
|
// Read z-mask to target texture 0 as source for bluring
|
|
rd->SetTexture(obj->m_TexId0, eTT_Base);
|
|
|
|
glReadBuffer(GL_BACK);
|
|
if (SUPPORTS_GL_SGIS_generate_mipmap)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (int)fsx-sizeMask2, (int)fsy-sizeMask2, sizeMask, sizeMask);
|
|
//if (SUPPORTS_GL_SGIS_generate_mipmap)
|
|
// glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
|
|
|
|
/*{
|
|
byte *data = new byte [sizeMask * sizeMask];
|
|
byte *pic = new byte [sizeMask * sizeMask * 4];
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
|
|
for (int i=0; i<sizeMask*sizeMask; i++)
|
|
{
|
|
byte a = data[i];
|
|
pic[i*4+0] = a;
|
|
pic[i*4+1] = a;
|
|
pic[i*4+2] = a;
|
|
pic[i*4+3] = 255;
|
|
}
|
|
WriteTGA(pic,sizeMask,sizeMask,"SunMapAlpha.tga");
|
|
delete [] pic;
|
|
delete [] data;
|
|
}*/
|
|
|
|
// Scale factor
|
|
obj->m_TempVars[1] = 8.0f;
|
|
int nPasses = 32;
|
|
float fSizeTex = (float)sizeTex;
|
|
// Result blured texture size
|
|
obj->m_TempVars[2] = fSizeTex;
|
|
float fScale = fScaleCorona * obj->m_TempVars[1];
|
|
float fDif = fSizeTex / (float)sizeMask;
|
|
float fSizeTex2 = fSizeTex / 2.0f;
|
|
float fLast = fSizeTex2 / (fScale * fDif);
|
|
float fCur = fSizeTex2 * 2;
|
|
float fDelt = (fLast - fCur) / (float)nPasses;
|
|
float fCurAlpha = 0.0f;
|
|
float fDeltAlpha = 1.0f / (float)nPasses;
|
|
float fPosx = (float)(rd->GetWidth()/2);
|
|
float fPosy = (float)(rd->GetHeight()/2);
|
|
|
|
gRenDev->m_TexMan->m_Text_White->Set();
|
|
|
|
// set alpha to 0.2
|
|
{
|
|
gRenDev->EF_SetState(GS_COLMASKONLYALPHA | GS_NODEPTHTEST);
|
|
|
|
glColor4f(1,1,1,0.2f);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
|
glVertex2f(fPosx-fSizeTex2, fPosy-fSizeTex2);
|
|
|
|
glTexCoord2f(1, 0);
|
|
glVertex2f(fPosx+fSizeTex2, fPosy-fSizeTex2);
|
|
|
|
glTexCoord2f(1, 1);
|
|
glVertex2f(fPosx+fSizeTex2, fPosy+fSizeTex2);
|
|
|
|
glTexCoord2f(0, 1);
|
|
glVertex2f(fPosx-fSizeTex2, fPosy+fSizeTex2);
|
|
|
|
glEnd();
|
|
|
|
gRenDev->m_nPolygons += 2;
|
|
}
|
|
|
|
gRenDev->SetTexture(obj->m_TexId0, eTT_Base);
|
|
// Radially blur the alpha texture
|
|
for (int pass=0; pass<nPasses; pass++)
|
|
{
|
|
gRenDev->EF_SetState(GS_COLMASKONLYALPHA | GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glColor4f(1, 1, 1, fDeltAlpha);
|
|
|
|
glTexCoord2f(0, 0);
|
|
glVertex3f(fPosx-fCur, fPosy-fCur, 0);
|
|
|
|
glTexCoord2f(1.0f, 0);
|
|
glVertex3f(fPosx+fCur, fPosy-fCur, 0);
|
|
|
|
glTexCoord2f(1.0f, 1.0f);
|
|
glVertex3f(fPosx+fCur, fPosy+fCur, 0);
|
|
|
|
glTexCoord2f(0, 1.0f);
|
|
glVertex3f(fPosx-fCur, fPosy+fCur, 0);
|
|
|
|
glEnd();
|
|
|
|
fCur += fDelt;
|
|
fCurAlpha += fDeltAlpha;
|
|
}
|
|
|
|
rd->m_nPolygons += 2 * nPasses;
|
|
|
|
// Generate blured alpha texture without mip-maps
|
|
rd->SetTexture(obj->m_TexId1, eTT_Base);
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (int)(fPosx-fSizeTex2), (int)(fPosy-fSizeTex2), sizeTex, sizeTex);
|
|
|
|
/*{
|
|
byte *data = new byte [sizeTex * sizeTex];
|
|
byte *pic = new byte [sizeTex * sizeTex * 4];
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
|
|
for (int i=0; i<sizeTex*sizeTex; i++)
|
|
{
|
|
byte a = data[i];
|
|
pic[i*4+0] = a;
|
|
pic[i*4+1] = a;
|
|
pic[i*4+2] = a;
|
|
pic[i*4+3] = 255;
|
|
}
|
|
WriteTGA(pic,sizeTex,sizeTex,"SunMapAlpha_Ready.tga");
|
|
delete [] pic;
|
|
delete [] data;
|
|
}*/
|
|
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
rd->EnableFog(bFog);
|
|
|
|
rd->SetTexture(0, eTT_Base);
|
|
}
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CREFlare::mfDrawFlares(SShader *ef, CFColor &col)
|
|
{
|
|
CSunFlares *lfl = ef->m_Flares;
|
|
|
|
int i;
|
|
SSunFlare *fl;
|
|
Vec3d lv;
|
|
|
|
if (!CRenderer::CV_r_flares || !lfl)
|
|
return;
|
|
|
|
CCObject *obj = gRenDev->m_RP.m_pCurObject;
|
|
|
|
Vec3d or = obj->GetTranslation();
|
|
if (obj->m_ObjFlags & FOB_DRSUN)
|
|
{
|
|
if (gRenDev->m_bHeatVision)
|
|
return;
|
|
}
|
|
|
|
Vec3d vFromPt = gRenDev->m_RP.m_ViewOrg;
|
|
Vec3d vViewVec = gRenDev->m_RP.m_CamVecs[0];
|
|
Vec3d vLightVec = or - vFromPt;
|
|
vLightVec.Normalize();
|
|
|
|
// Compute the vector and center point for the lens flare axis
|
|
float fDot = vLightVec | vViewVec;
|
|
if (fDot <= 0.2f)
|
|
return;
|
|
|
|
|
|
Vec3d vNewLightPt = vFromPt + 1.0f/fDot * vLightVec;
|
|
Vec3d vCenterPt = vFromPt + vViewVec;
|
|
Vec3d vAxisVec = vNewLightPt - vCenterPt;
|
|
|
|
// Store the lens flares positions for each flare
|
|
for (i=0; i<lfl->m_NumFlares; i++)
|
|
{
|
|
fl = &lfl->m_Flares[i];
|
|
|
|
// Store the position of the flare along the axis
|
|
fl->m_Position = vCenterPt + vAxisVec * fl->m_Loc;
|
|
|
|
// Store the render size of the flare. This is the lens flare size
|
|
// corrected for the orientation of the flaring axis.
|
|
fl->m_RenderSize = fl->m_Scale;//fViewScale * fl->scale;
|
|
}
|
|
|
|
gRenDev->EF_SetState(GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST);
|
|
gRenDev->SetCullMode(R_CULL_NONE);
|
|
|
|
Vec3d VecX = gRenDev->m_RP.m_CamVecs[1];
|
|
Vec3d VecY = gRenDev->m_RP.m_CamVecs[2];
|
|
Vec3d v;
|
|
|
|
fDot *= col.a;
|
|
|
|
// Do the flares
|
|
for (i=0; i<lfl->m_NumFlares; i++)
|
|
{
|
|
fl = &lfl->m_Flares[i];
|
|
|
|
Vec3d vx = VecX * fl->m_RenderSize;
|
|
Vec3d vy = VecY * fl->m_RenderSize;
|
|
|
|
CFColor col = fl->m_Color * fDot;
|
|
fl->m_Tex->Set();
|
|
glColor3fv(&col[0]);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
v = fl->m_Position + vx + vy;
|
|
glTexCoord2f(0, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = fl->m_Position - vx + vy;
|
|
glTexCoord2f(1, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = fl->m_Position - vx - vy;
|
|
glTexCoord2f(1, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = fl->m_Position + vx - vy;
|
|
glTexCoord2f(0, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
glEnd();
|
|
|
|
gRenDev->m_nPolygons += 2;
|
|
}
|
|
}
|
|
|
|
void CREFlare::mfDrawCorona(SShader *ef, CFColor &col)
|
|
{
|
|
Vec3d vx0, vy0, vx1, vy1, or, v, norm;
|
|
|
|
if (!CRenderer::CV_r_coronas)
|
|
return;
|
|
|
|
CGLRenderer *rd = gcpOGL;
|
|
CCObject *obj = rd->m_RP.m_pCurObject;
|
|
or = obj->GetTranslation();
|
|
|
|
bool bSun = false;
|
|
if (obj->m_ObjFlags & FOB_DRSUN)
|
|
{
|
|
bSun = true;
|
|
//or.Normalize();
|
|
//or *= 500.0f;
|
|
//or += gRenDev->m_RP.m_ViewOrg;
|
|
}
|
|
if (bSun && rd->m_bHeatVision)
|
|
return;
|
|
|
|
rd->EF_PushFog();
|
|
rd->EnableFog(false);
|
|
|
|
vx0 = rd->m_RP.m_CamVecs[2];
|
|
vx1 = vx0;
|
|
vy0 = rd->m_RP.m_CamVecs[1];
|
|
vy1 = vy0;
|
|
|
|
v = or - gRenDev->m_RP.m_ViewOrg;
|
|
float dist = v.Length();
|
|
float distX = dist;
|
|
if (m_fDistSizeFactor != 1.0f)
|
|
distX = cry_powf(distX, m_fDistSizeFactor);
|
|
float distY = distX;
|
|
|
|
float fScaleCorona = m_fScaleCorona;
|
|
if (m_pScaleCoronaParams)
|
|
fScaleCorona = m_pScaleCoronaParams->mfGet();
|
|
|
|
if (obj->m_TempVars[2])
|
|
{
|
|
distX *= fScaleCorona * (obj->m_TempVars[2]/128.0f) * CRenderer::CV_r_coronasizescale;
|
|
distY *= fScaleCorona * (obj->m_TempVars[2]/128.0f) * CRenderer::CV_r_coronasizescale;
|
|
}
|
|
else
|
|
{
|
|
distX *= fScaleCorona * CRenderer::CV_r_coronasizescale;
|
|
distY *= fScaleCorona * CRenderer::CV_r_coronasizescale;
|
|
}
|
|
|
|
float fDecay = col[3];
|
|
fDecay *= CRenderer::CV_r_coronacolorscale;
|
|
norm = gRenDev->m_RP.m_CamVecs[0];
|
|
bool bBlind = false;
|
|
if (m_bBlind && obj->m_pLight)
|
|
{
|
|
CDLight *dl = obj->m_pLight;
|
|
if (dl->m_Flags & DLF_PROJECT)
|
|
{
|
|
bBlind = true;
|
|
v.Normalize();
|
|
float fDot = -(v * dl->m_Orientation.m_vForward);
|
|
if (fDot < 0.0f)
|
|
return;
|
|
float fBlindSize = fDot * m_fSizeBlindScale + m_fSizeBlindBias;
|
|
float fBlindIntens = fDot * m_fIntensBlindScale + m_fIntensBlindBias;
|
|
fDecay *= fBlindIntens;
|
|
distX *= fBlindSize;
|
|
distY *= fBlindSize;
|
|
/*
|
|
vx0 += distX * dl->m_Orientation.m_vForward;
|
|
vy0 += distY * dl->m_Orientation.m_vForward;
|
|
vx1 += distX * -dl->m_Orientation.m_vForward;
|
|
vy1 += distY * -dl->m_Orientation.m_vForward;
|
|
*/
|
|
|
|
vx0 *= distX;// * dl->m_Orientation.m_vForward;
|
|
vy0 *= distY;// * dl->m_Orientation.m_vForward;
|
|
vx1 *= -distX;// * -dl->m_Orientation.m_vForward;
|
|
vy1 *= -distY;// * -dl->m_Orientation.m_vForward;
|
|
|
|
float fDot1 = (rd->m_RP.m_CamVecs[1] * dl->m_Orientation.m_vForward);
|
|
float k=0.1f;
|
|
fDot1 = fDot1*(1.0f-k) + k;
|
|
vx0 *= fDot1+1.0f;
|
|
vx1 *= 1.0f - fDot1 + k;
|
|
|
|
float fDot2 = (rd->m_RP.m_CamVecs[2] * dl->m_Orientation.m_vForward);
|
|
fDot2 = fDot2*(1.0f-k) + k;
|
|
vy0 *= fDot2+1.0f;
|
|
vy1 *= 1.0f - fDot2 + k;
|
|
}
|
|
}
|
|
if (!bBlind)
|
|
{
|
|
vx0 *= distX;
|
|
vy0 *= distY;
|
|
vx1 *= -distX;
|
|
vy1 *= -distY;
|
|
}
|
|
if (m_fDistIntensityFactor != 1.0f)
|
|
fDecay = fDecay * cry_powf(dist, m_fDistIntensityFactor);
|
|
|
|
if (fDecay <= 0.001f)
|
|
return;
|
|
else
|
|
if (fDecay > 1.0f)
|
|
fDecay = 1.0f;
|
|
|
|
CGLTexMan::BindNULL(1);
|
|
rd->EF_SelectTMU(0);
|
|
rd->GLSetCull(eCULL_None);
|
|
rd->EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
|
|
|
|
CFColor c = col;
|
|
|
|
if (m_Pass)
|
|
{
|
|
int St = m_Pass->m_RenderState & GS_BLEND_MASK;
|
|
if (St == (GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA))
|
|
{
|
|
c[3] = fDecay;
|
|
}
|
|
else
|
|
{
|
|
c[0] = c[0] * fDecay;
|
|
c[1] = c[1] * fDecay;
|
|
c[2] = c[2] * fDecay;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bSun)
|
|
{
|
|
c[0] = c[0] * fDecay;
|
|
c[1] = c[1] * fDecay;
|
|
c[2] = c[2] * fDecay;
|
|
c[3] = fDecay;
|
|
}
|
|
else
|
|
{
|
|
c[0] = c[0] * fDecay;
|
|
c[1] = c[1] * fDecay;
|
|
c[2] = c[2] * fDecay;
|
|
}
|
|
}
|
|
|
|
if (CRenderer::CV_r_SunStyleCoronas)
|
|
bSun = true;
|
|
bool bRays = bSun && CRenderer::CV_r_checkSunVis == 2;
|
|
|
|
//if (CRenderer::CV_r_checkSunVis == 1 || CRenderer::CV_r_checkSunVis == 3 || !bSun || obj->m_TexId1<=0)
|
|
{
|
|
if (bRays)
|
|
rd->EF_SetState(GS_BLSRC_ONE | GS_BLDST_ONE);
|
|
else
|
|
rd->EF_SetState(GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST);
|
|
if (m_Map)
|
|
m_Map->Set();
|
|
if (m_Pass)
|
|
{
|
|
// Render the 8 triangles from the data stream
|
|
if (m_Pass && m_Pass->m_TUnits.Num())
|
|
{
|
|
CVProgram *curVP = NULL;
|
|
CVProgram *newVP;
|
|
SShaderPassHW *slw = m_Pass;
|
|
if (slw->mfSetTextures())
|
|
{
|
|
newVP = slw->m_VProgram;
|
|
|
|
// Set vertex program for the current pass if needed
|
|
if (newVP != curVP)
|
|
{
|
|
if (newVP)
|
|
{
|
|
curVP = newVP;
|
|
curVP->mfSet(true, slw, VPF_DONTSETMATRICES);
|
|
}
|
|
else
|
|
curVP = NULL;
|
|
}
|
|
|
|
rd->EF_ApplyMatrixOps(slw->m_MatrixOps, true);
|
|
|
|
// Set Render states for the current pass
|
|
int State;
|
|
if (rd->m_RP.m_RendPass || (rd->m_RP.m_ObjFlags & FOB_LIGHTPASS))
|
|
State = slw->m_SecondRenderState;
|
|
else
|
|
State = slw->m_RenderState;
|
|
rd->EF_SetState(State);
|
|
|
|
if (curVP)
|
|
{
|
|
curVP->mfSetStateMatrices();
|
|
curVP->mfSetVariables(false, &slw->m_VPParamsNoObj);
|
|
curVP->mfSetVariables(true, &slw->m_VPParamsObj);
|
|
}
|
|
else
|
|
{
|
|
rd->m_RP.m_CurrentVLights = 0;
|
|
rd->m_RP.m_PersFlags &= ~RBPF_VSNEEDSET;
|
|
}
|
|
|
|
// Set Pixel shaders and Register combiners for the current pass
|
|
if (slw->m_FShader)
|
|
slw->m_FShader->mfSet(true, slw);
|
|
else
|
|
rd->m_RP.m_PersFlags &= ~RBPF_PS1NEEDSET;
|
|
|
|
if (slw->m_FShader)
|
|
slw->m_FShader->mfSetVariables(true, slw->m_CGFSParamsObj);
|
|
else
|
|
rd->EF_CommitTexStageState();
|
|
|
|
rd->m_RP.m_RendPass++;
|
|
|
|
int bFogOverrided = 0;
|
|
rd->EF_CommitPS();
|
|
rd->EF_CommitVS();
|
|
if (rd->m_FS.m_bEnable)
|
|
bFogOverrided = rd->EF_FogCorrection(false, false);
|
|
|
|
{
|
|
glColor4fv(&c[0]);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
|
|
v = or;
|
|
glTexCoord2f(0.5f, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy0;
|
|
glTexCoord2f(0, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0;
|
|
glTexCoord2f(0, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy1;
|
|
glTexCoord2f(0, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vy1;
|
|
glTexCoord2f(0.5f, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1 + vy1;
|
|
glTexCoord2f(1, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1;
|
|
glTexCoord2f(1, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1 + vy0;
|
|
glTexCoord2f(1, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vy0;
|
|
glTexCoord2f(0.5f, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy0;
|
|
glTexCoord2f(0, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
rd->EF_FogCorrectionRestore(bFogOverrided);
|
|
}
|
|
|
|
slw->mfResetTextures();
|
|
rd->EF_ApplyMatrixOps(slw->m_MatrixOps, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
glColor4fv(&c[0]);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
|
|
v = or;
|
|
glTexCoord2f(0.5f, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy0;
|
|
glTexCoord2f(0, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0;
|
|
glTexCoord2f(0, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy1;
|
|
glTexCoord2f(0, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vy1;
|
|
glTexCoord2f(0.5f, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1 + vy1;
|
|
glTexCoord2f(1, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1;
|
|
glTexCoord2f(1, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1 + vy0;
|
|
glTexCoord2f(1, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vy0;
|
|
glTexCoord2f(0.5f, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy0;
|
|
glTexCoord2f(0, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
glEnd();
|
|
}
|
|
}
|
|
//else
|
|
if (bRays)
|
|
{
|
|
rd->EF_SetState(GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST);
|
|
rd->EF_SelectTMU(0);
|
|
rd->EnableTMU(true);
|
|
m_Map->Set();
|
|
rd->EF_SelectTMU(1);
|
|
rd->EnableTMU(true);
|
|
rd->m_TexMan->SetTexture(obj->m_TexId1, eTT_Base);
|
|
|
|
CPShader *pRC = NULL;
|
|
// If device supports register combiners use advanced sun rays
|
|
if (rd->GetFeatures() & RFT_HW_RC && !rd->m_RP.m_RCSun)
|
|
{
|
|
pRC = CPShader::mfForName("CGRCSun");
|
|
rd->m_RP.m_RCSun = pRC;
|
|
}
|
|
else
|
|
pRC = rd->m_RP.m_RCSun;
|
|
|
|
glColor3fv(&c[0]);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
if(pRC)
|
|
{
|
|
pRC->mfSet(true);
|
|
rd->EF_CommitPS();
|
|
}
|
|
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
|
|
v = or;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.5f, 0.5f);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.5f, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy0;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 1);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 0.5f);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy1;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 0);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vy1;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.5f, 0);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.5f, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1 + vy1;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0.5f);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0.5f);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx1 + vy0;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 1);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vy0;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.5f, 1);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.5f, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
v = or + vx0 + vy0;
|
|
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 1);
|
|
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
|
|
glVertex3fv(&v[0]);
|
|
|
|
glEnd();
|
|
|
|
if (pRC)
|
|
{
|
|
pRC->mfSet(false);
|
|
rd->EF_CommitPS();
|
|
}
|
|
rd->EnableTMU(false);
|
|
rd->EF_SelectTMU(0);
|
|
}
|
|
|
|
rd->m_nPolygons += 8;
|
|
rd->EF_PopFog();
|
|
}
|
|
|
|
bool CREFlare::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
if (!CRenderer::CV_r_flares && !CRenderer::CV_r_coronas)
|
|
return false;
|
|
|
|
CCObject *obj = gRenDev->m_RP.m_pCurObject;
|
|
if ((obj->m_ObjFlags & FOB_DRSUN) && (gRenDev->m_RP.m_PersFlags & RBPF_DONTDRAWSUN))
|
|
return false;
|
|
|
|
float fBrightness = (obj->m_AmbColor[0]+obj->m_AmbColor[1]+obj->m_AmbColor[2]+
|
|
obj->m_Angs2[0]+obj->m_Angs2[1]+obj->m_Angs2[2]+
|
|
obj->m_TempVars[3]+obj->m_TempVars[4]) * 0.125f;
|
|
|
|
if (!fBrightness)
|
|
return false;
|
|
|
|
Matrix44 m = gRenDev->GetCamera().GetVCMatrixD3D9();
|
|
glLoadMatrixf(&m(0,0));
|
|
|
|
obj->m_Color.r = m_Color.r;
|
|
obj->m_Color.g = m_Color.g;
|
|
obj->m_Color.b = m_Color.b;
|
|
obj->m_Color.a = fBrightness;
|
|
|
|
mfDrawCorona(ef, obj->m_Color);
|
|
mfDrawFlares(ef, obj->m_Color);
|
|
|
|
return true;
|
|
}
|
|
|
|
//=====================================================================================
|
|
|
|
bool CREClearStencil::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
glClearStencil(0);
|
|
glClear(GL_STENCIL_BUFFER_BIT);
|
|
return true;
|
|
}
|
|
|
|
bool CREHDRProcess::mfDraw(SShader *ef, SShaderPass *sfm)
|
|
{
|
|
return true;
|
|
} |