Files
FC1/RenderDll/XRenderOGL/GL_Renderer.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

3274 lines
90 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code
//
// File:GlRenderer.cpp
// Description: Implementation of the GL renderer API
//
// History:
// -Jan 31,2001:Originally created by Marco Corbetta
// -: taken over by Andrey Khonich
//
//////////////////////////////////////////////////////////////////////
#include "RenderPCH.h"
#include "GL_Renderer.h"
#include "GLCGVProgram.h"
#include "GLCGPShader.h"
// GL functions implement.
#define GL_EXT(name) byte SUPPORTS##name;
#define GL_PROC(ext,ret,func,parms) ret (__stdcall *func)parms;
#include "GLFuncs.h"
#undef GL_EXT
#undef GL_PROC
#include "../common/shadow_renderer.h"
#include "limits.h"
int CGLRenderer::CV_gl_useextensions;
int CGLRenderer::CV_gl_3dfx_gamma_control;
int CGLRenderer::CV_gl_arb_texture_compression;
int CGLRenderer::CV_gl_arb_multitexture;
int CGLRenderer::CV_gl_arb_pbuffer;
int CGLRenderer::CV_gl_arb_pixel_format;
int CGLRenderer::CV_gl_arb_buffer_region;
int CGLRenderer::CV_gl_arb_render_texture;
int CGLRenderer::CV_gl_arb_multisample;
int CGLRenderer::CV_gl_arb_vertex_program;
int CGLRenderer::CV_gl_arb_vertex_buffer_object;
int CGLRenderer::CV_gl_arb_fragment_program;
int CGLRenderer::CV_gl_arb_texture_env_combine;
int CGLRenderer::CV_gl_ext_swapcontrol;
int CGLRenderer::CV_gl_ext_bgra;
int CGLRenderer::CV_gl_ext_depth_bounds_test;
int CGLRenderer::CV_gl_ext_multi_draw_arrays;
int CGLRenderer::CV_gl_ext_compiled_vertex_array;
int CGLRenderer::CV_gl_ext_texture_cube_map;
int CGLRenderer::CV_gl_ext_separate_specular_color;
int CGLRenderer::CV_gl_ext_secondary_color;
int CGLRenderer::CV_gl_ext_texture_env_combine;
int CGLRenderer::CV_gl_ext_paletted_texture;
int CGLRenderer::CV_gl_ext_stencil_two_side;
int CGLRenderer::CV_gl_ext_stencil_wrap;
int CGLRenderer::CV_gl_ext_texture_filter_anisotropic;
int CGLRenderer::CV_gl_ext_texture_env_add;
int CGLRenderer::CV_gl_ext_texture_rectangle;
int CGLRenderer::CV_gl_hp_occlusion_test;
int CGLRenderer::CV_gl_nv_fog_distance;
int CGLRenderer::CV_gl_nv_texture_env_combine4;
int CGLRenderer::CV_gl_nv_point_sprite;
int CGLRenderer::CV_gl_nv_vertex_array_range;
int CGLRenderer::CV_gl_nv_fence;
int CGLRenderer::CV_gl_nv_register_combiners;
int CGLRenderer::CV_gl_nv_register_combiners2;
int CGLRenderer::CV_gl_nv_texgen_reflection;
int CGLRenderer::CV_gl_nv_texgen_emboss;
int CGLRenderer::CV_gl_nv_vertex_program;
int CGLRenderer::CV_gl_nv_vertex_program3;
int CGLRenderer::CV_gl_nv_texture_rectangle;
int CGLRenderer::CV_gl_nv_texture_shader;
int CGLRenderer::CV_gl_nv_texture_shader2;
int CGLRenderer::CV_gl_nv_texture_shader3;
int CGLRenderer::CV_gl_nv_fragment_program;
int CGLRenderer::CV_gl_nv_multisample_filter_hint;
int CGLRenderer::CV_gl_sgix_depth_texture;
int CGLRenderer::CV_gl_sgix_shadow;
int CGLRenderer::CV_gl_sgis_generate_mipmap;
int CGLRenderer::CV_gl_sgis_texture_lod;
int CGLRenderer::CV_gl_ati_separate_stencil;
int CGLRenderer::CV_gl_ati_fragment_shader;
int CGLRenderer::CV_gl_psforce11;
int CGLRenderer::CV_gl_vsforce11;
int CGLRenderer::CV_gl_nv30_ps20;
int CGLRenderer::CV_gl_alpha_bits;
int CGLRenderer::CV_gl_swapOnStart;
int CGLRenderer::CV_gl_clipplanes;
float CGLRenderer::CV_gl_normalmapscale;
float CGLRenderer::CV_gl_offsetfactor;
float CGLRenderer::CV_gl_offsetunits;
float CGLRenderer::CV_gl_pip_allow_var;
float CGLRenderer::CV_gl_pip_buff_size;
int CGLRenderer::CV_gl_rb_verts;
int CGLRenderer::CV_gl_rb_tris;
int CGLRenderer::CV_gl_maxtexsize;
int CGLRenderer::CV_gl_squaretextures;
int CGLRenderer::CV_gl_mipprocedures;
ICVar *CGLRenderer::CV_gl_texturefilter;
//////////////////////////////////////////////////////////////////////
CGLRenderer::CGLRenderer()
{
if (!gcpOGL)
gcpOGL = this;
#ifdef DEBUGALLOC
#undef new
#endif
m_TexMan = new CGLTexMan;
#ifdef DEBUGALLOC
#define new DEBUG_CLIENTBLOCK
#endif
m_LogFile = NULL;
m_Features = RFT_DIRECTACCESSTOVIDEOMEMORY;
m_numvidmodes=0;
m_vidmodes=NULL;
mMinDepth = 0;
mMaxDepth = 1.0f;
m_lod_biasSupported=false;
m_IsDedicated = false;
m_sbpp=0;
m_polygon_mode = R_SOLID_MODE;
m_pip_buffer_size = 0;
m_AGPbuf=0; m_nPolygons = 0; m_nFrameID = 0;
iConsole->Register("gl_UseExtensions", &CV_gl_useextensions, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_3DFX_gamma_control", &CV_gl_3dfx_gamma_control, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_texture_compression", &CV_gl_arb_texture_compression, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_multitexture", &CV_gl_arb_multitexture, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_pbuffer", &CV_gl_arb_pbuffer, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_pixel_format", &CV_gl_arb_pixel_format, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_buffer_region", &CV_gl_arb_buffer_region, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_render_texture", &CV_gl_arb_render_texture, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_multisample", &CV_gl_arb_multisample, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_vertex_program", &CV_gl_arb_vertex_program, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_vertex_buffer_object", &CV_gl_arb_vertex_buffer_object, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_fragment_program", &CV_gl_arb_fragment_program, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ARB_texture_env_combine", &CV_gl_arb_texture_env_combine, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_swapcontrol", &CV_gl_ext_swapcontrol, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_bgra", &CV_gl_ext_bgra, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_depth_bounds_test", &CV_gl_ext_depth_bounds_test, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_multi_draw_arrays", &CV_gl_ext_multi_draw_arrays, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_Compiled_Vertex_Array", &CV_gl_ext_compiled_vertex_array, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_texture_cube_map", &CV_gl_ext_texture_cube_map, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_separate_specular_color", &CV_gl_ext_separate_specular_color, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_secondary_color", &CV_gl_ext_secondary_color, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_paletted_texture", &CV_gl_ext_paletted_texture, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_stencil_two_side", &CV_gl_ext_stencil_two_side, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_stencil_wrap", &CV_gl_ext_stencil_wrap, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_texture_filter_anisotropic", &CV_gl_ext_texture_filter_anisotropic, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_texture_env_add", &CV_gl_ext_texture_env_add, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_texture_env_combine", &CV_gl_ext_texture_env_combine, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_EXT_texture_rectangle", &CV_gl_ext_texture_rectangle, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_HP_occlusion_test", &CV_gl_hp_occlusion_test, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_fog_distance", &CV_gl_nv_fog_distance, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texture_env_combine4", &CV_gl_nv_texture_env_combine4, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_point_sprite", &CV_gl_nv_point_sprite, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_vertex_array_range", &CV_gl_nv_vertex_array_range, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_fence", &CV_gl_nv_fence, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_register_combiners", &CV_gl_nv_register_combiners, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_register_combiners2", &CV_gl_nv_register_combiners2, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texgen_reflection", &CV_gl_nv_texgen_reflection, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texgen_emboss", &CV_gl_nv_texgen_emboss, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_vertex_program", &CV_gl_nv_vertex_program, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_vertex_program3", &CV_gl_nv_vertex_program3, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texture_rectangle", &CV_gl_nv_texture_rectangle, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texture_shader", &CV_gl_nv_texture_shader, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texture_shader2", &CV_gl_nv_texture_shader2, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_texture_shader3", &CV_gl_nv_texture_shader3, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_fragment_program", &CV_gl_nv_fragment_program, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV_multisample_filter_hint", &CV_gl_nv_multisample_filter_hint, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_SGIX_depth_texture", &CV_gl_sgix_depth_texture, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_SGIX_shadow", &CV_gl_sgix_shadow, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_SGIS_generate_mipmap", &CV_gl_sgis_generate_mipmap, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_SGIS_texture_lod", &CV_gl_sgis_texture_lod, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ATI_separate_stencil", &CV_gl_ati_separate_stencil, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_ATI_fragment_shader", &CV_gl_ati_fragment_shader, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_PSforce11", &CV_gl_psforce11, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_VSforce11", &CV_gl_vsforce11, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_NV30_PS20", &CV_gl_nv30_ps20, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_alpha_bits", &CV_gl_alpha_bits, 8, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_SwapOnStart", &CV_gl_swapOnStart, 0);
iConsole->Register("GL_ClipPlanes", &CV_gl_clipplanes, 1);
iConsole->Register("GL_OffsetFactor", &CV_gl_offsetfactor, -1.0f);
iConsole->Register("GL_OffsetUnits", &CV_gl_offsetunits, -4.0f);
iConsole->Register("GL_pip_allow_var", &CV_gl_pip_allow_var, 1.0f, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_pip_buff_size", &CV_gl_pip_buff_size, 10.0f, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_RB_verts", &CV_gl_rb_verts, 2048, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_RB_tris", &CV_gl_rb_tris, 3084, VF_REQUIRE_APP_RESTART);
iConsole->Register("GL_MaxTexSize", &CV_gl_maxtexsize, 0);
iConsole->Register("GL_SquareTextures", &CV_gl_squaretextures, 0);
iConsole->Register("GL_MipProcedures", &CV_gl_mipprocedures, 0);
CV_gl_texturefilter = iConsole->CreateVariable("GL_TextureFilter", "GL_LINEAR_MIPMAP_LINEAR", VF_DUMPTODISK );
iConsole->Register("GL_NormalMapScale", &CV_gl_normalmapscale, 0.15f, VF_REQUIRE_LEVEL_RELOAD);
memset(m_ShadowTexIDBuffer,0,sizeof(m_ShadowTexIDBuffer));
m_Features |= RFT_RGBA;
CV_r_envlighting = 0;
//if (!CV_gl_arb_vertex_buffer_object)
// CV_gl_psforce11 = 0;
}
CGLRenderer *gcpOGL = NULL;
#include <stdio.h>
//////////////////////////////////////////////////////////////////////
CGLRenderer::~CGLRenderer()
{
ShutDown();
gcpOGL = NULL;
}
void CGLRenderer::GLSetDefaultState()
{
// Set permanent state.
CheckError("Set state1");
glEnable (GL_DEPTH_TEST);
glEnable (GL_TEXTURE_2D);
glShadeModel (GL_SMOOTH);
glDisable (GL_ALPHA_TEST);
glDepthMask (GL_TRUE);
glDisable (GL_BLEND);
// glEnable (GL_SCISSOR_TEST);
//glScissor (0,0,m_width,m_height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glClearDepth (1.0f);
glDepthFunc (GL_LEQUAL);
glCullFace (GL_BACK);
glDisable (GL_CULL_FACE);
glBlendFunc (GL_ZERO,GL_SRC_COLOR);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
if (CV_r_fsaa && m_CurrContext->m_bFSAAWasSet && SUPPORTS_GL_NV_multisample_filter_hint)
{
if (CV_r_fsaa==2)
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
else
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_FASTEST);
}
glPixelStorei (GL_PACK_ALIGNMENT,1);
glPixelStorei (GL_UNPACK_ALIGNMENT,1);
glMatrixMode (GL_TEXTURE);
glLoadIdentity ();
glDisable (GL_LIGHTING);
glDisable (GL_BLEND);
glDisable (GL_LINE_SMOOTH);
glDrawBuffer (GL_BACK);
glStencilMask(0xff);
glHint (GL_FOG_HINT,GL_NICEST);
float globalAmbient[] = {1,1,1,1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmbient);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, false);
float emission[] = {0,0,0,0};
glMaterialfv(GL_FRONT, GL_EMISSION, emission);
CheckError("Set state2");
// Set permanent state.
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
glEnableClientState(GL_VERTEX_ARRAY);
m_TexMan->SetFilter(CV_gl_texturefilter->GetString());
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::EnableTMU(bool enable)
{
if (CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target && CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target != GL_TEXTURE_2D)
{
glDisable(CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target);
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target = 0;
}
if (enable)
{
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target = GL_TEXTURE_2D;
glEnable(GL_TEXTURE_2D);
}
else
{
glDisable(GL_TEXTURE_2D);
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Bind = 0;
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target = 0;
}
}
extern float glLodCorrection;
void sLogTexture (char *name, int Size);
extern int nFrameTexSize;
void CGLRenderer::ChangeLog()
{
if (CV_r_log && !m_LogFile)
{
if (CV_r_log == 3)
SetLogFuncs(true);
m_LogFile = fxopen ("OpenGLLog.txt", "w");
if (m_LogFile)
{
iLog->Log("OpenGL log file '%s' opened\n", "OpenGLLog.txt");
char time[128];
char date[128];
_strtime( time );
_strdate( date );
fprintf(m_LogFile, "\n==========================================\n");
fprintf(m_LogFile, "OpenGL Log file opened: %s (%s)\n", date, time);
fprintf(m_LogFile, "==========================================\n");
}
}
else
if (!CV_r_log && m_LogFile)
{
SetLogFuncs(false);
char time[128];
char date[128];
_strtime( time );
_strdate( date );
fprintf(m_LogFile, "\n==========================================\n");
fprintf(m_LogFile, "OpenGL Log file closed: %s (%s)\n", date, time);
fprintf(m_LogFile, "==========================================\n");
fclose(m_LogFile);
m_LogFile = NULL;
iLog->Log("OpenGL log file '%s' closed\n", "OpenGLLog.txt");
}
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::BeginFrame()
{
g_bProfilerEnabled = iSystem->GetIProfileSystem()->IsProfiling();
PROFILE_FRAME(Screen_Begin);
CheckError("BeginFrame");
if (CV_r_vsync != m_VSync)
{
m_VSync = CV_r_vsync;
EnableVSync(m_VSync?true:false);
}
if (CV_r_reloadshaders)
{
gRenDev->m_cEF.mfReloadAllShaders(CV_r_reloadshaders);
CV_r_reloadshaders = 0;
}
if (CV_r_fsaa != m_FSAA && m_CurrContext->m_bFSAAWasSet)
{
m_FSAA = CV_r_fsaa;
if (!m_FSAA)
{
glDisable(GL_MULTISAMPLE_ARB);
}
else
{
glEnable(GL_MULTISAMPLE_ARB);
if (SUPPORTS_GL_NV_multisample_filter_hint)
{
if (m_FSAA == 2)
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
else
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_FASTEST);
}
}
}
ChangeLog ();
if (m_CurrContext->m_hRC != pwglGetCurrentContext())
pwglMakeCurrent(m_CurrContext->m_hDC, m_CurrContext->m_hRC);
if (CV_gl_swapOnStart && m_bSwapBuffers)
SwapBuffers(m_CurrContext->m_hDC);
if (CV_r_gamma+m_fDeltaGamma != m_fLastGamma || CV_r_brightness != m_fLastBrightness || CV_r_contrast != m_fLastContrast)
SetGamma(CV_r_gamma+m_fDeltaGamma, CV_r_brightness, CV_r_contrast);
gRenDev->m_cEF.mfBeginFrame();
if (CV_r_PolygonMode != m_polygon_mode)
SetPolygonMode(CV_r_PolygonMode);
glMatrixMode(GL_MODELVIEW);
if (strcmp(CV_gl_texturefilter->GetString(), m_TexMan->m_CurTexFilter) || CV_r_texture_anisotropic_level != m_TexMan->m_CurAnisotropic)
m_TexMan->SetFilter(CV_gl_texturefilter->GetString());
m_nPolygons = 0;
m_nShadowVolumePolys=0;
m_nFrameID++;
m_nFrameUpdateID++;
m_bWasCleared = false;
m_RP.m_RealTime = iTimer->GetCurrTime();
TArray<CRETempMesh *> *tm = &m_RP.m_TempMeshes[m_nFrameID & 1];
for (int i=0; i<tm->Num(); i++)
{
CRETempMesh *re = tm->Get(i);
if (!re)
continue;
if (re->m_VBuffer)
{
ReleaseBuffer(re->m_VBuffer);
re->m_VBuffer = NULL;
}
ReleaseIndexBuffer(&re->m_Inds);
}
tm->SetUse(0);
m_RP.m_CurTempMeshes = tm;
if (CRenderer::CV_r_log)
Logv(0, "******************************* BeginFrame ********************************\n");
glColor4f(1,1,1,1);
nFrameTexSize = 0;
glDrawBuffer (GL_BACK);
ResetToDefault();
// EF_ClearBuffers(true);
}
bool CGLRenderer::ChangeResolution(int nNewWidth, int nNewHeight, int nNewColDepth, int nNewRefreshHZ, bool bFullScreen)
{
return false;
}
//////////////////////////////////////////////////////////////////////
bool CGLRenderer::ChangeDisplay(unsigned int width,unsigned int height,unsigned int bpp)
{
#ifdef WIN32
DWORD Mode = 0;
DEVMODE dm;
ZeroMemory(&dm,sizeof(dm));
EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dm);
dm.dmFields=0;
long lRes = 0;
if (width || height || bpp )
{
if (width && height)
if (width!=dm.dmPelsWidth || height != dm.dmPelsHeight )
{
dm.dmPelsWidth = width;
dm.dmPelsHeight= height;
dm.dmFields = dm.dmFields | DM_PELSWIDTH | DM_PELSHEIGHT;
}
if ((bpp) && (bpp != dm.dmBitsPerPel ))
{
dm.dmBitsPerPel = bpp;
dm.dmFields = dm.dmFields | DM_BITSPERPEL;
}
if (!dm.dmFields) return (true); //already in this mode
lRes = ChangeDisplaySettings(&dm, 0);
}
else
{
lRes = ChangeDisplaySettings(NULL, 0);
}
switch(lRes)
{
case DISP_CHANGE_SUCCESSFUL:
SetViewport(0, 0, width, height);
m_width = width;
m_height = height;
m_cbpp = bpp;
return (true);
break;
case DISP_CHANGE_RESTART:
case DISP_CHANGE_BADFLAGS:
case DISP_CHANGE_FAILED:
case DISP_CHANGE_BADMODE:
case DISP_CHANGE_NOTUPDATED:
//ChangeDisplaySettings(NULL, 0);
return (false);
iLog->Log("Cannot change display settings\n");
break;
}
return (false);
#else
return (false);
#endif
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::ChangeViewport(unsigned int x,unsigned int y,unsigned int width,unsigned int height)
{
SetViewport(x, y, width, height);
m_width = width;
m_height = height;
}
//////////////////////////////////////////////////////////////////////
extern int gEnvFrame;
//extern double timeFtoI, timeFtoL, timeQRound;
extern int nTexSize;
void CGLRenderer::DrawPoints(Vec3d v[], int nump, CFColor& col, int flags)
{
int i;
int st;
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
st = GS_NODEPTHTEST;
if (flags & 1)
st |= GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
else
if (flags & 2)
st = GS_DEPTHWRITE;
else
st = flags | GS_NODEPTHTEST;
EF_SetState(st);
glColor4fv(&col[0]);
glBegin(GL_POINTS);
for (i=0; i<nump; i++)
{
glVertex3fv(v[i]);
}
glEnd();
}
void CGLRenderer::DrawLines(Vec3d v[], int nump, CFColor& col, int flags, float fGround)
{
int i;
int st;
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
st = GS_NODEPTHTEST;
if (flags & 1)
st |= GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
else
st = flags | GS_NODEPTHTEST;
EF_SetState(st);
glDisableClientState(GL_COLOR_ARRAY);
glColor4fv(&col[0]);
if (fGround >= 0)
{
glBegin(GL_LINES);
for (i=0; i<nump; i++)
{
glVertex3f(v[i][0], fGround, 0);
glVertex3fv(v[i]);
}
glEnd();
}
else
{
glBegin(GL_LINE_STRIP);
for (i=0; i<nump; i++)
{
glVertex3fv(v[i]);
}
glEnd();
}
}
static void sDrawImage(float xpos,float ypos,float w,float h,int texture_id,float s0,float t0,float s1,float t1,float r,float g,float b,float a)
{
PROFILE_FRAME(Draw_2DImage);
gcpOGL->SetCullMode(R_CULL_DISABLE);
gcpOGL->SelectTMU(0);
if(texture_id>=0)
{
gcpOGL->EnableTMU(true);
gcpOGL->SetTexture(texture_id);
}
else
gcpOGL->EnableTMU(false);
glBegin(GL_QUADS);
glColor4f(r,g,b,a);
glTexCoord2f(s0, t1);
glVertex2f(xpos, ypos);
glColor4f(r,g,b,a);
glTexCoord2f(s1, t1);
glVertex2f(xpos+w, ypos);
glColor4f(r,g,b,a);
glTexCoord2f(s1, t0);
glVertex2f(xpos+w,ypos+h);
glColor4f(r,g,b,a);
glTexCoord2f(s0, t0);
glVertex2f(xpos, ypos+h);
glEnd();
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::Update()
{
PROFILE_FRAME(Screen_Update);
CheckError("Renderer::Update begin");
m_prevCamera = m_cam;
if (CV_r_showtimegraph)
{
static byte *fg;
static float fPrevTime = iTimer->GetCurrTime();
static int sPrevWidth = 0;
static int sPrevHeight = 0;
static int nC;
float fCurTime = iTimer->GetCurrTime();
float frametime = fCurTime - fPrevTime;
fPrevTime = fCurTime;
int wdt = m_width;
int hgt = m_height;
if (sPrevHeight != hgt || sPrevWidth != wdt)
{
if (fg)
{
delete [] fg;
fg = NULL;
}
sPrevWidth = wdt;
sPrevHeight = hgt;
}
if (!fg)
{
fg = new byte[wdt];
memset(fg, -1, wdt);
}
int type = CV_r_showtimegraph;
float f;
float fScale;
if (type > 2)
{
type = 2;
fScale = (float)CV_r_showtimegraph / 1000.0f;
}
else
fScale = 0.1f;
f = frametime / fScale;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
if (fg)
{
fg[nC] = (byte)f;
Graph(fg, 0, hgt-280, wdt, 256, nC, type, "Frame Time", Col_Green, fScale);
}
nC++;
if (nC == wdt)
nC = 0;
}
if (CV_r_logVBuffers)
{
GenerateVBLog("LogVBuffers.txt");
CV_r_logVBuffers = 0;
}
if (CV_r_measureoverdraw)
{
byte *buf = new byte [m_width*m_height];
glReadPixels(0, 0, m_width, m_height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
int size = m_width * m_height;
int acc = 0;
for (int i=0; i<size; i++)
{
acc += buf[i];
}
m_RP.m_PS.m_fOverdraw += (float)acc;
if (CV_r_measureoverdraw > 1)
{
static uint tBind = 0;
if (!tBind)
{
glGenTextures(1, &tBind);
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
{
glBindTexture(GL_TEXTURE_RECTANGLE_NV, tBind);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB8, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
byte *bBuf = new byte[m_width*m_height*3];
for (int i=0; i<size; i++)
{
int b = buf[i]*CV_r_measureoverdraw;
if (b > 255)
b = 255;
bBuf[i*3+0] = b;
bBuf[i*3+1] = b;
bBuf[i*3+2] = b;
}
EF_SetState(GS_NODEPTHTEST);
SetCullMode(R_CULL_NONE);
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
{
glBindTexture(GL_TEXTURE_RECTANGLE_NV, tBind);
glEnable(GL_TEXTURE_RECTANGLE_NV);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, m_width, m_height, GL_RGB, GL_UNSIGNED_BYTE, bBuf);
}
Set2DMode(true, m_width, m_height);
glBegin (GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f (0, (float)m_height, 1);
glTexCoord2f(0, (float)m_height);
glVertex3f (0, 0, 1);
glTexCoord2f((float)m_width, (float)m_height);
glVertex3f ((float)m_width, 0, 1);
glTexCoord2f((float)m_width, 0);
glVertex3f ((float)m_width, (float)m_height, 1);
glEnd ();
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
{
glDisable(GL_TEXTURE_RECTANGLE_NV);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
}
Set2DMode(false, m_width, m_height);
delete [] bBuf;
}
delete [] buf;
}
if (iConsole && iConsole->GetFont())
{
CRenderer *crend=gRenDev;
CXFont *cf=iConsole->GetFont();
if (CV_r_measureoverdraw)
crend->WriteXY(cf,550,75, 0.5f,1,1,1,1,1,"Overdraw=%0.3f",m_RP.m_PS.m_fOverdraw / (float)(m_width * m_height));
switch (CV_r_stats)
{
case 1:
crend->WriteXY(cf,10,270, 0.5f,1,1,1,1,1, "Unique Render Items=%d (%d)",m_RP.m_PS.m_NumRendItems, m_RP.m_PS.m_NumRendBatches);
crend->WriteXY(cf,10,290, 0.5f,1,1,1,1,1, "Unique VPrograms=%d",m_RP.m_PS.m_NumVShaders);
crend->WriteXY(cf,10,320, 0.5f,1,1,1,1,1, "Unique PShaders=%d",m_RP.m_PS.m_NumPShaders);
crend->WriteXY(cf,10,365, 0.5f,1,1,1,1,1,"Unique Textures=%d",m_RP.m_PS.m_NumTextures);
crend->WriteXY(cf,10,385, 0.5f,1,1,1,1,1,"TexturesSize=%.03f Kb",m_RP.m_PS.m_TexturesSize/1024.0f);
crend->WriteXY(cf,10,400, 0.5f,1,1,1,1,1,"Mesh update=%.03f Kb",m_RP.m_PS.m_MeshUpdateBytes/1024.0f);
break;
case 2:
{
crend->WriteXY(cf,550,140, 0.5f,1,1,1,1,1,"FFTTables=%0.3f",CREOcean::m_RS.m_StatsTimeFFTTable);
crend->WriteXY(cf,550,155, 0.5f,1,1,1,1,1,"FFT=%0.3f",CREOcean::m_RS.m_StatsTimeFFT);
crend->WriteXY(cf,550,170, 0.5f,1,1,1,1,1,"UpdateVerts=%0.3f",CREOcean::m_RS.m_StatsTimeUpdateVerts);
crend->WriteXY(cf,550,185, 0.5f,1,1,1,1,1,"BumpTexUpdate=%0.3f",CREOcean::m_RS.m_StatsTimeTexUpdate);
crend->WriteXY(cf,550,200, 0.5f,1,1,1,1,1,"RendOcean=%0.3f",CREOcean::m_RS.m_StatsTimeRendOcean);
crend->WriteXY(cf,550,215, 0.5f,1,1,1,1,1,"NumRendSectors=%d",CREOcean::m_RS.m_StatsNumRendOceanSectors);
crend->WriteXY(cf,550,230, 0.5f,1,1,1,1,1,"NumAllocatedSectors=%d",CREOcean::m_RS.m_StatsAllocatedSectors);
}
break;
case 3:
{
CLeafBuffer *pLB = CLeafBuffer::m_Root.m_Prev;
int nMem = 0;
while (pLB != &CLeafBuffer::m_Root)
{
nMem += pLB->GetAllocatedBytes(true);
pLB = pLB->m_Prev;
}
crend->WriteXY(cf,550,140, 0.5f,1,1,1,1,1,"LeafBuffer Vert. size=%0.3fMb",(float)nMem/1024.0f/1024.0f);
int num_used = 0, size_used = 0, num_all = 0, size_all = 0;
for(int i=0; i<m_alloc_info.Count(); i++)
{
if(m_alloc_info[i].busy)
{
num_used++;
size_used+=m_alloc_info[i].bytes_num;
}
num_all++;
size_all+=m_alloc_info[i].bytes_num;
}
crend->WriteXY(cf,550,160, 0.5f,1,1,1,1,1,"Total Vert. size=%0.3fMb",(float)size_all/1024.0f/1024.0f);
}
break;
case 4:
{
int i;
int nSize = 0;
int n = 0;
for (i=0; i<SShader::m_Shaders_known.GetSize(); i++)
{
SShader *pSH = SShader::m_Shaders_known[i];
if (!pSH)
continue;
nSize += pSH->Size(0);
n++;
}
crend->WriteXY(cf,550,160, 0.5f,1,1,1,1,1,"Shaders: %d, size=%0.3fMb",n , (float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<SShader::m_ShaderResources_known.Num(); i++)
{
SRenderShaderResources *pSR = SShader::m_ShaderResources_known[i];
if (!pSR)
continue;
nSize += pSR->Size();
n++;
}
crend->WriteXY(cf,550,175, 0.5f,1,1,1,1,1,"Shader Res: %d, size=%0.3fMb",n , (float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<SParamComp::m_ParamComps.Num(); i++)
{
nSize += SParamComp::m_ParamComps[i]->Size();
n++;
}
crend->WriteXY(cf,550,190, 0.5f,1,1,1,1,1,"Shader Comps: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CVProgram::m_VPrograms.Num(); i++)
{
nSize += CVProgram::m_VPrograms[i]->Size();
n++;
}
crend->WriteXY(cf,550,205, 0.5f,1,1,1,1,1,"VProgramms: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CPShader::m_PShaders.Num(); i++)
{
nSize += CPShader::m_PShaders[i]->Size();
n++;
}
crend->WriteXY(cf,550,220, 0.5f,1,1,1,1,1,"PShaders: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CLightStyle::m_LStyles.Num(); i++)
{
nSize += CLightStyle::m_LStyles[i]->Size();
n++;
}
crend->WriteXY(cf,550,235, 0.5f,1,1,1,1,1,"LStyles: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<SLightMaterial::known_materials.Num(); i++)
{
nSize += SLightMaterial::known_materials[i]->Size();
n++;
}
crend->WriteXY(cf,550,250, 0.5f,1,1,1,1,1,"LMaterials: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
while (pLB != &CLeafBuffer::m_RootGlobal)
{
n++;
nSize += pLB->Size(0);
pLB = pLB->m_NextGlobal;
}
crend->WriteXY(cf,550,280, 0.5f,1,1,1,1,1,"Mesh: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
while (pRE != &CRendElement::m_RootGlobal)
{
n++;
nSize += pRE->Size();
pRE = pRE->m_NextGlobal;
}
crend->WriteXY(cf,550,295, 0.5f,1,1,1,1,1,"Rend. Elements: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
{
STexPic *tp = gRenDev->m_TexMan->m_Textures[i];
if (!tp)
continue;
n++;
nSize += tp->Size(0);
}
crend->WriteXY(cf,550,310, 0.5f,1,1,1,1,1,"Textures: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
}
break;
}
}
m_TexMan->Update();
if (CV_r_profileshaders)
EF_PrintProfileInfo();
// draw debug bboxes and lines
std :: vector<BBoxInfo>::iterator itBBox = m_arrBoxesToDraw.begin(), itBBoxEnd = m_arrBoxesToDraw.end();
for( ; itBBox != itBBoxEnd; ++itBBox)
{
BBoxInfo& rBBox = *itBBox;
SetMaterialColor( rBBox.fColor[0], rBBox.fColor[1],
rBBox.fColor[2], rBBox.fColor[3] );
// set blend for transparent objects
if(rBBox.fColor[3]!=1.f)
EF_SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
switch(rBBox.nPrimType)
{
case DPRIM_LINE:
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_LOOP);
glVertex3f(rBBox.vMins.x,rBBox.vMins.y,rBBox.vMins.z);
glVertex3f(rBBox.vMaxs.x,rBBox.vMaxs.y,rBBox.vMaxs.z);
glEnd();
glEnable(GL_TEXTURE_2D);
break;
case DPRIM_WHIRE_BOX:
Flush3dBBox(rBBox.vMins, rBBox.vMaxs, false);
break;
case DPRIM_SOLID_BOX:
Flush3dBBox(rBBox.vMins, rBBox.vMaxs, true);
break;
case DPRIM_SOLID_SPHERE:
{
Vec3d vPos = (rBBox.vMins+rBBox.vMaxs)*0.5f;
float fRadius = (rBBox.vMins-rBBox.vMaxs).Length();
DrawBall(vPos, fRadius);
}
break;
}
if(rBBox.fColor[3]!=1.f)
{
EF_SetState(GS_DEPTHWRITE);
}
}
m_arrBoxesToDraw.clear();
/*if (m_TexMan->m_Text_ScreenLuminosityMap->m_Flags & FT_ALLOCATED)
{
EF_SetState(GS_NODEPTHTEST);
int iTmpX, iTmpY, iTempWidth, iTempHeight;
GetViewport(&iTmpX, &iTmpY, &iTempWidth, &iTempHeight);
Set2DMode(true, 1, 1);
SetViewport(10, 400, 100, 100);
sDrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenMap->m_Bind, 0, 0, m_TexMan->m_Text_ScreenMap->m_Width, m_TexMan->m_Text_ScreenMap->m_Height, 1,1,1,1);
SetViewport(120, 400, 100, 100);
sDrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenLowMap->m_Bind, 0, 0, m_TexMan->m_Text_ScreenLowMap->m_Width, m_TexMan->m_Text_ScreenLowMap->m_Height, 1,1,1,1);
SetViewport(230, 400, 100, 100);
sDrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenAvg1x1->m_Bind, 0, 0, m_TexMan->m_Text_ScreenAvg1x1->m_Width, m_TexMan->m_Text_ScreenAvg1x1->m_Height, 1,1,1,1);
SetViewport(340, 400, 100, 100);
sDrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenLuminosityMap->m_Bind, 0, 0, m_TexMan->m_Text_ScreenLuminosityMap->m_Width, m_TexMan->m_Text_ScreenLuminosityMap->m_Height, 1,1,1,1);
SetViewport(450, 400, 100, 100);
sDrawImage(0, 0, 1, 1, m_TexMan->m_Text_Glare->m_Bind, 0, 0, m_TexMan->m_Text_Glare->m_Width, m_TexMan->m_Text_Glare->m_Height, 1,1,1,1);
SetViewport(560, 400, 100, 100);
sDrawImage(0, 0, 1, 1, m_TexMan->m_Text_PrevScreenMap->m_Bind, 0, 0, m_TexMan->m_Text_PrevScreenMap->m_Width, m_TexMan->m_Text_PrevScreenMap->m_Height, 1,1,1,1);
Set2DMode(false, 1, 1);
SetViewport(iTmpX, iTmpY, iTempWidth, iTempHeight);
}*/
{
// print shadow volume stats
static ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3)
CRETriMeshShadow::PrintStats();
}
{ // print shadow maps on the screen
static ICVar *pVar = iConsole->GetCVar("e_shadow_maps_debug");
if(pVar && pVar->GetIVal()==2)
DrawAllShadowsOnTheScreen();
}
if (!CV_gl_swapOnStart && m_bSwapBuffers)
SwapBuffers(m_CurrContext->m_hDC);
if (CRenderer::CV_r_log)
Logv(0, "******************************* EndFrame ********************************\n");
if (CV_r_GetScreenShot)
{
ScreenShot();
CV_r_GetScreenShot = 0;
}
}
extern int BindSizes[];
extern int BindFrame[];
void CGLRenderer::GetMemoryUsage(ICrySizer* Sizer)
{
int i, nSize;
assert (Sizer);
//SIZER_COMPONENT_NAME(Sizer, "GLRenderer");
{
SIZER_COMPONENT_NAME(Sizer, "Renderer static");
Sizer->AddObject(&BindSizes[0], TX_LASTBIND * 4);
for (i=0; i<NUMRI_LISTS; i++)
{
Sizer->AddObject(&SRendItem::m_RendItems[i], SRendItem::m_RendItems[i].GetMemoryUsage());
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Renderer dynamic");
Sizer->Add(*this);
Sizer->AddObject(&CCObject::m_Waves, CCObject::m_Waves.GetMemoryUsage());
Sizer->AddObject(m_RP.m_VisObjects, MAX_REND_OBJECTS*sizeof(CCObject *));
Sizer->AddObject(&m_RP.m_TempObjects, m_RP.m_TempObjects.GetMemoryUsage());
Sizer->AddObject(&m_RP.m_Objects, m_RP.m_Objects.GetMemoryUsage());
Sizer->AddObject(&m_RP.m_ObjectsPool, m_RP.m_nNumObjectsInPool * sizeof(CCObject));
Sizer->AddObject(&m_RP.m_DLights, m_RP.m_DLights[0].GetMemoryUsage());
Sizer->AddObject(m_SysArray, m_SizeSysArray);
Sizer->AddObject(&m_RP.m_Splashes, m_RP.m_Splashes.GetMemoryUsage());
nSize = 0;
for (i=0; i<4; i++)
{
nSize += CREClientPoly::mPolysStorage[i].GetMemoryUsage();
}
nSize += CREClientPoly2D::mPolysStorage.GetMemoryUsage();
Sizer->AddObject(&CREClientPoly2D::mPolysStorage, nSize);
Sizer->AddObject(&m_RP.m_Sprites, m_RP.m_Sprites.GetMemoryUsage());
nSize = 0;
for (i=0; i<2; i++)
{
nSize += m_RP.m_TempMeshes[i].GetMemoryUsage();
}
Sizer->AddObject(&m_RP.m_TempMeshes, nSize);
Sizer->AddObject(&gCurLightStyles, gCurLightStyles.GetMemoryUsage());
Sizer->AddObject(&CName::mDuplicate, CName::Size());
}
{
SIZER_COMPONENT_NAME(Sizer, "Shaders");
for (i=0; i<SShader::m_Shaders_known.GetSize(); i++)
{
SShader *pSH = SShader::m_Shaders_known[i];
if (!pSH)
continue;
nSize = pSH->Size(0);
Sizer->AddObject(pSH, nSize);
}
{
SIZER_COMPONENT_NAME(Sizer, "Shader shared components");
for (i=0; i<SParamComp::m_ParamComps.Num(); i++)
{
nSize = SParamComp::m_ParamComps[i]->Size();
Sizer->AddObject(SParamComp::m_ParamComps[i], nSize);
}
for (i=0; i<CVProgram::m_VPrograms.Num(); i++)
{
nSize = CVProgram::m_VPrograms[i]->Size();
Sizer->AddObject(CVProgram::m_VPrograms[i], nSize);
}
for (i=0; i<CPShader::m_PShaders.Num(); i++)
{
nSize = CPShader::m_PShaders[i]->Size();
Sizer->AddObject(CPShader::m_PShaders[i], nSize);
}
for (i=0; i<CLightStyle::m_LStyles.Num(); i++)
{
nSize = CLightStyle::m_LStyles[i]->Size();
Sizer->AddObject(CLightStyle::m_LStyles[i], nSize);
}
for (i=0; i<SLightMaterial::known_materials.Num(); i++)
{
nSize = SLightMaterial::known_materials[i]->Size();
Sizer->AddObject(SLightMaterial::known_materials[i], nSize);
}
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Mesh");
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
while (pLB != &CLeafBuffer::m_RootGlobal)
{
nSize = pLB->Size(0);
Sizer->AddObject(pLB, nSize);
pLB = pLB->m_NextGlobal;
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Render elements");
CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
while (pRE != &CRendElement::m_RootGlobal)
{
nSize = pRE->Size();
Sizer->AddObject(pRE, nSize);
pRE = pRE->m_NextGlobal;
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Texture Objects");
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
{
STexPic *tp = gRenDev->m_TexMan->m_Textures[i];
if (!tp)
continue;
nSize = tp->Size(0);
Sizer->AddObject(tp, nSize);
}
Sizer->AddObject(&gRenDev->m_TexMan->m_Textures[0], gRenDev->m_TexMan->m_Textures.GetMemoryUsage());
Sizer->AddObject(&gRenDev->m_TexMan->m_FreeSlots[0], gRenDev->m_TexMan->m_FreeSlots.GetMemoryUsage());
Sizer->AddObject(&gRenDev->m_TexMan->m_TexData[0], 256*256*4);
Sizer->AddObject(&gRenDev->m_TexMan->m_EnvCMaps[0], sizeof(SEnvTexture)*MAX_ENVCUBEMAPS);
Sizer->AddObject(&gRenDev->m_TexMan->m_EnvTexts[0], sizeof(SEnvTexture)*MAX_ENVTEXTURES);
Sizer->AddObject(&gRenDev->m_TexMan->m_CustomCMaps[0], sizeof(SEnvTexture)*16);
Sizer->AddObject(&gRenDev->m_TexMan->m_CustomTextures[0], sizeof(SEnvTexture)*16);
Sizer->AddObject(&gRenDev->m_TexMan->m_Templates[0], sizeof(STexPic)*EFTT_MAX);
}
{
SIZER_COMPONENT_NAME(Sizer, "API Texture memory");
Sizer->AddObject(&nTexSize, nTexSize);
}
}
WIN_HWND CGLRenderer::GetHWND()
{
return m_CurrContext ? m_CurrContext->m_Glhwnd : 0;
}
//////////////////////////////////////////////////////////////////////
const char* CGLRenderer::ErrorString( GLenum errorCode )
{
static char *tess_error[] = {
"missing gluEndPolygon",
"missing gluBeginPolygon",
"misoriented contour",
"vertex/edge intersection",
"misoriented or self-intersecting loops",
"coincident vertices",
"colinear vertices",
"intersecting edges",
"not coplanar contours"
};
static char *nurbs_error[] = {
"spline order un-supported",
"too few knots",
"valid knot range is empty",
"decreasing knot sequence knot",
"knot multiplicity greater than order of spline",
"endcurve() must follow bgncurve()",
"bgncurve() must precede endcurve()",
"missing or extra geometric data",
"can't draw pwlcurves",
"missing bgncurve()",
"missing bgnsurface()",
"endtrim() must precede endsurface()",
"bgnsurface() must precede endsurface()",
"curve of improper type passed as trim curve",
"bgnsurface() must precede bgntrim()",
"endtrim() must follow bgntrim()",
"bgntrim() must precede endtrim()",
"invalid or missing trim curve",
"bgntrim() must precede pwlcurve()",
"pwlcurve referenced twice",
"pwlcurve and nurbscurve mixed",
"improper usage of trim data type",
"nurbscurve referenced twice",
"nurbscurve and pwlcurve mixed",
"nurbssurface referenced twice",
"invalid property",
"endsurface() must follow bgnsurface()",
"misoriented trim curves",
"intersecting trim curves",
"UNUSED",
"unconnected trim curves",
"unknown knot error",
"negative vertex count encountered",
"negative byte-stride encounteed",
"unknown type descriptor",
"null control array or knot vector",
"duplicate point on pwlcurve"
};
/* GL Errors */
if (errorCode==GL_NO_ERROR) {
return "no error";
}
else if (errorCode==GL_INVALID_VALUE) {
return "invalid value";
}
else if (errorCode==GL_INVALID_ENUM) {
return "invalid enum";
}
else if (errorCode==GL_INVALID_OPERATION) {
return "invalid operation";
}
else if (errorCode==GL_STACK_OVERFLOW) {
return "stack overflow";
}
else if (errorCode==GL_STACK_UNDERFLOW) {
return "stack underflow";
}
else if (errorCode==GL_OUT_OF_MEMORY) {
return "out of memory";
}
return NULL;
}
void CGLRenderer::CheckError(const char *comment)
{
GLenum err = glGetError();
int errnum=0;
while (err != GL_NO_ERROR)
{
char * pErrText = (char*)ErrorString(err);
if (comment)
_text_to_log( "glGetError: %s: %s", pErrText ? pErrText : "-", comment);
else
_text_to_log( "glGetError: %s:", pErrText ? pErrText : "-");
err = glGetError();
if (++errnum>10)
break;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//MISC TEXTURE FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
void CGLRenderer::SetTexture(int tnum)
{
if(tnum > INT_MAX/2)
{ // tnum is a shifted pointer to CImage structure
CImage * pImage = (CImage *)(tnum - INT_MAX/2);
ASSERT(pImage && pImage->m_valid_test == 123);
if(!pImage->GetTextureId())
{ // if not loaded
pImage->SetTextureId(LoadTexture(pImage->GetName(),&pImage->m_type));
}
glBindTexture(GL_TEXTURE_2D,pImage->GetTextureId());
pImage->m_last_time_used = iTimer->GetCurrTime();
iConsole->Exit("tnum > INT_MAX/2");
}
else
{
if (tnum>=0 && tnum!=m_lastbind[m_currstage])
{
glBindTexture(GL_TEXTURE_2D,tnum);
m_lastbind[m_currstage]=tnum;
}
}
}*/
//====================================================================
//////////////////////////////////////////////////////////////////////
/*void CGLRenderer::SetTexture(CImage *image)
{
SetTexture(image->GetTextureId());
} */
void CGLRenderer::SetTexClampMode(bool clamp)
{
if (!clamp)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
//////////////////////////////////////////////////////////////////////
unsigned int CGLRenderer::DownLoadToVideoMemory(unsigned char *data,int w, int h, ETEX_Format eTFSrc, ETEX_Format eTFDst, int nummipmap, bool repeat, int filter, int Id, char *szCacheName, int flags)
{
unsigned int tnum;
/* char name[128];
sprintf(name, "$Auto_%d", m_TexGenID++);
int flags = nummipmap ? 0 : FT_NOMIPS | FT_NOWORLD;
int DXTSize = 0;
int blockSize = 0;
if (eTFSrc == eTF_DXT1)
{
flags |= FT_DXT1;
blockSize = 8;
}
else
if (eTFSrc == eTF_DXT3)
{
flags |= FT_DXT3;
blockSize = 16;
}
else
if (eTFSrc == eTF_DXT5)
{
flags |= FT_DXT5;
blockSize = 16;
}
if (blockSize)
{
if (!nummipmap)
nummipmap = 1;
int wdt = w;
int hgt = h;
for (int i=0; i<nummipmap; i++)
{
DXTSize += ((wdt+3)/4)*((hgt+3)/4)*blockSize;
wdt >>= 1;
hgt >>= 1;
if (!wdt)
wdt = 1;
if (!hgt)
hgt = 1;
}
}
if (!repeat)
flags |= FT_CLAMP;
if (eTFDst==eTF_8888)
flags |= FT_HASALPHA;
STexPic *tp = m_TexMan->DownloadTexture(name, w, h, flags, FT2_NODXT, data, eTT_Base, DXTSize, NULL, 0, eTFSrc);
return (tp->m_Bind); */
tnum = Id;
ETexType eTT = eTT_Base;
int nW = ilog2(w);
int nH = ilog2(h);
if (w-nW || h-nH)
{
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
eTT = eTT_Rectangle;
}
if (tnum == 0)
glGenTextures(1,&tnum);
assert(tnum<14000);
SetTexture(tnum, eTT);
int tgt = GL_TEXTURE_2D;
if (eTT == eTT_Rectangle)
tgt = GL_TEXTURE_RECTANGLE_NV;
int srcformat, dstformat;
if (eTFSrc==eTF_DXT1)
srcformat=GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
if (eTFDst==eTF_DXT1)
dstformat=GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
if (eTFSrc==eTF_0888)
srcformat=GL_BGR_EXT;
if (eTFDst==eTF_0888)
dstformat=GL_RGB8;
if (eTFSrc==eTF_8888)
srcformat=GL_BGRA_EXT;
if (eTFDst==eTF_8888)
dstformat=GL_RGBA;
if (eTFSrc==eTF_RGBA)
srcformat=GL_RGBA;
if (eTFDst==eTF_RGBA)
dstformat=GL_RGBA;
if (eTFSrc==eTF_8000)
srcformat=GL_ALPHA;
if (eTFDst==eTF_8000)
dstformat=GL_ALPHA;
if (eTFSrc==eTF_4444)
srcformat=GL_RGBA4;
if (eTFDst==eTF_4444)
dstformat=GL_RGBA4;
if (repeat)
{
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
else
{
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
// filter mode
if (filter==FILTER_BILINEAR)
{
glTexParameteri(tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else if (filter==FILTER_TRILINEAR)
{
glTexParameteri(tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else if(filter==FILTER_LINEAR)
{
glTexParameteri(tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(tgt, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tgt, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (nummipmap)
{
glTexImage2D( tgt,
1-nummipmap,
dstformat,
w,
h,
0,
srcformat,
GL_UNSIGNED_BYTE, data);
}
else
{
if (filter == FILTER_TRILINEAR || filter == FILTER_BILINEAR)
{
if (SUPPORTS_GL_SGIS_generate_mipmap)
glTexParameteri(tgt, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
}
if (eTFDst==eTF_DXT1)
{
int blockSize = (eTFDst == eTF_DXT1) ? 8 : 16;
int size = ((w+3)/4)*((h+3)/4)*blockSize;
glCompressedTexImage2DARB(tgt,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,w,h,0,size,data);
}
else
glTexImage2D(tgt,
0,//1-mlevels,
dstformat,
w,
h,
0,
srcformat,
GL_UNSIGNED_BYTE, data);
}
return (tnum);
}
extern int TargetTex[TX_LASTBIND];
//////////////////////////////////////////////////////////////////////
void CGLRenderer::UpdateTextureInVideoMemory(uint tnum, unsigned char *newdata,int posx,int posy,int w,int h,ETEX_Format eTF)
{
ETexType eTT = eTT_Base;
if (TargetTex[tnum] == GL_TEXTURE_RECTANGLE_NV)
eTT = eTT_Rectangle;
SetTexture(tnum, eTT);
int srcformat;
if (eTF == eTF_DXT1)
srcformat=GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
if (eTF == eTF_0888)
srcformat=GL_BGR_EXT;// GL_RGB8
if (eTF==eTF_8888)
srcformat=GL_BGRA_EXT;// GL_RGBA;
if (eTF==eTF_4444)
{
srcformat=GL_RGBA4;
assert(0); // not supported in opengl as source format
}
if (eTF == eTF_DXT1)
{
int blockSize = (eTF == eTF_DXT1) ? 8 : 16;
int size = ((w+3)/4)*((h+3)/4)*blockSize;
//glCompressedTexSubImage2DARB(GL_TEXTURE_2D,0,posx,posy,w,h,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,size,newdata);
//glCompressedTexImage2DARB(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,w,h,0,size,newdata);
glCompressedTexSubImage2DARB(TargetTex[tnum],0,posx,posy,w,h,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,size,newdata);
}
else
{
if (TargetTex[tnum] == GL_TEXTURE_2D)
{
int nw = ilog2(w);
if (w != nw)
return;
int nh = ilog2(h);
if (h != nh)
return;
}
glTexSubImage2D(TargetTex[tnum],0,posx,posy,w,h,srcformat,GL_UNSIGNED_BYTE,newdata);
}
}
void CGLRenderer::RemoveTexture(ITexPic * pTexPic)
{
if(!pTexPic)
return;
STexPic * pSTexPic = (STexPic *)pTexPic;
pSTexPic->Release(false);
}
void CGLRenderer::RemoveTexture(unsigned int nTextureId)
{
if(nTextureId)
{
STexPic *tp = m_TexMan->GetByID(nTextureId);
if (tp)
tp->Release(false);
else
{
CGLTexMan::m_TUState[CGLTexMan::m_CurStage].m_Bind = 0;
CGLTexMan::m_TUState[CGLTexMan::m_CurStage].m_Target = 0;
glDeleteTextures(1, &nTextureId);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//IMAGES DRAWING
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
void CGLRenderer::Draw2dImage(float xpos,float ypos,float w,float h,int texture_id,float s0,float t0,float s1,float t1,float angle,float r,float g,float b,float a, float z)
{
PROFILE_FRAME(Draw_2DImage);
xpos=(float)ScaleCoordX(xpos);
ypos=(float)ScaleCoordY(ypos)-1.0f;
w=(float)ScaleCoordX(w)+1.0f;
h=((float)ScaleCoordY(h))+2.0f;
bool bSaveZTest = ((m_CurState & GS_NODEPTHTEST) == 0);
SetCullMode(R_CULL_DISABLE);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, m_width, m_height, 0.0, -9999.0, 9999.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
SelectTMU(0);
ETexType eTT = eTT_Base;
if (texture_id >= 0)
{
if (TargetTex[texture_id] == GL_TEXTURE_RECTANGLE_NV)
eTT = eTT_Rectangle;
}
float fXSc = 1.0f;
float fYSc = 1.0f;
if(texture_id>0)
{
SetTexture(texture_id, eTT);
if (eTT == eTT_Rectangle)
{
int nW, nH;
glGetTexLevelParameteriv(TargetTex[texture_id], 0, GL_TEXTURE_WIDTH, &nW);
glGetTexLevelParameteriv(TargetTex[texture_id], 0, GL_TEXTURE_HEIGHT, &nH);
fXSc = (float)nW;
fYSc = (float)nH;
}
}
else
EnableTMU(false);
EF_SetColorOp(255, 255, DEF_TEXARG0, DEF_TEXARG0);
glBegin(GL_QUADS);
if (angle!=0)
{
float xsub=(float)(xpos+w/2);
float ysub=(float)(ypos+h/2);
float x,y,x1,y1;
float mcos=cry_cosf(DEG2RAD(angle));
float msin=cry_sinf(DEG2RAD(angle));
x=xpos-xsub;
y=ypos-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
glColor4f(r,g,b,a);
glTexCoord2f(s0, 1.f-t0);
glVertex3f(x1, y1, z);
x=xpos+w-xsub;
y=ypos-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
glColor4f(r,g,b,a);
glTexCoord2f(s1, 1.f-t0);
glVertex3f(x1, y1, z);
x=xpos+w-xsub;
y=ypos+h-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
glColor4f(r,g,b,a);
glTexCoord2f(s1, 1.f-t1);
glVertex3f(x1,y1,z);
x=xpos-xsub;
y=ypos+h-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
glColor4f(r,g,b,a);
glTexCoord2f(s0, 1.f-t1);
glVertex3f(x1,y1,z);
}
else
{
glColor4f(r,g,b,a);
glTexCoord2f(s0*fXSc, (1.f-t0)*fYSc);
glVertex3f((xpos), (ypos), z);
glColor4f(r,g,b,a);
glTexCoord2f(s1*fXSc, (1.f-t0)*fYSc);
glVertex3f((xpos+w), (ypos), z);
glColor4f(r,g,b,a);
glTexCoord2f(s1*fXSc, (1.f-t1)*fYSc);
glVertex3f((xpos+w),(ypos+h),z);
glColor4f(r,g,b,a);
glTexCoord2f(s0*fXSc, (1.f-t1)*fYSc);
glVertex3f((xpos), (ypos+h),z);
}
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::DrawImage(float xpos,float ypos,float w,float h,int texture_id,float s0,float t0,float s1,float t1,float r,float g,float b,float a)
{
PROFILE_FRAME(Draw_2DImage);
SetCullMode(R_CULL_DISABLE);
SelectTMU(0);
if(texture_id>=0)
{
EnableTMU(true);
SetTexture(texture_id);
}
else
EnableTMU(false);
glBegin(GL_QUADS);
glColor4f(r,g,b,a);
glTexCoord2f(s0, 1.f-t0);
glVertex2f((float)(xpos), (float)(ypos));
glColor4f(r,g,b,a);
glTexCoord2f(s1, 1.f-t0);
glVertex2f((float)(xpos+w), (float)(ypos));
glColor4f(r,g,b,a);
glTexCoord2f(s1, 1.f-t1);
glVertex2f((float)(xpos+w),(float)(ypos+h));
glColor4f(r,g,b,a);
glTexCoord2f(s0, 1.f-t1);
glVertex2f((float)(xpos), (float)(ypos+h));
glEnd();
}
///////////////////////////////////////////
void CGLRenderer::SetCullMode(int mode)
{
switch (mode)
{
case R_CULL_DISABLE:
GLSetCull(eCULL_None);
break;
case R_CULL_BACK:
GLSetCull(eCULL_Back);
break;
case R_CULL_FRONT:
GLSetCull(eCULL_Front);
break;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//FOG
////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
void CGLRenderer::SetFog(float density,float fogstart,float fogend,const float *color,int fogmode)
{
if (fogmode==R_FOGMODE_LINEAR)
glFogi(GL_FOG_MODE,GL_LINEAR);
else
if (fogmode==R_FOGMODE_EXP2)
glFogi(GL_FOG_MODE,GL_EXP2);
//fogend = 200;
m_FS.m_FogDensity = density;
m_FS.m_FogStart = fogstart;
m_FS.m_FogEnd = fogend;
m_FS.m_nFogMode = fogmode;
CFColor col = CFColor(color[0], color[1], color[2], 1.0f);
if (m_bHeatVision)
col = CFColor(0.0f, 0.0f, 0.0f, 1.0f);
m_FS.m_FogColor = col;
glFogf(GL_FOG_DENSITY,density);
glFogf(GL_FOG_START, fogstart);
glFogf(GL_FOG_END, fogend);
glFogfv(GL_FOG_COLOR,&col[0]);
if (SUPPORTS_GL_NV_fog_distance)
{
glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
}
}
///////////////////////////////////////////
bool CGLRenderer::EnableFog(bool enable)
{
bool bPrevFog = m_FS.m_bEnable; // remember fog value
if (enable)
glEnable(GL_FOG);
else
glDisable(GL_FOG);
m_FS.m_bEnable = enable;
return bPrevFog;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//TEXGEN
////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
void CGLRenderer::EnableTexGen(bool enable)
{
if(enable)
{
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
// glEnable(GL_TEXTURE_GEN_R);
// glEnable(GL_TEXTURE_GEN_Q);
}
else
{
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
}
}
///////////////////////////////////////////
void CGLRenderer::SetTexgen(float scaleX,float scaleY,float translateX,float translateY)
{
GLfloat eyePlaneT[] = { scaleX, 0.0f, 0.0f, translateX };
GLfloat eyePlaneS[] = { 0.0f, scaleY, 0.0f, translateY };
glTexGenfv(GL_S, GL_OBJECT_PLANE, eyePlaneS);
glTexGenfv(GL_T, GL_OBJECT_PLANE, eyePlaneT);
glTexGenf(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGenf(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
}
void CGLRenderer::SetTexgen3D(float x1, float y1, float z1, float x2, float y2, float z2)
{
GLfloat eyePlaneS[] = { x1, y1, z1, 0 };
GLfloat eyePlaneT[] = { x2, y2, z2, 0 };
glTexGenfv(GL_S, GL_OBJECT_PLANE, eyePlaneS);
glTexGenfv(GL_T, GL_OBJECT_PLANE, eyePlaneT);
glTexGenf(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGenf(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//MISC EXTENSIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
void CGLRenderer::SetLodBias(float value)
{
if (m_lod_biasSupported)
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, value);
}
///////////////////////////////////////////
void CGLRenderer::EnableVSync(bool enable)
{
if (wglSwapIntervalEXT)
{
if (enable)
wglSwapIntervalEXT(1);
else
wglSwapIntervalEXT(0);
}
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::SelectTMU(int tnum)
{
EF_SelectTMU(tnum);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//MATRIX FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
void CGLRenderer::PushMatrix()
{
glPushMatrix();
}
///////////////////////////////////////////
void CGLRenderer::RotateMatrix(float a,float x,float y,float z)
{
glRotatef(a,x,y,z);
}
void CGLRenderer::RotateMatrix(const Vec3d & angles)
{
glRotatef(angles.z,0,0,1);
glRotatef(angles.y,0,1,0);
glRotatef(angles.x,1,0,0);
}
///////////////////////////////////////////
void CGLRenderer::TranslateMatrix(float x,float y,float z)
{
glTranslatef(x,y,z);
}
void CGLRenderer::MultMatrix(float * mat)
{
glMultMatrixf(mat);
}
void CGLRenderer::TranslateMatrix(const Vec3d &pos)
{
glTranslatef(pos.x,pos.y,pos.z);
}
///////////////////////////////////////////
void CGLRenderer::ScaleMatrix(float x,float y,float z)
{
glScalef(x,y,z);
}
///////////////////////////////////////////
void CGLRenderer::PopMatrix()
{
glPopMatrix();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void CGLRenderer::LoadMatrix(const Matrix44 *src)
{
if(src)
glLoadMatrixf((float *)src);
else
glLoadIdentity();
}
void CGLRenderer::Flush3dBBox(const Vec3d &mins,const Vec3d &maxs,const bool bSolid)
{
if(bSolid)
{
EnableTMU(false);
SetCullMode(R_CULL_NONE);
glBegin(GL_QUADS);
glVertex3f(maxs.x,mins.y,mins.z); //3
glVertex3f(maxs.x,mins.y,maxs.z); //2
glVertex3f(mins.x,mins.y,maxs.z); //1
glVertex3f(mins.x,mins.y,mins.z); //0
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); //54
glVertex3f(maxs.x,maxs.y,maxs.z); //73
glVertex3f(maxs.x,mins.y,maxs.z); //22
glVertex3f(maxs.x,mins.y,mins.z); //31
glEnd();
EnableTMU(true);
}
else
{
EnableTMU(false);
SetCullMode(R_CULL_NONE);
glBegin(GL_LINE_LOOP);
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_LINE_LOOP);
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_LINE_LOOP);
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_LINE_LOOP);
glVertex3f(maxs.x,mins.y,mins.z); //3
glVertex3f(maxs.x,mins.y,maxs.z); //2
glVertex3f(maxs.x,maxs.y,maxs.z); //7
glVertex3f(maxs.x,maxs.y,mins.z); //5
glEnd();
EnableTMU(true);
}
}
///////////////////////////////////////////
void CGLRenderer::Draw3dBBox(const Vec3d &mins,const Vec3d &maxs, int nPrimType)
{
Draw3dPrim(mins, maxs, nPrimType);
}
void CGLRenderer::Draw3dPrim(const Vec3d &mins,const Vec3d &maxs, int nPrimType, const float* pRGBA)
{
BBoxInfo info;
info.vMins = mins;
info.vMaxs = maxs;
info.nPrimType = nPrimType;
if (pRGBA)
{
for (int i = 0; i < 4; ++i)
info.fColor[i] = pRGBA[i];
}
else
glGetFloatv(GL_CURRENT_COLOR, (float*)info.fColor);
m_arrBoxesToDraw.push_back(info);
}
///////////////////////////////////////////
int CGLRenderer::SetPolygonMode(int mode)
{
int prev_mode = m_polygon_mode;
m_polygon_mode = mode;
if (mode==R_WIREFRAME_MODE)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
return prev_mode;
}
///////////////////////////////////////////
void CGLRenderer::SetPerspective(const CCamera &cam)
{
gluPerspective(cam.GetFov()/(gf_PI/180.0f)*cam.GetProjRatio(), 1.0f/cam.GetProjRatio(), cam.GetZMin(), cam.GetZMax());
}
///////////////////////////////////////////
void CGLRenderer::SetCamera(const CCamera &cam)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// camera.fov is for horizontal -> GL needs it vertical
// projection.ratio is height/width -> GL needs width/height
gluPerspective(cam.GetFov()/(gf_PI/180.0f)*cam.GetProjRatio(), 1.0f/cam.GetProjRatio(), cam.GetZMin(), cam.GetZMax());
glMatrixMode(GL_MODELVIEW);
Matrix44 mat = cam.GetVCMatrixD3D9();
glLoadMatrixf(mat.GetData());
EF_SetCameraInfo();
m_cam=cam;
}
void CGLRenderer::SetViewport(int x, int y, int width, int height)
{
if (!x && !y && !width && !height)
{
if(glViewport)
glViewport(m_VX, m_VY, m_VWidth, m_VHeight);
return;
}
if(glViewport)
glViewport(x, y, width, height);
m_VX = x;
m_VY = y;
m_VWidth = width;
m_VHeight = height;
}
void CGLRenderer::SetScissor(int x, int y, int width, int height)
{
if (!x && !y && !width && !height)
EF_Scissor(false, x, y, width, height);
else
EF_Scissor(true, x, y, width, height);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::GetModelViewMatrix(float * mat)
{
glGetFloatv(GL_MODELVIEW_MATRIX, mat);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::GetModelViewMatrix(double *mat)
{
glGetDoublev(GL_MODELVIEW_MATRIX, mat);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::GetProjectionMatrix(double *mat)
{
glGetDoublev(GL_PROJECTION_MATRIX, mat);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::GetProjectionMatrix(float *mat)
{
glGetFloatv(GL_PROJECTION_MATRIX, mat);
}
//////////////////////////////////////////////////////////////////////
Vec3d CGLRenderer::GetUnProject(const Vec3d &WindowCoords,const CCamera &cam)
{
/*double sx=WindowCoords.x;
double sy=WindowCoords.y;
double sz=WindowCoords.z;
double px,py,pz;
int nViewport[4]={0,0,m_width,m_height};
int res=gluUnProject(sx,sy,sz,
cam.m_fViewMatrix,
cam.m_fProjMatrix,
nViewport,
&px,&py,&pz);
return (Vec3d((float)(px),(float)(py),(float)(pz))); */
return (Vec3d(0,0,0));
}
void CGLRenderer::DrawQuad(float x0, float y0, float x1, float y1, const CFColor & color, float z)
{
PROFILE_FRAME(Draw_2DImage);
glColor4fv(&color[0]);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex3f(x0, y1, z);
glTexCoord2f(1,0);
glVertex3f(x1, y1, z);
glTexCoord2f(1,1);
glVertex3f(x1, y0, z);
glTexCoord2f(0,1);
glVertex3f(x0, y0, z);
glEnd();
m_nPolygons += 2;
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::DrawQuad(const Vec3d &right, const Vec3d &up, const Vec3d &origin,int nFlipmode/*=0*/)
{
glBegin(GL_QUADS);
Vec3d curr;
if (nFlipmode==1)
{
curr=origin+(-right-up);
glTexCoord2f(1,0);
glVertex3fv((float *)&curr);
curr=origin+(right-up);
glTexCoord2f(0,0);
glVertex3fv((float *)&curr);
curr=origin+(right+up);
glTexCoord2f(0,1);
glVertex3fv((float *)&curr);
curr=origin+(-right+up);
glTexCoord2f(1,1);
glVertex3fv((float *)&curr);
}
else
if (nFlipmode==2)
{
curr=origin+(-right-up);
glTexCoord2f(0,1);
glVertex3fv((float *)&curr);
curr=origin+(right-up);
glTexCoord2f(1,1);
glVertex3fv((float *)&curr);
curr=origin+(right+up);
glTexCoord2f(1,0);
glVertex3fv((float *)&curr);
curr=origin+(-right+up);
glTexCoord2f(0,0);
glVertex3fv((float *)&curr);
}
else
{
curr=origin+(-right-up);
glTexCoord2f(0,0);
glVertex3fv((float *)&curr);
curr=origin+(right-up);
glTexCoord2f(1,0);
glVertex3fv((float *)&curr);
curr=origin+(right+up);
glTexCoord2f(1,1);
glVertex3fv((float *)&curr);
curr=origin+(-right+up);
glTexCoord2f(0,1);
glVertex3fv((float *)&curr);
}
glEnd();
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::ProjectToScreen( float ptx, float pty, float ptz,
float *sx, float *sy, float *sz )
{
float g_ProjectionMatrix[16];
float g_ModelMatrix[16];
int g_Viewport[4];
glGetFloatv(GL_PROJECTION_MATRIX,g_ProjectionMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX,g_ModelMatrix);
glGetIntegerv(GL_VIEWPORT,g_Viewport);
SGLFuncs::gluProject(ptx,pty,ptz,
g_ModelMatrix,
g_ProjectionMatrix,
g_Viewport,
sx,sy,sz);
(*sx) = (*sx) * 100/m_width;
(*sy) = 100 - (*sy) * 100/m_height;
}
int CGLRenderer::UnProject(float sx, float sy, float sz,
float *px, float *py, float *pz,
const float modelMatrix[16],
const float projMatrix[16],
const int viewport[4])
{
return SGLFuncs::gluUnProject(sx,sy,sz,
modelMatrix,
projMatrix,
viewport,
px,py,pz);
}
//////////////////////////////////////////////////////////////////////
int CGLRenderer::UnProjectFromScreen( float sx, float sy, float sz,
float *px, float *py, float *pz)
{
float g_ProjectionMatrix[16];
float g_ModelMatrix[16];
int g_Viewport[4];
glGetFloatv(GL_MODELVIEW_MATRIX, g_ModelMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, g_ProjectionMatrix);
glGetIntegerv(GL_VIEWPORT, g_Viewport);
int res=SGLFuncs::gluUnProject(sx,sy,sz,
g_ModelMatrix,
g_ProjectionMatrix,
g_Viewport,
px,py,pz);
CheckError("unproj");
return(res);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::Draw2dLine (float x1,float y1,float x2,float y2)
{
float x1pos=(float)(int)ScaleCoordX(x1);
float y1pos=(float)(int)ScaleCoordY(y1);
float x2pos=(float)(int)ScaleCoordX(x2);
float y2pos=(float)(int)ScaleCoordY(y2);
SetState(GS_NODEPTHTEST);
SetCullMode(R_CULL_NONE);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, m_width, m_height, 0.0, -9999.0, 9999.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
Vec3d Start(x1pos, y1pos, 0.0f);
Vec3d End(x2pos, y2pos, 0.0f);
EnableTMU(false);
glBegin(GL_LINES);
glVertex3fv(&Start.x);
glVertex3fv(&End.x);
glEnd();
EnableTMU(true);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void CGLRenderer::DrawLine(const Vec3d & vPos1, const Vec3d & vPos2)
{
SetCullMode(R_CULL_DISABLE);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
glColor4f(1,1,1,1);
glBegin(GL_LINES);
glVertex3fv(&vPos1.x);
glVertex3fv(&vPos2.x);
glEnd();
}
void CGLRenderer::DrawLineColor(const Vec3d & vPos1, const CFColor & vColor1, const Vec3d & vPos2, const CFColor & vColor2)
{
EnableTMU(false);
glBegin(GL_LINES);
glColor4fv(&vColor1.r);
glVertex3fv(&vPos1.x);
glColor4fv(&vColor2.r);
glVertex3fv(&vPos2.x);
glEnd();
EnableTMU(true);
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::ScreenShot(const char *filename)
{
char scname[512];
int i;
FILE *fp;
if (!filename)
{
strcpy(scname,"FarCry00.jpg");
for (i=0 ; i<=99 ; i++)
{
scname[6] = i/10 + '0';
scname[7] = i%10 + '0';
//if (!CXFile::FileExist(scname))
fp=fxopen(scname,"rb");
if (!fp)
break; // file doesn't exist
fclose(fp);
}
if (i==100)
{
iLog->Log("Cannot save ScreenShot: Too many JPG files\n");
return;
}
}
else
strcpy(scname,filename);
iLog->Log("ScreenShot %s\n",scname);
unsigned char *pic=new unsigned char [m_width*m_height*4];
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
byte *src = pic;
byte *dst = new byte[m_width*m_height*4];
for (i=0; i<m_height; i++)
{
int ni0 = (m_height-i-1)*m_width*4;
int ni1 = (i * m_width)*4;
for (int j=0; j<m_width; j++)
{
*(uint *)&dst[ni0+j*4] = *(uint *)&src[ni1+j*4];
}
}
::WriteJPG(dst, m_width, m_height,scname);
//CImage::SaveTga(pic,FORMAT_24_BIT,m_width,m_height,scname,false);
//unsigned char *pic=new unsigned char [m_width*m_height*FORMAT_8_BIT];
//glReadPixels(0, 0, m_width, m_height, GL_ALPHA, GL_UNSIGNED_BYTE, pic);
//CImage::SaveTga(pic,FORMAT_8_BIT,m_width,m_height,scname,false);
delete [] pic;
delete [] dst;
}
int CGLRenderer::ScreenToTexture()
{
// for death effects
unsigned char * pic = new unsigned char [m_width*m_height*3];
glReadPixels(0, 0, m_width, m_height, GL_RGB, GL_UNSIGNED_BYTE, pic);
uint tid;
glGenTextures(1,&tid);
m_TexMan->SetTexture(tid, eTT_Base);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, pic);
delete [] pic;
return tid;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// TEXTURE LOADING
////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
unsigned int CGLRenderer::LoadTexture(const char * _filename,int *tex_type,unsigned int def_tid,bool compresstodisk,bool bWarn)
{
if (def_tid == 0)
def_tid = -1;
ITexPic * pPic = EF_LoadTexture(_filename,FT_NOREMOVE,0, eTT_Base, -1, -1, def_tid);
if (pPic->IsTextureLoaded())
return (pPic->GetTextureID());
return (0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//FONT RENDERING
////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
void CGLRenderer::Print(CXFont *currfont,float x, float y, const char *buf,float xscale,float yscale,float r,float g,float b,float a)
{
x=ScaleCoordX(x);
y=ScaleCoordY(y);
int xsize=(int)(currfont->m_charsize*xscale*(float)(m_width)/800.0f);
int ysize=(int)(currfont->m_charsize*yscale*(float)(m_height)/600.0f);
float r1=r+0.25f;if (r1>1) r1=1;
float g1=g+0.25f;if (g1>1) g1=1;
float b1=b+0.25f;if (b1>1) b1=1;
glBegin(GL_QUADS);
for (size_t i = strlen(buf); i; i--, x += xsize, buf++) //AMD Port
{
float xot = (float)(*buf & 15)*currfont->m_char_inc;
float yot = 1.f-(-(float)(*buf >> 4)*currfont->m_char_inc);
glColor4f (r1,g1,b1,a);
glTexCoord2f(xot, yot);
glVertex2i ((int)(x), (int)(y));
glColor4f (r1,g1,b1,a);
glTexCoord2f(xot+currfont->m_char_inc , yot);
glVertex2i ((int)(x+xsize),(int)(y));
glColor4f (r,g,b,a);
glTexCoord2f(xot+currfont->m_char_inc, yot+currfont->m_char_inc);
glVertex2i ((int)(x+xsize),(int)(y+ysize));
glColor4f (r,g,b,a);
glTexCoord2f(xot, yot+currfont->m_char_inc);
glVertex2i ((int)(x),(int)(y+ysize));
}
glEnd();
}
void CGLRenderer::ResetToDefault()
{
if (m_LogFile)
Logv(SRendItem::m_RecurseLevel, ".... ResetToDefault ....\n");
EF_Scissor(false, 0, 0, 0, 0);
if (SUPPORTS_GL_ATI_fragment_shader)
glDisable(GL_FRAGMENT_SHADER_ATI);
if (SUPPORTS_GL_ARB_fragment_program)
glDisable(GL_FRAGMENT_PROGRAM_ARB);
if (SUPPORTS_GL_NV_register_combiners)
glDisable(GL_REGISTER_COMBINERS_NV);
if (SUPPORTS_GL_NV_texture_shader && m_RP.m_ClipPlaneEnabled != 1)
glDisable(GL_TEXTURE_SHADER_NV);
if (SUPPORTS_GL_NV_vertex_program)
glDisable(GL_VERTEX_PROGRAM_NV);
if (SUPPORTS_GL_ARB_vertex_program)
glDisable(GL_VERTEX_PROGRAM_ARB);
if (m_RP.m_ClipPlaneWasOverrided == 1)
{
m_RP.m_ClipPlaneWasOverrided = 0;
m_RP.m_ClipPlaneEnabled = 1;
}
for (int i=0; i<m_numtmus; i++)
{
if (i >= 4)
break;
EF_SelectTMU(i);
m_eCurColorOp[i] = -1;
m_eCurAlphaOp[i] = -1;
m_eCurColorArg[i] = -1;
m_eCurAlphaArg[i] = -1;
m_fCurRGBScale[i] = -1.0f;
CGLTexMan::m_TUState[i].m_Bind = 0;
SArrayPointer_Texture::m_pLastPointer[i] = NULL;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
// tiago: added
SetLodBias(CRenderer::CV_r_maxtexlod_bias);
if (!i)
{
CGLTexMan::m_TUState[i].m_Target = GL_TEXTURE_2D;
if (m_RP.m_ClipPlaneEnabled == 1 && SUPPORTS_GL_NV_texture_shader)
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, CGLTexMan::m_TUState[i].m_Target);
glEnable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_CUBE_MAP_EXT);
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
glDisable(GL_TEXTURE_RECTANGLE_NV);
EnableTexGen(false);
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, 255, 255);
}
else
{
CGLTexMan::m_TUState[i].m_Target = 0;
//glDisable(GL_TEXTURE_CUBE_MAP_EXT);
glDisable(GL_TEXTURE_2D);
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
glDisable(GL_TEXTURE_RECTANGLE_NV);
if (m_RP.m_ClipPlaneEnabled!=1 || i!=3)
{
EnableTexGen(false);
}
else
if (m_RP.m_ClipPlaneEnabled == 1 && SUPPORTS_GL_NV_texture_shader)
{
if (i == 3)
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_CULL_FRAGMENT_NV);
else
{
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
EnableTexGen(false);
}
}
else
EnableTexGen(false);
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, 255, 255);
}
}
EF_SelectTMU(0);
gRenDev->m_TexMan->m_nCurStages = 1;
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
SetMaterialColor(1,1,1,1);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_NORMALIZE);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glColorMask(1,1,1,1);
glDisable(GL_POINT_SMOOTH);
m_CurState = GS_DEPTHWRITE;
m_RP.m_eCull = (ECull)-1;
SArrayPointer::m_CurEnabled = PFE_POINTER_VERT;
SArrayPointer_Vertex::m_pLastPointer = NULL;
SArrayPointer_Normal::m_pLastPointer = NULL;
SArrayPointer_Color::m_pLastPointer = NULL;
SArrayPointer_SecColor::m_pLastPointer = NULL;
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
m_RP.m_FlagsPerFlush &= ~(RBSI_ALPHAGEN | RBSI_RGBGEN);
m_RP.m_PersFlags &= ~(RBPF_PS1NEEDSET | RBPF_PS1NEEDSET | RBPF_TSNEEDSET | RBPF_VSNEEDSET);
m_RP.m_PersFlags &= ~(RBPF_PS1WASSET | RBPF_PS2WASSET | RBPF_TSWASSET | RBPF_VSWASSET);
m_RP.m_FlagsModificators = 0;
m_RP.m_CurrentVLights = 0;
EF_CommitVLights();
m_RP.m_PersFlags &= ~RBPF_WASWORLDSPACE;
if (m_LogFile && CV_r_log == 3)
Logv(SRendItem::m_RecurseLevel, ".... End ResetToDefault ....\n");
CPShader::m_CurRC = NULL;
CVProgram::m_LastVP = NULL;
CPShader::m_LastVP = NULL;
}
int CGLRenderer::GenerateAlphaGlowTexture(float k)
{
// float k = 6;
const int tex_size = 256;
unsigned char data[tex_size][tex_size];
for(int x=0; x<tex_size; x++)
for(int y=0; y<tex_size; y++)
{
int _x = x-tex_size/2;
int _y = y-tex_size/2;
float val = k*2.f*((float)tex_size/2 - (float)(sqrt(double(_x*_x+_y*_y))));
if(val>255)
val=255;
if(val<0)
val=0;
data[x][y] = (int)(val);
}
return DownLoadToVideoMemory((unsigned char*)data,tex_size,tex_size,eTF_8000,eTF_8000,false,false,FILTER_LINEAR);
}
void CGLRenderer::SetMaterialColor(float r, float g, float b, float a)
{
EF_SetGlobalColor(r, g, b, a);
}
int CGLRenderer::LoadAnimatedTexture(const char * szFileNameFormat,const int nCount)
{
if(nCount<1)
return 0;
for(int t=0; t<m_LoadedAnimatedTextures.Count(); t++)
{
if(strcmp(m_LoadedAnimatedTextures[t]->sName, szFileNameFormat) == 0)
if(m_LoadedAnimatedTextures[t]->nFramesCount == nCount)
{
m_LoadedAnimatedTextures[t]->nRefCounter++;
return t+1;
}
}
{
char szFileName[256];
sprintf(szFileName,szFileNameFormat,0);
iLog->LogToFile("Loading animated texture %s", szFileName);
}
// load new textures
AnimTexInfo * pInfo = new AnimTexInfo();
pInfo->pBindIds = new int[nCount];
memset(pInfo->pBindIds,0,nCount*sizeof(int));
pInfo->nFramesCount = 0;
strncpy(pInfo->sName, szFileNameFormat, sizeof(pInfo->sName));
if (strstr(szFileNameFormat,"%") != 0)
{
// Formatted filename.
for (int i=0; i<nCount; i++)
{
char filename[80]="";
sprintf(filename, szFileNameFormat, i);
pInfo->pBindIds[i] = LoadTexture( filename );
if (!pInfo->pBindIds[i])
break;
pInfo->nFramesCount++;
}
}
else
{
char szFileName[_MAX_PATH];
char szFileFormat[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath( szFileNameFormat,drive,dir,fname,ext );
int numDigits = 0;
int namelen = strlen(fname);
int i = namelen-1;
// Find out number of digits in the end of the filename.
while (i >= 0 && isdigit(fname[i]))
{
numDigits++;
i--;
}
int firstFrame = 0;
if (numDigits > 0)
{
const char *sNum = fname + namelen - numDigits;
firstFrame = atoi(sNum);
fname[namelen-numDigits] = 0;
// Make format string.
sprintf( fname+strlen(fname),"%%.%dd",numDigits );
}
_makepath( szFileFormat,drive,dir,fname,ext );
for (int i=0; i<nCount; i++)
{
sprintf( szFileName,szFileFormat,firstFrame + i );
pInfo->pBindIds[i] = LoadTexture( szFileName );
if (!pInfo->pBindIds[i])
break;
pInfo->nFramesCount++;
}
}
iLog->LogToFilePlus(" (%d)", nCount);
pInfo->nRefCounter=1;
m_LoadedAnimatedTextures.Add(pInfo);
return (int)m_LoadedAnimatedTextures.Count();
}
char * CGLRenderer::GetStatusText(ERendStats type)
{
static char sStatusText[128]="";
int num_used = 0, size_used = 0, num_all = 0, size_all = 0;
int i;
for(i=0; i<m_alloc_info.Count(); i++)
{
if(m_alloc_info[i].busy)
{
num_used++;
size_used+=m_alloc_info[i].bytes_num;
}
num_all++;
size_all+=m_alloc_info[i].bytes_num;
// TextToScreen(1,(float)(10+i*3),"busy=%d bytes=%6d", (int)m_alloc_info[i].busy, (int)m_alloc_info[i].bytes_num);
}
sprintf(sStatusText,"Busy=%d(%.1fmb), All=%d(%.1fmb), BuffSize=%.1fmb",
num_used, float(size_used/1024)/1024, num_all, float(size_all/1024)/1024, float(m_pip_buffer_size/1024)/1024);
return sStatusText;
/*
// calculate resident textures
int tex_count = m_imageList.size();
int resident_count = 0;
for (ImageIt it=m_imageList.begin(); !(it==m_imageList.end()); it++)
{
CImage *ci=(*it);
uint tid = ci->GetTextureId();
if(tid)
{
uchar res=0;
glAreTexturesResident(1,&tid,&res);
resident_count += res;
}
}
int loaded_tests=0;
for(i=0; i<m_texture_registry.Count(); i++)
{
if(m_texture_registry[i].bind_id)
{
loaded_tests++;
}
}
sprintf(buf, "VAR %.3f/%.1f/%.1f %d TEX %3d/%3d REG %3d/%3d",
((float)size_used)/1024,
(float)GetPipWaterLevel()/1024/1024,
(float)m_pip_buffer_size/1024/1024,
m_alloc_info.Count(),
resident_count,tex_count,
loaded_tests,m_texture_registry.Count());
return buf;*/
}
void CGLRenderer::DrawBall(float x, float y, float z, float radius )
{
// glColor3f(1,0,0);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
glPushMatrix();
glTranslatef(x,y,z);
GLUquadricObj * q = gluNewQuadric();
gluSphere( q, radius, 16, 16 );
gluDeleteQuadric(q);
glPopMatrix();
}
void CGLRenderer::DrawBall(const Vec3d & pos, float radius )
{
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
glPushMatrix();
glTranslatef(pos.x,pos.y,pos.z);
GLUquadricObj * q = gluNewQuadric();
gluSphere( q, radius, 16, 16 );
gluDeleteQuadric(q);
glPopMatrix();
}
void CGLRenderer::DrawPoint(float x, float y, float z, float fSize)
{
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
glPointSize(fSize);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
glVertex3f(x, y, z);
glEnd();
glDisable(GL_POINT_SMOOTH);
}
void CGLRenderer::SetClipPlane( int id, float * params )
{
if (params)
EF_SetClipPlane(true, params, false);
else
EF_SetClipPlane(false, NULL, false);
}
struct RGB { uchar r,g,b; };
struct RGBA { uchar r,g,b,a; };
//////////////////////////////////////////////////////////////////////
void CGLRenderer::ClearDepthBuffer()
{
m_bWasCleared = true;
EF_SetState(GS_DEPTHWRITE);
glClear(GL_DEPTH_BUFFER_BIT);
}
void CGLRenderer::ClearColorBuffer(const Vec3d vColor)
{
m_bWasCleared = true;
glClearColor(vColor.x,vColor.y,vColor.z,1.f);
glClear(GL_COLOR_BUFFER_BIT);
}
void CGLRenderer::ReadFrameBuffer(unsigned char * pRGB, int nSizeX, int nSizeY, bool bBackBuffer, bool bRGBA, int nScaledX, int nScaledY)
{
glFinish();
if(bBackBuffer)
glReadBuffer(GL_BACK);
else
glReadBuffer(GL_FRONT);
if (nScaledX <= 0)
{
nScaledX = nSizeX;
nScaledY = nSizeY;
}
glReadPixels(0, 0, nScaledX, nScaledY, bRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, pRGB);
glReadBuffer(GL_BACK);
}
void CGLRenderer::SetFogColor(float * color)
{
m_FS.m_FogColor = CFColor(color);
glFogfv(GL_FOG_COLOR,color);
}
void CGLRenderer::TransformTextureMatrix(float x, float y, float angle, float scale)
{
glMatrixMode(GL_TEXTURE);
glTranslatef(x,y,0);
glTranslatef(0.5,0.5,0);
glRotatef(angle,0,0,1);
glScalef(scale,scale,scale);
glTranslatef(-0.5,-0.5,0);
glMatrixMode(GL_MODELVIEW);
}
void CGLRenderer::ResetTextureMatrix()
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void CGLRenderer::DrawQuad(float dy,float dx, float dz, float x, float y, float z)
{
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f( -1, 0 );
glVertex3f (-dx+x, dy+y,-dz+z);
glTexCoord2f( 0, 0 );
glVertex3f ( dx+x,-dy+y,-dz+z);
glTexCoord2f( 0, 1 );
glVertex3f ( dx+x,-dy+y, dz+z);
glTexCoord2f( -1, 1 );
glVertex3f (-dx+x, dy+y, dz+z);
glEnd();
m_nPolygons+=2;
}
void CGLRenderer::EnableAALines(bool bEnable)
{
if (bEnable)
{
glEnable (GL_LINE_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
}
else
{
glDisable (GL_LINE_SMOOTH);
glDisable (GL_BLEND);
glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
}
}
//////////////////////////////////////////////////////////////////////
void CGLRenderer::Set2DMode(bool enable, int ortox, int ortoy)
{
static int bOldFog = 0;
if(enable)
{
glGetIntegerv(GL_FOG, &bOldFog);
glDisable(GL_FOG);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
//glOrtho(0.0, ortox, ortoy, 0.0, -19999.0, 19999.0);
glOrtho(0.0, ortox, ortoy, 0.0, -1e30, 1e30 );
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
else
{
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
if(bOldFog)
glEnable(GL_FOG);
}
EF_SetCameraInfo();
}
void CGLRenderer::PrintToScreen(float x, float y, float size, const char *buf)
{
PushMatrix();
TranslateMatrix(Vec3d(x,y,0));
EF_SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
SetTexture(iConsole->GetFont()->m_image->GetTextureID());
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
Print(iConsole->GetFont(),0,0,buf,size*0.5f/8, size*1.f/8, 1,1,1,1);
PopMatrix();
}
// ogl to create matrix
void CGLRenderer::MakeMatrix(const Vec3d & pos, const Vec3d & angles,const Vec3d & scale, Matrix44 * mat)
{
// make tran&rot matrix
PushMatrix();
LoadMatrix(0);
TranslateMatrix(pos);
RotateMatrix(angles.z,0,0,1);
RotateMatrix(angles.y,0,1,0);
RotateMatrix(angles.x,1,0,0);
ScaleMatrix(scale.x,scale.y,scale.z);
// GetModelViewMatrix(&(mat->m_values(0,0)));
GetModelViewMatrix((float*)(&mat));
PopMatrix();
}
char* CGLRenderer::GetVertexProfile(bool bSupportedProfile)
{
CGprofile pr;
#ifndef WIN64
// TODO: AMD64 port: find 64-bit CG
pr = cgGLGetLatestProfile(CG_GL_VERTEX);
#else
if ((m_Features & RFT_HW_MASK) == RFT_HW_GFFX)
pr = CG_PROFILE_ARBVP1;
else
pr = CG_PROFILE_VP20;
#endif
if (pr != CG_PROFILE_VP20 && SUPPORTS_GL_ARB_vertex_program)
pr = CG_PROFILE_ARBVP1;
else
pr = CG_PROFILE_VP20;
if (CGLRenderer::CV_gl_vsforce11 && SUPPORTS_GL_NV_vertex_program && !bSupportedProfile)
pr = CG_PROFILE_VP20;
if (pr == CG_PROFILE_VP20)
return "PROFILE_VS_1_1";
else
return "PROFILE_VS_2_0";
}
char* CGLRenderer::GetPixelProfile(bool bSupportedProfile)
{
CGprofile pr;
#ifndef WIN64
// TODO: AMD64 port: find 64-bit CG
pr = cgGLGetLatestProfile(CG_GL_FRAGMENT);
#else
if ((m_Features & RFT_HW_MASK) == RFT_HW_GFFX)
pr = CG_PROFILE_ARBFP1;
else
pr = CG_PROFILE_FP20;
#endif
if (pr != CG_PROFILE_FP20 && SUPPORTS_GL_ARB_fragment_program)
pr = CG_PROFILE_ARBFP1;
else
pr = CG_PROFILE_FP20;
if (CGLRenderer::CV_gl_psforce11 && SUPPORTS_GL_NV_register_combiners && !bSupportedProfile)
pr = CG_PROFILE_FP20;
if (pr == CG_PROFILE_FP20)
return "PROFILE_PS_1_1";
else
return "PROFILE_PS_2_0";
}
void CGLRenderer::EF_PolygonOffset(bool bEnable, float fFactor, float fUnits)
{
if (bEnable)
{
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(fFactor, fUnits);
}
else
{
glDisable(GL_POLYGON_OFFSET_FILL);
}
}
//=========================================================================================
#ifdef CRTDBG_MAP_ALLOC
#pragma pack (push,1)
#define nNoMansLandSize 4
typedef struct MyCrtMemBlockHeader
{
struct MyCrtMemBlockHeader * pBlockHeaderNext;
struct MyCrtMemBlockHeader * pBlockHeaderPrev;
char * szFileName;
int nLine;
size_t nDataSize;
int nBlockUse;
long lRequest;
unsigned char gap[nNoMansLandSize];
/* followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[nNoMansLandSize];
*/
} MyCrtMemBlockHeader;
#pragma pack (pop)
#define pbData(pblock) ((unsigned char *)((MyCrtMemBlockHeader *)pblock + 1))
#define pHdr(pbData) (((MyCrtMemBlockHeader *)pbData)-1)
void crtdebug( const char *s,... )
{
char str[32768];
va_list arg_ptr;
va_start( arg_ptr,s );
vsprintf( str,s,arg_ptr );
va_end( arg_ptr );
FILE *l = fopen( "crtdump.txt","a+t" );
if (l) {
fprintf( l,"%s",str );
fclose( l );
}
}
int crtAllocHook(int nAllocType, void *pvData,
size_t nSize, int nBlockUse, long lRequest,
const unsigned char * szFileName, int nLine )
{
if (nBlockUse == _CRT_BLOCK)
return( TRUE );
static int total_cnt = 0;
static int total_mem = 0;
if (nAllocType == _HOOK_ALLOC)
{
//total_mem += nSize;
//total_cnt++;
//_CrtMemState mem_state;
//_CrtMemCheckpoint( &mem_state );
//total_cnt = mem_state.lCounts[_NORMAL_BLOCK];
//total_mem = mem_state.lTotalCount;
if ((total_cnt&0xF) == 0)
{
//_CrtCheckMemory();
}
total_cnt++;
total_mem += nSize;
//crtdebug( "<CRT> Alloc %d,size=%d,in: %s %d (total size=%d,num=%d)\n",lRequest,nSize,szFileName,nLine,total_mem,total_cnt );
crtdebug( "Malloc: Size=%d, [Total=%d,N=%d] [%s:%d]\n",nSize,total_mem,total_cnt,szFileName,nLine );
}
else
if (nAllocType == _HOOK_FREE)
{
MyCrtMemBlockHeader *pHead;
pHead = pHdr(pvData);
total_cnt--;
total_mem -= pHead->nDataSize;
crtdebug( "Free: Size=%d, [Total=%d,N=%d] [%s:%d]\n",pHead->nDataSize,total_mem,total_cnt,pHead->szFileName,pHead->nLine );
//crtdebug( "<CRT> Free size=%d,in: %s %d (total size=%d,num=%d)\n",pHead->nDataSize,pHead->szFileName,pHead->nLine,total_mem,total_cnt );
//total_mem -= nSize;
//total_cnt--;
}
else
if (nAllocType == _HOOK_REALLOC)
{
MyCrtMemBlockHeader *pHead;
pHead = pHdr(pvData);
//total_cnt++;
total_mem -= pHead->nDataSize;
total_mem += nSize;
crtdebug( "Realloc: Size=%d, [Total=%d,N=%d] [%s:%d]\n",nSize,total_mem,total_cnt,pHead->szFileName,pHead->nLine );
//crtdebug( "<CRT> Free size=%d,in: %s %d (total size=%d,num=%d)\n",pHead->nDataSize,pHead->szFileName,pHead->nLine,total_mem,total_cnt );
//total_mem -= nSize;
//total_cnt--;
}
return TRUE;
}
int crtReportHook(int nRptType, char *szMsg, int *retVal)
{
static int gl_num_asserts = 0;
if (gl_num_asserts != 0) return TRUE;
gl_num_asserts++;
switch (nRptType) {
case _CRT_WARN:
crtdebug( "<CRT WARNING> %s\n",szMsg );
break;
case _CRT_ERROR:
crtdebug( "<CRT ERROR> %s\n",szMsg );
break;
case _CRT_ASSERT:
crtdebug( "<CRT ASSERT> %s\n",szMsg );
break;
}
gl_num_asserts--;
return TRUE;
}
void InitCrt() {
FILE *l = fopen( "crtdump.txt","w" );
if (l) fclose(l);
//_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
//_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
//_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG );
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_WNDW );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_WNDW );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_WNDW );
//_CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_CHECK_CRT_DF|_CRTDBG_LEAK_CHECK_DF|_CRTDBG_DELAY_FREE_MEM_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
//_CrtSetDbgFlag( _CRTDBG_CHECK_CRT_DF|_CRTDBG_LEAK_CHECK_DF/*|_CRTDBG_DELAY_FREE_MEM_DF*/ | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
flags &= ~_CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_CRT_DF;
_CrtSetDbgFlag( flags );
_CrtSetAllocHook ( crtAllocHook );
_CrtSetReportHook( crtReportHook );
void *ptr = malloc(123123);
ptr = realloc(ptr, 654654);
free(ptr);
}
void DoneCrt() {
//_CrtCheckMemory();
//_CrtDumpMemoryLeaks();
}
// Autoinit CRT.
//struct __autoinit_crt { __autoinit_crt() { InitCrt(); }; ~__autoinit_crt() { DoneCrt(); } } __autoinit_crt_var;
#endif // CRTDBG_MAP_ALLOC