5950 lines
168 KiB
C++
5950 lines
168 KiB
C++
/*=============================================================================
|
|
GLTextures.cpp : OpenGL specific texture manager implementation.
|
|
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honitch Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#include "RenderPCH.h"
|
|
#include "GL_Renderer.h"
|
|
#include "GLPBuffer.h"
|
|
#include "I3dengine.h"
|
|
#include "GLCubeMaps.h"
|
|
#include "CryHeaders.h"
|
|
|
|
// tiago: added
|
|
#include "GLCGPShader.h"
|
|
#include "GLCGVProgram.h"
|
|
|
|
TTextureMap CGLTexMan::m_RefTexs;
|
|
|
|
SGLTexUnit CGLTexMan::m_TUState[16];
|
|
|
|
extern int BindSizes[TX_LASTBIND];
|
|
extern int BindFrame[TX_LASTBIND];
|
|
|
|
//===============================================================================
|
|
|
|
/*** NORMALIZATION CUBE MAP CONSTRUCTION ***/
|
|
|
|
/* Given a cube map face index, cube map size, and integer 2D face position,
|
|
* return the cooresponding normalized vector.
|
|
*/
|
|
void CGLTexMan::GetCubeVector(int i, int cubesize, int x, int y, float *vector)
|
|
{
|
|
float s, t, sc, tc, mag;
|
|
|
|
s = ((float)x + 0.5f) / (float)cubesize;
|
|
t = ((float)y + 0.5f) / (float)cubesize;
|
|
sc = s*2.0f - 1.0f;
|
|
tc = t*2.0f - 1.0f;
|
|
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
vector[0] = 1.0f;
|
|
vector[1] = -tc;
|
|
vector[2] = -sc;
|
|
break;
|
|
case 1:
|
|
vector[0] = -1.0f;
|
|
vector[1] = -tc;
|
|
vector[2] = sc;
|
|
break;
|
|
case 2:
|
|
vector[0] = sc;
|
|
vector[1] = 1.0f;
|
|
vector[2] = tc;
|
|
break;
|
|
case 3:
|
|
vector[0] = sc;
|
|
vector[1] = -1.0f;
|
|
vector[2] = -tc;
|
|
break;
|
|
case 4:
|
|
vector[0] = sc;
|
|
vector[1] = -tc;
|
|
vector[2] = 1.0f;
|
|
break;
|
|
case 5:
|
|
vector[0] = -sc;
|
|
vector[1] = -tc;
|
|
vector[2] = -1.0f;
|
|
break;
|
|
}
|
|
|
|
mag = 1.0f/cry_sqrtf(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
|
|
vector[0] *= mag;
|
|
vector[1] *= mag;
|
|
vector[2] *= mag;
|
|
}
|
|
|
|
void CGLTexMan::MakeNormalizeVectorCubeMap(int size, STexPic *tp)
|
|
{
|
|
float vector[3];
|
|
int i, x, y;
|
|
GLubyte *pixels;
|
|
|
|
pixels = new GLubyte [size*size*3];
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
tp->m_Width = size;
|
|
tp->m_Height = size;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
for (y = 0; y < size; y++)
|
|
{
|
|
for (x = 0; x < size; x++)
|
|
{
|
|
GetCubeVector(i, size, x, y, vector);
|
|
pixels[3*(y*size+x) + 0] = (byte)(128.0f + 127.0f*vector[0]);
|
|
pixels[3*(y*size+x) + 1] = (byte)(128.0f + 127.0f*vector[1]);
|
|
pixels[3*(y*size+x) + 2] = (byte)(128.0f + 127.0f*vector[2]);
|
|
}
|
|
}
|
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT+i, 0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
|
|
}
|
|
CGLTexMan::CalcMipsAndSize(tp);
|
|
tp->m_Size *= 6;
|
|
AddToHash(tp->m_Bind, tp);
|
|
tp->Unlink();
|
|
tp->Link(&STexPic::m_Root);
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += tp->m_Size;
|
|
CheckTexLimits(NULL);
|
|
|
|
delete [] pixels;
|
|
}
|
|
|
|
void CGLTexMan::MakePhongLookupTexture(float shininess, STexPic *ti)
|
|
{
|
|
int specular_size = 256;
|
|
int diffuse_size = 256;
|
|
unsigned char * img = new unsigned char[specular_size*diffuse_size*4];
|
|
unsigned char * ip = img;
|
|
for(int j=0; j<specular_size; j++)
|
|
{
|
|
unsigned char a = (unsigned char)(255.99 * pow(double(j/(specular_size-1.0)), (double)shininess));
|
|
for(int i=0; i<diffuse_size; i++)
|
|
{
|
|
byte b = (unsigned char)(255.99 * (i/(diffuse_size-1.0)));
|
|
*ip++ = b;
|
|
*ip++ = b;
|
|
*ip++ = b;
|
|
*ip++ = a;
|
|
}
|
|
}
|
|
ti->m_Size = 0;
|
|
ti->m_nMips = 0;
|
|
int wdt = diffuse_size;
|
|
int hgt = specular_size;
|
|
int mode = GL_RGBA8;
|
|
ti->m_Width = wdt;
|
|
ti->m_Height = hgt;
|
|
ti->m_ETF = eTF_8888;
|
|
CGLTexMan::CalcMipsAndSize(ti);
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
|
|
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);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, mode, diffuse_size, specular_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
|
|
delete [] img;
|
|
}
|
|
|
|
void STexPic::SaveTGA(const char *nam, bool bMips)
|
|
{
|
|
char name[256];
|
|
StripExtension(nam, name);
|
|
|
|
Set();
|
|
CGLRenderer *r = gcpOGL;
|
|
const GLenum cubefaces[6] =
|
|
{
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,
|
|
};
|
|
const char* scubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
|
|
|
|
if (m_eTT == eTT_Cubemap)
|
|
{
|
|
for (int CubeSide=0; CubeSide<6; CubeSide++)
|
|
{
|
|
char nm[256];
|
|
sprintf(nm, "%s_%s.tga", name, scubefaces[CubeSide]);
|
|
int tgt = cubefaces[CubeSide];
|
|
int level = 0;
|
|
int w, h;
|
|
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_HEIGHT, &h);
|
|
if (!w || !h)
|
|
continue;
|
|
|
|
byte *pDst = new byte [w*h*4];
|
|
glGetTexImage(tgt, level, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
WriteTGA(pDst, w, h, nm, 32);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int tgt = GL_TEXTURE_2D;
|
|
int level = 0;
|
|
int w, h;
|
|
char nm[256];
|
|
|
|
if (!bMips)
|
|
{
|
|
sprintf(nm, "%s.tga", name);
|
|
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_HEIGHT, &h);
|
|
if (w && h)
|
|
{
|
|
byte *pDst = new byte [w*h*4];
|
|
|
|
glGetTexImage(tgt, level, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
WriteTGA(pDst, w, h, nm, 32);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<m_nMips; i++)
|
|
{
|
|
sprintf(nm, "%s[%d].tga", name, i);
|
|
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_HEIGHT, &h);
|
|
if (w && h)
|
|
{
|
|
byte *pDst = new byte [w*h*4];
|
|
|
|
glGetTexImage(tgt, i, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
WriteTGA(pDst, w, h, nm, 32);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void STexPic::SaveJPG(const char *nam, bool bMips)
|
|
{
|
|
char name[256];
|
|
StripExtension(nam, name);
|
|
|
|
// Set();
|
|
CGLRenderer *r = gcpOGL;
|
|
static const GLenum cubefaces[6] =
|
|
{
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,
|
|
};
|
|
static char* scubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
|
|
|
|
if (m_eTT == eTT_Cubemap)
|
|
{
|
|
if (!bMips)
|
|
{
|
|
for (int CubeSide=0; CubeSide<6; CubeSide++)
|
|
{
|
|
char nm[256];
|
|
sprintf(nm, "%s_%s.jpg", name, scubefaces[CubeSide]);
|
|
int tgt = cubefaces[CubeSide];
|
|
int level = 0;
|
|
int w, h;
|
|
|
|
glGetTexLevelParameteriv(tgt, level, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, level, GL_TEXTURE_HEIGHT, &h);
|
|
if (!w || !h)
|
|
continue;
|
|
|
|
byte *pDst = new byte [w*h*4];
|
|
glGetTexImage(tgt, level, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
WriteJPG(pDst, w, h, nm);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<m_nMips; i++)
|
|
{
|
|
for (int CubeSide=0; CubeSide<6; CubeSide++)
|
|
{
|
|
char nm[256];
|
|
sprintf(nm, "%s_%s[%d].jpg", name, scubefaces[CubeSide], i);
|
|
int tgt = cubefaces[CubeSide];
|
|
int level = i;
|
|
int w, h;
|
|
|
|
glGetTexLevelParameteriv(tgt, level, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, level, GL_TEXTURE_HEIGHT, &h);
|
|
if (!w || !h)
|
|
continue;
|
|
|
|
byte *pDst = new byte [w*h*4];
|
|
glGetTexImage(tgt, level, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
WriteJPG(pDst, w, h, nm);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int tgt = GL_TEXTURE_2D;
|
|
int level = 0;
|
|
int w, h;
|
|
char nm[256];
|
|
if (!bMips)
|
|
{
|
|
sprintf(nm, "%s.jpg", name);
|
|
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_HEIGHT, &h);
|
|
if (w && h)
|
|
{
|
|
byte *pDst = new byte [w*h*4];
|
|
|
|
glGetTexImage(tgt, level, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
/*for (int i=0; i<w*h; i++)
|
|
{
|
|
pDst[i*4+0] = pDst[i*4+1] = pDst[i*4+2] = pDst[i*4+3];
|
|
}*/
|
|
|
|
WriteJPG(pDst, w, h, nm);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<m_nMips; i++)
|
|
{
|
|
sprintf(nm, "%s[%d].jpg", name, i);
|
|
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_HEIGHT, &h);
|
|
if (w && h)
|
|
{
|
|
byte *pDst = new byte [w*h*4];
|
|
|
|
glGetTexImage(tgt, i, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
|
|
WriteJPG(pDst, w, h, nm);
|
|
delete [] pDst;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
byte *STexPic::GetData32()
|
|
{
|
|
CGLRenderer *r = gcpOGL;
|
|
static const GLenum cubefaces[6] =
|
|
{
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,
|
|
};
|
|
|
|
byte *pDst = NULL;
|
|
if (m_eTT == eTT_Cubemap)
|
|
{
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, m_Bind);
|
|
for (int CubeSide=0; CubeSide<6; CubeSide++)
|
|
{
|
|
int tgt = cubefaces[CubeSide];
|
|
int w, h;
|
|
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_HEIGHT, &h);
|
|
if (!w || !h)
|
|
continue;
|
|
if (!pDst)
|
|
pDst = new byte [w*h*4*6];
|
|
|
|
glGetTexImage(tgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pDst[w*h*4*CubeSide]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, m_Bind);
|
|
int tgt = GL_TEXTURE_2D;
|
|
int w, h;
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, 0, GL_TEXTURE_HEIGHT, &h);
|
|
if (w && h)
|
|
{
|
|
if (!pDst)
|
|
pDst = new byte [w*h*4];
|
|
|
|
glGetTexImage(tgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
|
|
}
|
|
}
|
|
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Bind = 0;
|
|
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target = 0;
|
|
return pDst;
|
|
}
|
|
|
|
void STexPic::ReleaseDriverTexture()
|
|
{
|
|
if (!(m_Flags2 & FT2_WASUNLOADED) && (m_Bind && m_Bind != TX_FIRSTBIND))
|
|
{
|
|
m_Flags2 &= ~FT2_PARTIALLYLOADED;
|
|
if (m_LoadedSize)
|
|
gRenDev->m_TexMan->m_StatsCurTexMem -= m_LoadedSize;
|
|
else
|
|
gRenDev->m_TexMan->m_StatsCurTexMem -= m_Size;
|
|
if (m_Mips[0])
|
|
{
|
|
int nSides = m_eTT == eTT_Cubemap ? 6 : 1;
|
|
for (int nS=0; nS<nSides; nS++)
|
|
{
|
|
for (int i=0; i<m_nMips; i++)
|
|
{
|
|
SMipmap *mp = m_Mips[nS][i];
|
|
if (!mp)
|
|
continue;
|
|
mp->m_bUploaded = false;
|
|
}
|
|
}
|
|
}
|
|
m_LoadedSize = 0;
|
|
Unlink();
|
|
glDeleteTextures(1, &m_Bind);
|
|
}
|
|
}
|
|
|
|
void STexPic::SetWrapping()
|
|
{
|
|
int tgt = m_TargetType;
|
|
if (m_eTT != eTT_Cubemap)
|
|
{
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
if (m_Flags & FT_CLAMP)
|
|
{
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
}
|
|
if (m_Flags2 & FT2_UCLAMP)
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
if (m_Flags2 & FT2_VCLAMP)
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
}
|
|
else
|
|
{
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
}
|
|
}
|
|
|
|
bool STexPic::SetFilter(int nFilter)
|
|
{
|
|
Set();
|
|
switch(nFilter)
|
|
{
|
|
case FILTER_LINEAR:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
break;
|
|
case FILTER_BILINEAR:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
break;
|
|
case FILTER_TRILINEAR:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void STexPic::SetFilter()
|
|
{
|
|
if (!(m_Flags & FT_NOMIPS))
|
|
{
|
|
if (!(m_Flags2 & FT2_FILTER))
|
|
{
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, gcpOGL->m_TexMan->GetMinFilter());
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, gcpOGL->m_TexMan->GetMagFilter());
|
|
if (int anf = gcpOGL->GetAnisotropicLevel())
|
|
glTexParameterf(m_TargetType, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)anf);
|
|
}
|
|
else
|
|
{
|
|
switch(m_Flags2 & FT2_FILTER)
|
|
{
|
|
case FT2_FILTER_NEAREST:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
break;
|
|
|
|
case FT2_FILTER_BILINEAR:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
break;
|
|
|
|
case FT2_FILTER_TRILINEAR:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
break;
|
|
|
|
case FT2_FILTER_ANISOTROPIC:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
if (int anf = gcpOGL->GetAnisotropicLevel())
|
|
glTexParameterf(m_TargetType, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)anf);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(m_Flags2 & FT2_FILTER))
|
|
{
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
}
|
|
else
|
|
{
|
|
switch(m_Flags2 & FT2_FILTER)
|
|
{
|
|
case FT2_FILTER_NEAREST:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
break;
|
|
|
|
case FT2_FILTER_BILINEAR:
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(m_TargetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
STexPic *CGLTexMan::GetByID(int Id)
|
|
{
|
|
if (Id >= TX_FIRSTBIND)
|
|
{
|
|
int n = Id - TX_FIRSTBIND;
|
|
if (n < m_Textures.Num())
|
|
{
|
|
STexPic *tp = m_Textures[n];
|
|
if (tp && tp->m_Bind == Id)
|
|
return tp;
|
|
}
|
|
}
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it != m_RefTexs.end())
|
|
return it->second;
|
|
return NULL;
|
|
}
|
|
|
|
void CGLTexMan::RemoveFromHash(int Id, STexPic *ti)
|
|
{
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it != m_RefTexs.end())
|
|
{
|
|
if (ti)
|
|
assert(ti == it->second);
|
|
m_RefTexs.erase(Id);
|
|
}
|
|
}
|
|
|
|
STexPic *CGLTexMan::AddToHash(int Id, STexPic *ti)
|
|
{
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it == m_RefTexs.end())
|
|
m_RefTexs.insert(TTextureMapItor::value_type(Id, ti));
|
|
else
|
|
assert(ti == it->second);
|
|
return ti;
|
|
}
|
|
|
|
void STexPic::SetClamp(bool bEnable)
|
|
{
|
|
if (m_Bind == TX_FIRSTBIND)
|
|
return;
|
|
|
|
Set();
|
|
|
|
int tgt = m_TargetType;
|
|
|
|
if (bEnable)
|
|
{
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
if (tgt == GL_TEXTURE_CUBE_MAP_EXT)
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
}
|
|
else
|
|
{
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
if (tgt == GL_TEXTURE_CUBE_MAP_EXT)
|
|
glTexParameteri(tgt, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
|
}
|
|
gRenDev->m_TexMan->SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
void CGLTexMan::SetTexture(int Id, ETexType eTT)
|
|
{
|
|
if(Id < 0 || Id >= TX_LASTBIND)
|
|
{
|
|
iLog->Log("Error: CGLTexMan::SetTexture: Texture id is out of range: %d", Id);
|
|
return;
|
|
}
|
|
STexPic *tp = GetByID(Id);
|
|
if (tp)
|
|
{
|
|
tp->Set();
|
|
//tp->SaveJPG("hud.jpg", true);
|
|
return;
|
|
}
|
|
|
|
if (Id < 0)
|
|
return;
|
|
|
|
//PROFILE_FRAME_TOTAL(Texture_Changes);
|
|
|
|
int i = m_CurStage;
|
|
if (CRenderer::CV_r_log == 3 || CRenderer::CV_r_log == 4)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "CGLTexMan::SetTexture: (%d) \"%d\"\n", i, Id);
|
|
if (CGLTexMan::m_TUState[i].m_Bind != Id)
|
|
{
|
|
CGLTexMan::m_TUState[i].m_Bind = Id;
|
|
int tgt;
|
|
switch(eTT)
|
|
{
|
|
case eTT_Cubemap:
|
|
tgt = GL_TEXTURE_CUBE_MAP_EXT;
|
|
break;
|
|
case eTT_Rectangle:
|
|
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
|
|
tgt = GL_TEXTURE_RECTANGLE_NV;
|
|
else
|
|
tgt = GL_TEXTURE_2D;
|
|
break;
|
|
case eTT_3D:
|
|
tgt = GL_TEXTURE_3D_EXT;
|
|
break;
|
|
default:
|
|
tgt = GL_TEXTURE_2D;
|
|
break;
|
|
}
|
|
|
|
if (Id)
|
|
SetTextureTarget(i, tgt);
|
|
else
|
|
ResetTextureTarget(i);
|
|
glBindTexture(tgt, Id);
|
|
}
|
|
}
|
|
|
|
void STexPic::Set(int nTexSlot)
|
|
{
|
|
//PROFILE_FRAME_TOTAL(Texture_Changes);
|
|
|
|
static int sRecursion = 0;
|
|
if (!sRecursion)
|
|
{
|
|
if (CRenderer::CV_r_texbindmode>=2)
|
|
{
|
|
if (CRenderer::CV_r_texbindmode==2 && (m_Flags2 & FT2_WASLOADED) && m_eTT == eTT_Base)
|
|
{
|
|
if (sRecursion)
|
|
return;
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->SetGridTexture(this);
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==3 && (m_Flags2 & FT2_WASLOADED) && m_eTT == eTT_Bumpmap)
|
|
{
|
|
if (sRecursion)
|
|
return;
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->SetGridTexture(this);
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==4 && (m_Flags2 & FT2_WASLOADED) && m_eTT == eTT_Base)
|
|
{
|
|
if (sRecursion)
|
|
return;
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->m_Text_Gray->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==5 && nTexSlot==EFTT_DIFFUSE)
|
|
{
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->m_Text_White->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert(m_Bind >= 0 && m_Bind < TX_LASTBIND);
|
|
if ((m_Flags2 & (FT2_WASUNLOADED | FT2_PARTIALLYLOADED)))
|
|
{
|
|
int Size = m_LoadedSize;
|
|
Restore();
|
|
if (Size != m_LoadedSize)
|
|
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Bind = -1;
|
|
}
|
|
else
|
|
Relink(&STexPic::m_Root);
|
|
int i = gRenDev->m_TexMan->m_CurStage;
|
|
if (CRenderer::CV_r_log == 3 || CRenderer::CV_r_log == 4)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "STexPic::Set(): (%d) \"%s\"\n", i, m_SourceName.c_str());
|
|
if (m_AccessFrame != gRenDev->GetFrameID())
|
|
{
|
|
m_AccessFrame = gRenDev->GetFrameID();
|
|
gRenDev->m_RP.m_PS.m_NumTextures++;
|
|
gRenDev->m_RP.m_PS.m_TexturesSize += m_Size;
|
|
}
|
|
//if (m_Bind != 0x1000)
|
|
// assert (m_Size == BindSizes[m_Bind]);
|
|
|
|
if (CGLTexMan::m_TUState[i].m_Bind != m_Bind)
|
|
{
|
|
CGLTexMan::m_TUState[i].m_Bind = m_Bind;
|
|
int tgt = m_TargetType;
|
|
CGLTexMan::SetTextureTarget(i, tgt);
|
|
glBindTexture(tgt, m_Bind);
|
|
}
|
|
}
|
|
|
|
void WriteTGA8(byte *data8, int width, int height, char *filename);
|
|
|
|
int SShaderTexUnit::mfSetTexture(int nt)
|
|
{
|
|
CGLRenderer *rd = gcpOGL;
|
|
int tgt = GL_TEXTURE_2D;
|
|
|
|
if (nt >= 0)
|
|
rd->EF_SelectTMU(nt);
|
|
|
|
SShaderTexUnit *pSTU = this;
|
|
|
|
int nSetID = -1;
|
|
if (m_TexPic && m_TexPic->m_Bind < EFTT_MAX)
|
|
{
|
|
if (m_TexPic->m_Bind >= EFTT_LIGHTMAP && m_TexPic->m_Bind <= EFTT_OCCLUSION)
|
|
{
|
|
if (m_TexPic->m_Bind == EFTT_LIGHTMAP && rd->m_RP.m_pCurObject->m_nLMId)
|
|
nSetID = rd->m_RP.m_pCurObject->m_nLMId;
|
|
else
|
|
if (m_TexPic->m_Bind == EFTT_LIGHTMAP_DIR && rd->m_RP.m_pCurObject->m_nLMDirId)
|
|
nSetID = rd->m_RP.m_pCurObject->m_nLMDirId;
|
|
else
|
|
if (m_TexPic->m_Bind == EFTT_OCCLUSION && rd->m_RP.m_pCurObject->m_nOcclId)
|
|
nSetID = rd->m_RP.m_pCurObject->m_nOcclId;
|
|
}
|
|
else
|
|
if (nSetID < 0)
|
|
{
|
|
if (!rd->m_RP.m_pShaderResources || !rd->m_RP.m_pShaderResources->m_Textures[m_TexPic->m_Bind])
|
|
iLog->Log("WARNING: SShaderTexUnit::mfSetTexture: Missed template texture '%s' for shader '%s'\n", gRenDev->m_cEF.mfTemplateTexIdToName(m_TexPic->m_Bind), rd->m_RP.m_pShader->GetName());
|
|
else
|
|
{
|
|
pSTU = &rd->m_RP.m_pShaderResources->m_Textures[m_TexPic->m_Bind]->m_TU;
|
|
rd->m_RP.m_pShaderResources->m_Textures[m_TexPic->m_Bind]->Update(nt);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pSTU->m_AnimInfo)
|
|
pSTU->mfUpdate();
|
|
|
|
if (pSTU->m_TexPic)
|
|
{
|
|
tgt = pSTU->m_TexPic->m_TargetType;
|
|
if (nSetID > 0)
|
|
{
|
|
rd->m_TexMan->SetTexture(nSetID, eTT_Base);
|
|
tgt = GL_TEXTURE_2D;
|
|
}
|
|
else
|
|
{
|
|
int bind = pSTU->m_TexPic->m_Bind;
|
|
if (bind >= TX_FIRSTBIND)
|
|
{
|
|
pSTU->m_TexPic->Set();
|
|
//pSTU->m_TexPic->SaveJPG("Bug.jpg", true);
|
|
}
|
|
else
|
|
{
|
|
switch (bind)
|
|
{
|
|
case TO_FROMRE0:
|
|
case TO_FROMRE1:
|
|
case TO_FROMRE2:
|
|
case TO_FROMRE3:
|
|
case TO_FROMRE4:
|
|
case TO_FROMRE5:
|
|
case TO_FROMRE6:
|
|
case TO_FROMRE7:
|
|
{
|
|
if (rd->m_RP.m_pRE)
|
|
bind = rd->m_RP.m_pRE->m_CustomTexBind[bind-TO_FROMRE0];
|
|
else
|
|
bind = rd->m_RP.m_RECustomTexBind[bind-TO_FROMRE0];
|
|
if (bind < 0)
|
|
return 0;
|
|
rd->SetTexture(bind, pSTU->m_TexPic->m_eTT);
|
|
/*{
|
|
int width;
|
|
int height;
|
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
|
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
|
|
byte *pic = new byte [width * height];
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pic);
|
|
char buff[128];
|
|
sprintf(buff, "ShadowMap.tga");
|
|
WriteTGA8(pic,width,height,buff);
|
|
delete [] pic;
|
|
}*/
|
|
}
|
|
break;
|
|
|
|
case TO_FROMOBJ:
|
|
{
|
|
if (rd->m_RP.m_pCurObject)
|
|
bind = rd->m_RP.m_pCurObject->m_NumCM;
|
|
if (bind <= 0)
|
|
return 0;
|
|
rd->SetTexture(bind, eTT_Base);
|
|
}
|
|
break;
|
|
|
|
case TO_FROMLIGHT:
|
|
{
|
|
bool bRes = false;
|
|
if (rd->m_RP.m_nCurLight < rd->m_RP.m_DLights[SRendItem::m_RecurseLevel].Num())
|
|
{
|
|
CDLight *dl = rd->m_RP.m_pCurLight;
|
|
if (dl && dl->m_pLightImage!=0)
|
|
{
|
|
bRes = true;
|
|
STexPic *tp = (STexPic *)((ITexPic*)dl->m_pLightImage);
|
|
//dl->m_NumCM = 0;
|
|
if (dl->m_NumCM >= 0)
|
|
tp = gRenDev->m_TexMan->m_CustomCMaps[dl->m_NumCM].m_Tex;
|
|
else
|
|
if (dl->m_fAnimSpeed)
|
|
{
|
|
int n = 0;
|
|
STexPic *t = tp;
|
|
while (t)
|
|
{
|
|
t = t->m_NextTxt;
|
|
n++;
|
|
}
|
|
if (n > 1)
|
|
{
|
|
int m = (int)(gRenDev->m_RP.m_RealTime / dl->m_fAnimSpeed) % n;
|
|
for (int i=0; i<m; i++)
|
|
{
|
|
tp = tp->m_NextTxt;
|
|
}
|
|
}
|
|
}
|
|
if(tp)
|
|
{
|
|
tp->Set();
|
|
//tp->SaveJPG("CubeProj.jpg", true);
|
|
}
|
|
else
|
|
assert (tp);
|
|
//tp->SaveJPG("CubeLight");
|
|
}
|
|
}
|
|
if (!bRes)
|
|
iLog->Log("Warning: Couldn't set projected texture for %d light source (Shader: '%s')\n", rd->m_RP.m_nCurLight, rd->m_RP.m_pShader->m_Name.c_str());
|
|
}
|
|
break;
|
|
|
|
case TO_ENVIRONMENT_CUBE_MAP:
|
|
{
|
|
SEnvTexture *cm = NULL;
|
|
cm = gRenDev->m_cEF.mfFindSuitableEnvCMap(rd->m_RP.m_pCurObject->GetTranslation(), true, 0, 0);
|
|
if (cm)
|
|
cm->m_Tex->Set();
|
|
else
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case TO_ENVIRONMENT_LIGHTCUBE_MAP:
|
|
{
|
|
SEnvTexture *cm = NULL;
|
|
cm = gRenDev->m_cEF.mfFindSuitableEnvLCMap(rd->m_RP.m_pCurObject->GetTranslation(), true, 0, 0);
|
|
if (cm)
|
|
cm->m_Tex->Set();
|
|
else
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case TO_ENVIRONMENT_TEX:
|
|
{
|
|
SEnvTexture *cm = NULL;
|
|
CCamera cam = rd->GetCamera();
|
|
Vec3d Angs = cam.GetAngles();
|
|
Vec3d Pos = cam.GetPos();
|
|
bool bReflect = false;
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & (EF3_CLIPPLANE_FRONT | EF3_REFLECTION)))
|
|
bReflect = true;
|
|
cm = gRenDev->m_cEF.mfFindSuitableEnvTex(Pos, Angs, true, 0, false, gRenDev->m_RP.m_pShader, gRenDev->m_RP.m_pShaderResources, gRenDev->m_RP.m_pCurObject, bReflect, gRenDev->m_RP.m_pRE);
|
|
if (cm)
|
|
cm->m_Tex->Set();
|
|
else
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if (bind >= TO_CUSTOM_CUBE_MAP_FIRST && bind <= TO_CUSTOM_CUBE_MAP_LAST)
|
|
{
|
|
SEnvTexture *cm = &gRenDev->m_TexMan->m_CustomCMaps[bind-TO_CUSTOM_CUBE_MAP_FIRST];
|
|
if (!cm->m_bReady)
|
|
{
|
|
iLog->Log("Warning: Custom CubeMap %d doesn't ready\n", bind-TO_CUSTOM_CUBE_MAP_FIRST);
|
|
return 0;
|
|
}
|
|
cm->m_Tex->Set();
|
|
}
|
|
else
|
|
if (bind >= TO_CUSTOM_TEXTURE_FIRST && bind <= TO_CUSTOM_TEXTURE_LAST)
|
|
{
|
|
SEnvTexture *cm = &gRenDev->m_TexMan->m_CustomTextures[bind-TO_CUSTOM_TEXTURE_FIRST];
|
|
if (!cm->m_bReady)
|
|
{
|
|
iLog->Log("Warning: Custom Texture %d doesn't ready\n", bind-TO_CUSTOM_TEXTURE_FIRST);
|
|
return 0;
|
|
}
|
|
cm->m_Tex->Set();
|
|
}
|
|
else
|
|
if (pSTU->m_TexPic->m_TargetType)
|
|
pSTU->m_TexPic->Set();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pSTU->m_fTexFilterLodBias != CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_fTexFilterLodBias)
|
|
{
|
|
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_fTexFilterLodBias = pSTU->m_fTexFilterLodBias;
|
|
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, pSTU->m_fTexFilterLodBias);
|
|
}
|
|
}
|
|
else
|
|
if (CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target)
|
|
{
|
|
glDisable(CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target);
|
|
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Target = 0;
|
|
CGLTexMan::m_TUState[gRenDev->m_TexMan->m_CurStage].m_Bind = 0;
|
|
}
|
|
|
|
if (m_GTC)
|
|
{
|
|
if (!m_GTC->mfSet(true))
|
|
return 0;
|
|
if (m_GTC->m_bDependsOnObject)
|
|
{
|
|
rd->m_RP.m_pGTC[nt] = m_GTC;
|
|
rd->m_RP.m_FrameGTC = rd->m_RP.m_Frame;
|
|
}
|
|
else
|
|
rd->m_RP.m_pGTC[nt] = NULL;
|
|
}
|
|
else
|
|
rd->m_RP.m_pGTC[nt] = NULL;
|
|
|
|
if (m_eColorOp != eCO_NOSET)
|
|
{
|
|
rd->m_RP.m_TexStages[nt].m_CO = m_eColorOp;
|
|
rd->m_RP.m_TexStages[nt].m_AO = m_eAlphaOp;
|
|
rd->m_RP.m_TexStages[nt].m_CA = m_eColorArg;
|
|
rd->m_RP.m_TexStages[nt].m_AA = m_eAlphaArg;
|
|
}
|
|
|
|
return tgt;
|
|
}
|
|
|
|
bool SShaderPass::mfSetTextures()
|
|
{
|
|
int i;
|
|
for (i=0; i<m_TUnits.Num() && i<gcpOGL->m_MaxActiveTexturesARB_VP; i++)
|
|
{
|
|
SShaderTexUnit *tl = &m_TUnits[i];
|
|
tl->mfSetTexture(i);
|
|
}
|
|
CGLTexMan::BindNULL(i);
|
|
return true;
|
|
}
|
|
|
|
void SShaderPass::mfResetTextures()
|
|
{
|
|
int i;
|
|
for (i=0; i<m_TUnits.Num(); i++)
|
|
{
|
|
SShaderTexUnit *tl = &m_TUnits[i];
|
|
if (tl->m_GTC)
|
|
{
|
|
gcpOGL->EF_SelectTMU(i);
|
|
tl->m_GTC->mfSet(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
CGLTexMan::~CGLTexMan()
|
|
{
|
|
if (m_PBuffer_256)
|
|
{
|
|
delete m_PBuffer_256;
|
|
m_PBuffer_256 = NULL;
|
|
}
|
|
if (m_EnvPBuffer)
|
|
{
|
|
delete m_EnvPBuffer;
|
|
m_EnvPBuffer = NULL;
|
|
}
|
|
for (int i=0; i<m_BufRegions.Num(); i++)
|
|
{
|
|
SBufRegion *br = &m_BufRegions[i];
|
|
if (br->m_BRHandle)
|
|
{
|
|
wglDeleteBufferRegionARB(br->m_BRHandle);
|
|
br->m_BRHandle = 0;
|
|
}
|
|
}
|
|
m_BufRegions.Free();
|
|
}
|
|
|
|
|
|
STexPic *CGLTexMan::CreateTexture()
|
|
{
|
|
#ifdef DEBUGALLOC
|
|
#undef new
|
|
#endif
|
|
return new STexPic;
|
|
#ifdef DEBUGALLOC
|
|
#define new DEBUG_CLIENTBLOCK
|
|
#endif
|
|
}
|
|
|
|
bool CGLTexMan::SetFilter(char *tex)
|
|
{
|
|
int i;
|
|
struct textype
|
|
{
|
|
char *name;
|
|
uint typemin;
|
|
uint typemag;
|
|
};
|
|
|
|
static textype tt[] =
|
|
{
|
|
{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
|
|
{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
|
|
{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
|
|
{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
|
|
{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
|
|
{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
|
|
};
|
|
|
|
strcpy(m_CurTexFilter, tex);
|
|
m_CurAnisotropic = CLAMP(CRenderer::CV_r_texture_anisotropic_level, 1, gcpOGL->m_MaxAnisotropicLevel);
|
|
CRenderer::CV_r_texture_anisotropic_level = m_CurAnisotropic;
|
|
if ((gRenDev->GetFeatures() & RFT_ALLOWANISOTROPIC) && m_CurAnisotropic > 1)
|
|
{
|
|
CGLRenderer::CV_gl_texturefilter->Set("GL_LINEAR_MIPMAP_LINEAR");
|
|
tex = CGLRenderer::CV_gl_texturefilter->GetString();
|
|
}
|
|
|
|
for (i=0; i<6; i++)
|
|
{
|
|
if ( !stricmp(tex, tt[i].name) )
|
|
{
|
|
m_MinFilter = tt[i].typemin;
|
|
m_MagFilter = tt[i].typemag;
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
if (m_Textures[i] && m_Textures[i]->m_bBusy && !(m_Textures[i]->m_Flags & FT_NOMIPS))
|
|
{
|
|
gRenDev->SetTexture(m_Textures[i]->m_Bind);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GetMinFilter());
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GetMagFilter());
|
|
if (int anf = gcpOGL->GetAnisotropicLevel())
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)anf);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
iLog->Log("Warning: Bad texture filter name <%s>\n", tex);
|
|
return false;
|
|
}
|
|
|
|
void CGLTexMan::CalcMipsAndSize(STexPic *ti)
|
|
{
|
|
ti->m_nMips = 0;
|
|
ti->m_Size = 0;
|
|
int wdt = ti->m_Width;
|
|
int hgt = ti->m_Height;
|
|
int depth = ti->m_Depth;
|
|
int mode = GetTexDstFormat(ti->m_ETF);
|
|
while (wdt || hgt || depth)
|
|
{
|
|
if (!wdt)
|
|
wdt = 1;
|
|
if (!hgt)
|
|
hgt = 1;
|
|
if (!depth)
|
|
depth = 1;
|
|
ti->m_nMips++;
|
|
ti->m_Size += CGLTexMan::TexSize(wdt,hgt,depth,mode);
|
|
if (ti->m_Flags & FT_NOMIPS)
|
|
break;
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
depth >>= 1;
|
|
}
|
|
}
|
|
|
|
ETEX_Format CGLTexMan::GetTexFormat(int GLFormat)
|
|
{
|
|
switch(GLFormat)
|
|
{
|
|
case GL_COLOR_INDEX8_EXT:
|
|
return eTF_Index;
|
|
case GL_RGB8:
|
|
return eTF_0888;
|
|
case GL_RGBA8:
|
|
return eTF_8888;
|
|
case GL_RGBA4:
|
|
return eTF_4444;
|
|
case GL_RGB5:
|
|
return eTF_0555;
|
|
case GL_ALPHA:
|
|
return eTF_8000;
|
|
case GL_LUMINANCE_ALPHA:
|
|
return eTF_0088;
|
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
return eTF_DXT1;
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
return eTF_DXT3;
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
return eTF_DXT5;
|
|
case GL_SIGNED_HILO16_NV:
|
|
return eTF_SIGNED_HILO16;
|
|
case GL_SIGNED_HILO_NV:
|
|
return eTF_SIGNED_HILO8;
|
|
case GL_SIGNED_RGB8_NV:
|
|
return eTF_SIGNED_RGB8;
|
|
case GL_DSDT_MAG_NV:
|
|
return eTF_DSDT_MAG;
|
|
case GL_DSDT_NV:
|
|
return eTF_DSDT;
|
|
case GL_HILO_NV:
|
|
return eTF_V8U8;
|
|
case GL_HILO16_NV:
|
|
return eTF_V16U16;
|
|
case GL_ALPHA8:
|
|
return eTF_8000;
|
|
default:
|
|
assert(0);
|
|
}
|
|
return eTF_Unknown;
|
|
}
|
|
|
|
int CGLTexMan::GetTexDstFormat(ETEX_Format eTF)
|
|
{
|
|
switch (eTF)
|
|
{
|
|
case eTF_Index:
|
|
return GL_COLOR_INDEX8_EXT;
|
|
case eTF_0888:
|
|
return GL_RGB8;
|
|
case eTF_8888:
|
|
return GL_RGBA8;
|
|
case eTF_4444:
|
|
return GL_RGBA4;
|
|
case eTF_0555:
|
|
return GL_RGB5;
|
|
case eTF_8000:
|
|
return GL_ALPHA;
|
|
case eTF_0088:
|
|
return GL_LUMINANCE_ALPHA;
|
|
case eTF_DXT1:
|
|
return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
case eTF_DXT3:
|
|
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
case eTF_DXT5:
|
|
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
|
case eTF_SIGNED_HILO16:
|
|
return GL_SIGNED_HILO16_NV;
|
|
case eTF_SIGNED_HILO8:
|
|
return GL_SIGNED_HILO_NV;
|
|
case eTF_SIGNED_RGB8:
|
|
return GL_SIGNED_RGB8_NV;
|
|
case eTF_RGB8:
|
|
return GL_RGB8;
|
|
case eTF_DSDT_MAG:
|
|
return GL_DSDT_MAG_NV;
|
|
case eTF_DSDT:
|
|
return GL_DSDT_NV;
|
|
case eTF_V8U8:
|
|
return GL_HILO_NV;
|
|
case eTF_V16U16:
|
|
return GL_HILO16_NV;
|
|
default:
|
|
assert(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CGLTexMan::GetTexSrcFormat(ETEX_Format eTF)
|
|
{
|
|
switch (eTF)
|
|
{
|
|
case eTF_Index:
|
|
return GL_COLOR_INDEX;
|
|
case eTF_0888:
|
|
return GL_RGB;
|
|
case eTF_0555:
|
|
return GL_RGB;
|
|
case eTF_8888:
|
|
return GL_RGBA;
|
|
case eTF_4444:
|
|
return GL_RGBA;
|
|
case eTF_0088:
|
|
return GL_LUMINANCE_ALPHA;
|
|
case eTF_8000:
|
|
return GL_ALPHA;
|
|
case eTF_DXT1:
|
|
return GL_RGB;
|
|
case eTF_DXT3:
|
|
return GL_RGBA;
|
|
case eTF_DXT5:
|
|
return GL_RGBA;
|
|
case eTF_SIGNED_HILO16:
|
|
return GL_SIGNED_HILO16_NV;
|
|
case eTF_SIGNED_HILO8:
|
|
return GL_SIGNED_HILO_NV;
|
|
case eTF_SIGNED_RGB8:
|
|
return GL_SIGNED_RGB8_NV;
|
|
case eTF_RGB8:
|
|
return GL_RGB;
|
|
case eTF_DSDT_MAG:
|
|
return GL_DSDT_MAG_NV;
|
|
case eTF_DSDT:
|
|
return GL_DSDT_NV;
|
|
default:
|
|
assert(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int STexPic::DstFormatFromTexFormat(ETEX_Format eTF)
|
|
{
|
|
return CGLTexMan::GetTexDstFormat(eTF);
|
|
}
|
|
int STexPic::TexSize(int Width, int Height, int DstFormat)
|
|
{
|
|
return CGLTexMan::TexSize(Width, Height, 1, DstFormat);
|
|
}
|
|
|
|
int CGLTexMan::TexSize(int wdt, int hgt, int depth, int mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case GL_RGB8:
|
|
case GL_RGB:
|
|
case 3:
|
|
case GL_BGR_EXT:
|
|
return wdt * hgt * depth * 3;
|
|
|
|
case GL_RGBA8:
|
|
case GL_RGBA:
|
|
case GL_BGRA_EXT:
|
|
case 4:
|
|
return wdt * hgt * depth * 4;
|
|
|
|
case GL_RGBA4:
|
|
case GL_RGB5:
|
|
return wdt * hgt * depth * 2;
|
|
|
|
case GL_COMPRESSED_ALPHA_ARB:
|
|
return wdt * hgt * depth;
|
|
|
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
{
|
|
int blockSize = (mode == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || mode == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
|
|
return ((wdt+3)/4)*((hgt+3)/4)*blockSize;
|
|
}
|
|
|
|
case 0x83a0:
|
|
{
|
|
int blockSize = 8;
|
|
return ((wdt+3)/4)*((hgt+3)/4)*blockSize;
|
|
}
|
|
|
|
case GL_COLOR_INDEX8_EXT:
|
|
return wdt * hgt * depth;
|
|
|
|
case GL_LUMINANCE_ALPHA:
|
|
return wdt * hgt * depth * 2;
|
|
|
|
case GL_DSDT_MAG_NV:
|
|
return wdt * hgt * depth * 3;
|
|
|
|
case GL_DSDT_NV:
|
|
return wdt * hgt * depth * 2;
|
|
|
|
case GL_ALPHA:
|
|
case GL_ALPHA8:
|
|
return wdt * hgt * depth;
|
|
|
|
case GL_DEPTH_COMPONENT24_SGIX:
|
|
return wdt * hgt * 3;
|
|
|
|
case GL_DEPTH_COMPONENT16_SGIX:
|
|
return wdt * hgt * 2;
|
|
|
|
case GL_LUMINANCE8:
|
|
return wdt * hgt * depth;
|
|
|
|
case GL_DEPTH_COMPONENT:
|
|
return wdt * hgt * depth;
|
|
|
|
case GL_HILO16_NV:
|
|
case GL_SIGNED_HILO16_NV:
|
|
return wdt * hgt * depth * 4;
|
|
|
|
case GL_HILO_NV:
|
|
case GL_SIGNED_HILO_NV:
|
|
return wdt * hgt * depth * 2;
|
|
|
|
default:
|
|
assert(0);
|
|
break;
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if DO_ASM
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4731) // frame pointer register 'ebp' modified by inline assembly code
|
|
|
|
_inline byte *ASM_BuildMipLine(byte *src1, byte *dst1, int wd, int wdt)
|
|
{
|
|
__asm
|
|
{
|
|
push ebp
|
|
mov edi, dst1
|
|
mov esi, src1
|
|
mov ebx, wd
|
|
mov ebp, wdt
|
|
|
|
xor eax, eax
|
|
xor ecx, ecx
|
|
xor edx, edx
|
|
jmp ll
|
|
align 16
|
|
ll:
|
|
mov al, [esi]
|
|
mov dl, [esi+4]
|
|
mov cl, [esi+ebx]
|
|
add eax, edx
|
|
add eax, ecx
|
|
mov dl, [esi+ebx+4]
|
|
mov cl, [esi+ebx+1]
|
|
add eax, edx
|
|
shr eax, 2
|
|
mov dl, [esi+5]
|
|
mov [edi], al
|
|
mov al, [esi+1]
|
|
add eax, edx
|
|
add eax, ecx
|
|
mov dl, [esi+ebx+5]
|
|
mov cl, [esi+ebx+2]
|
|
add eax, edx
|
|
shr eax, 2
|
|
mov dl, [esi+6]
|
|
mov [edi+1], al
|
|
mov al, [esi+2]
|
|
add eax, edx
|
|
add eax, ecx
|
|
mov dl, [esi+ebx+6]
|
|
mov cl, [esi+ebx+3]
|
|
add eax, edx
|
|
shr eax, 2
|
|
mov dl, [esi+7]
|
|
mov [edi+2], al
|
|
mov al, [esi+3]
|
|
add eax, edx
|
|
add eax, ecx
|
|
mov dl, [esi+ebx+7]
|
|
add edi, 4
|
|
add eax, edx
|
|
add esi, 8
|
|
shr eax, 2
|
|
dec ebp
|
|
mov [edi-1], al
|
|
jne ll
|
|
pop ebp
|
|
mov eax, edi
|
|
}
|
|
//return dst1;
|
|
}
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
|
|
|
_inline uint filter3x3(uint* data, int x, int y, int dx, int dy)
|
|
{
|
|
int r, g, b, a;
|
|
|
|
static int filter[3][3] =
|
|
{
|
|
{0, 1, 0},
|
|
{1, 2, 1},
|
|
{0, 1, 0}
|
|
};
|
|
|
|
r = b = g = a = 0;
|
|
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
for (int j=0; j<3; j++)
|
|
{
|
|
uint col = data[((y + dy + i - 1) % dy) * dx + ((x + dx + j - 1) % dx)];
|
|
r += ( col & 0xff) << filter[i][j];
|
|
g += ((col >> 8) & 0xff) << filter[i][j];
|
|
b += ((col >> 16) & 0xff) << filter[i][j];
|
|
a += ((col >> 24) & 0xff) << filter[i][j];
|
|
}
|
|
}
|
|
|
|
r >>= 4; g >>= 4; b >>= 4; a >>= 4;
|
|
|
|
return r + (g<<8) + (b<<16) + (a<<24);
|
|
}
|
|
|
|
void CGLTexMan::GenerateMips_SW(GLenum tgt, byte* src, int wdt, int hgt, int mode, STexPic *ti)
|
|
{
|
|
int wd;
|
|
int i, j;
|
|
byte *src1, *dst1;
|
|
int num;
|
|
|
|
glTexImage2D(tgt, 0, mode, wdt, hgt, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, src);
|
|
num = 1;
|
|
while (wdt!=1 && hgt!=1)
|
|
{
|
|
wd = wdt<<2;
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
if (wdt < 1)
|
|
wdt = 1;
|
|
if (hgt < 1)
|
|
hgt = 1;
|
|
if (CRenderer::CV_r_texsimplemips || (ti->m_Flags2 & FT2_FORCEMIPS2X2))
|
|
{
|
|
src1 = dst1 = src;
|
|
for (i=0; i<hgt; i++)
|
|
{
|
|
#if !DO_ASM
|
|
byte *src2 = src1;
|
|
for (j=0; j<wdt; j++)
|
|
{
|
|
dst1[0] = (src2[0]+src2[4]+src2[wd]+src2[wd+4])>>2;
|
|
dst1[1] = (src2[1]+src2[5]+src2[wd+1]+src2[wd+5])>>2;
|
|
dst1[2] = (src2[2]+src2[6]+src2[wd+2]+src1[wd+6])>>2;
|
|
dst1[3] = (src2[3]+src2[7]+src2[wd+3]+src2[wd+7])>>2;
|
|
dst1 += 4;
|
|
src2 += 8;
|
|
}
|
|
#else
|
|
dst1 = ASM_BuildMipLine(src1, dst1, wd, wdt);
|
|
#endif
|
|
src1 += wd<<1;
|
|
}
|
|
glTexImage2D(tgt, num, mode, wdt, hgt, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, src);
|
|
}
|
|
else
|
|
{
|
|
uint *ds = new uint[wdt*hgt];
|
|
memset(ds, 0, wdt*hgt*4);
|
|
uint *ds1 = ds;
|
|
for (i=0; i<hgt; i++)
|
|
{
|
|
for (j=0; j<wdt; j++)
|
|
{
|
|
*ds++ = filter3x3((uint *)src, j<<1, i<<1, wdt<<1, hgt<<1);
|
|
}
|
|
}
|
|
glTexImage2D(tgt, num, mode, wdt, hgt, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, ds1);
|
|
memcpy(src, ds1, wdt*hgt*4);
|
|
delete [] ds1;
|
|
}
|
|
num++;
|
|
}
|
|
}
|
|
|
|
static inline bool IsDXTFormat(int format)
|
|
{
|
|
if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
|
|
format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
|
|
format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
|
|
format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void CGLTexMan::BuildMips(GLenum tgt, byte* src, int wdt, int hgt, int depth, STexPic *ti, int srcFormat, int dstFormat, int blockSize, int DXTSize, int nMips)
|
|
{
|
|
int offset = 0;
|
|
ti->m_nMips = 0;
|
|
if (nMips)
|
|
{
|
|
signed char *data = (signed char *)src;
|
|
int w = wdt;
|
|
int h = hgt;
|
|
if (dstFormat == GL_DSDT_MAG_NV)
|
|
{
|
|
for (int l=0; l<nMips; l++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
float *fd = new float[w*h*3];
|
|
for (int i=0; i<w*h; i++)
|
|
{
|
|
fd[i*3+0] = data[i*4+0]/127.0f;
|
|
fd[i*3+1] = data[i*4+1]/127.0f;
|
|
fd[i*3+2] = data[i*4+2]/127.0f;
|
|
}
|
|
glTexImage2D(GL_TEXTURE_2D, l, GL_DSDT_MAG_NV, w, h, 0, GL_DSDT_MAG_NV, GL_FLOAT, fd);
|
|
delete [] fd;
|
|
data += w*h*4;
|
|
ti->m_Size += w*h*3;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
else
|
|
if (dstFormat == GL_COLOR_INDEX8_EXT && srcFormat == GL_COLOR_INDEX)
|
|
{
|
|
for (int l=0; l<nMips; l++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
glTexImage2D(tgt, l, dstFormat, w, h, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data );
|
|
data += w*h;
|
|
ti->m_Size += w*h;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dstFormat == GL_SIGNED_HILO_NV || dstFormat == GL_SIGNED_HILO16_NV || dstFormat == GL_HILO_NV)
|
|
{
|
|
for (int l=0; l<nMips; l++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
glTexImage2D(tgt, l, dstFormat, w, h, 0, GL_HILO_NV, GL_BYTE, data);
|
|
data += w*h*2;
|
|
ti->m_Size += w*h*2;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
else
|
|
if (ti->m_eTT == eTT_DSDTBump)
|
|
{
|
|
srcFormat = GL_RGBA;
|
|
for (int l=0; l<nMips; l++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
/*for (int i=0; i<w*h; i++)
|
|
{
|
|
Exchange(data[i*4+2], data[i*4+0]);
|
|
}*/
|
|
glTexImage2D(tgt, l, dstFormat, w, h, 0, srcFormat, GL_BYTE, data);
|
|
data += w*h*4;
|
|
ti->m_Size += w*h*3;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
else
|
|
if (IsDXTFormat(dstFormat) && dstFormat == srcFormat)
|
|
{
|
|
int l = 0;
|
|
int size;
|
|
while (w>0 || h>0)
|
|
{
|
|
if (offset >= DXTSize)
|
|
break;
|
|
ti->m_nMips++;
|
|
if (w == 0)
|
|
w = 1;
|
|
if (h == 0)
|
|
h = 1;
|
|
|
|
size = ((w+3)/4)*((h+3)/4)*blockSize;
|
|
|
|
ti->m_Size += size;
|
|
glCompressedTexImage2DARB(tgt, l, dstFormat, w, h, 0, size, src + offset);
|
|
|
|
l++;
|
|
offset += size;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
if (l == 1)
|
|
ti->m_Flags |= FT_NOMIPS;
|
|
else
|
|
{
|
|
if (w <= 2 && h <= 2)
|
|
{
|
|
offset -= size;
|
|
while (w>0 || h>0)
|
|
{
|
|
ti->m_nMips++;
|
|
if (w == 0)
|
|
w = 1;
|
|
if (h == 0)
|
|
h = 1;
|
|
|
|
ti->m_Size += size;
|
|
glCompressedTexImage2DARB(tgt, l, dstFormat, w, h, 0, size, src + offset);
|
|
|
|
l++;
|
|
offset += size;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
assert (!w && !h);
|
|
if(w || h)
|
|
Warning(0, ti->GetName(), "CGLTexMan::BuildMips_DXT: Texture has no requested mips: %s", ti->GetName());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int l=0; l<nMips; l++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
glTexImage2D(tgt, l, dstFormat, w, h, 0, srcFormat, GL_UNSIGNED_BYTE, data);
|
|
data += TexSize(w, h, depth, srcFormat);
|
|
ti->m_Size += TexSize(w, h, depth, dstFormat);
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_texhwmipsgeneration && SUPPORTS_GL_SGIS_generate_mipmap)
|
|
{
|
|
if (tgt >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT && tgt <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT)
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
else
|
|
glTexParameteri(tgt, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
|
|
if (tgt == GL_TEXTURE_3D_EXT)
|
|
glTexImage3DEXT(tgt, 0, dstFormat, wdt, hgt, depth, 0, srcFormat, GL_UNSIGNED_BYTE, src);
|
|
else
|
|
glTexImage2D(tgt, 0, dstFormat, wdt, hgt, 0, srcFormat, GL_UNSIGNED_BYTE, src);
|
|
}
|
|
else
|
|
{
|
|
GenerateMips_SW(tgt, src, wdt, hgt, dstFormat, ti);
|
|
}
|
|
CalcMipsAndSize(ti);
|
|
}
|
|
|
|
void CGLTexMan::BuildMips8(GLenum tgt, STexPic *ti, byte *data, bool bSub)
|
|
{
|
|
GLuint SourceFormat = GL_COLOR_INDEX;
|
|
GLuint InternalFormat = GL_COLOR_INDEX8_EXT;
|
|
int width = ti->m_Width;
|
|
int height = ti->m_Height;
|
|
|
|
ti->m_Size = 0;
|
|
if (bSub)
|
|
glTexSubImage2D(tgt, 0, 0, 0, width, height, SourceFormat, GL_UNSIGNED_BYTE, data);
|
|
else
|
|
{
|
|
glTexImage2D(tgt, 0, InternalFormat, width, height, 0, SourceFormat, GL_UNSIGNED_BYTE, data);
|
|
ti->m_Size += TexSize(width, height, 1, InternalFormat);
|
|
}
|
|
|
|
int miplevel;
|
|
miplevel = 0;
|
|
|
|
byte *out = new byte [width*height];
|
|
byte *outRet = out;
|
|
ti->m_nMips = 0;
|
|
while (width > 1 || height > 1)
|
|
{
|
|
ti->m_nMips++;
|
|
MipMap8Bit (ti, data, out, width, height);
|
|
width >>= 1;
|
|
height >>= 1;
|
|
if (width < 1)
|
|
width = 1;
|
|
if (height < 1)
|
|
height = 1;
|
|
miplevel++;
|
|
if (bSub)
|
|
glTexSubImage2D(tgt, miplevel, 0, 0, width, height, SourceFormat, GL_UNSIGNED_BYTE, out);
|
|
else
|
|
{
|
|
glTexImage2D(tgt, miplevel, InternalFormat, width, height, 0, SourceFormat, GL_UNSIGNED_BYTE, out);
|
|
ti->m_Size += TexSize(width, height, 1, InternalFormat);
|
|
}
|
|
Exchange(out, data);
|
|
}
|
|
delete [] outRet;
|
|
}
|
|
|
|
byte *CGLTexMan::GenerateDXT_HW(STexPic *ti, EImFormat eF, byte *dst, int *numMips, int *DXTSize, bool bMips)
|
|
{
|
|
int mode = 0;
|
|
|
|
uint tnum = 0;
|
|
glGenTextures(1, &tnum);
|
|
assert(tnum<14000);
|
|
SetTexture(tnum, eTT_Base);
|
|
|
|
if (eF == eIF_DXT1)
|
|
mode = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
else
|
|
if (eF == eIF_DXT3)
|
|
mode = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
else
|
|
if (eF == eIF_DXT5)
|
|
mode = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
|
|
|
int wdt = ti->m_Width;
|
|
int hgt = ti->m_Height;
|
|
int Size = TexSize(wdt,hgt,1,mode);
|
|
if (SUPPORTS_GL_SGIS_generate_mipmap)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
else
|
|
return NULL;
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, mode, wdt, hgt, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, dst);
|
|
int nMips = 1;
|
|
while (wdt>1 || hgt>1)
|
|
{
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
if (wdt < 1)
|
|
wdt = 1;
|
|
if (hgt < 1)
|
|
hgt = 1;
|
|
Size += TexSize(wdt,hgt,1,mode);
|
|
if (!bMips)
|
|
break;
|
|
nMips++;
|
|
}
|
|
ti->m_nMips = nMips;
|
|
*DXTSize = Size;
|
|
*numMips = nMips;
|
|
|
|
int mip_size = 0;
|
|
int level = 0;
|
|
int w = 0, h = 0;
|
|
byte *data = new byte [Size];
|
|
int nOffs = 0;
|
|
do
|
|
{
|
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &h);
|
|
if (!w || !h)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
glDeleteTextures(1, &tnum);
|
|
delete [] data;
|
|
return NULL;
|
|
}
|
|
|
|
mip_size=0;
|
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_IMAGE_SIZE_ARB, &mip_size);
|
|
|
|
glGetCompressedTexImageARB(GL_TEXTURE_2D, level, &data[nOffs]);
|
|
nOffs += mip_size;
|
|
|
|
level++;
|
|
if (!bMips)
|
|
break;
|
|
}
|
|
while((w!=1 || h!=1));
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
glDeleteTextures(1, &tnum);
|
|
SetTexture(0, eTT_Base);
|
|
|
|
return data;
|
|
}
|
|
|
|
//TArray<STexPic *> sTestStr;
|
|
//TArray<STexPic *> sTestTx;
|
|
|
|
STexPic *CGLTexMan::CopyTexture(const char *name, STexPic *tiSrc, int CubeSide)
|
|
{
|
|
STexPic *ti = TextureInfoForName(name, -1, tiSrc->m_eTT, tiSrc->m_Flags, tiSrc->m_Flags2, 0);
|
|
|
|
ti->m_bBusy = true;
|
|
ti->m_Flags = tiSrc->m_Flags;
|
|
ti->m_Flags2 = tiSrc->m_Flags2;
|
|
ti->m_Bind = TX_FIRSTBIND + ti->m_Id;
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->m_Width = tiSrc->m_Width;
|
|
ti->m_Height = tiSrc->m_Height;
|
|
ti->m_nMips = tiSrc->m_nMips;
|
|
ti->m_ETF = tiSrc->m_ETF;
|
|
ti->m_CubeSide = CubeSide;
|
|
ti->m_DstFormat = tiSrc->m_DstFormat;
|
|
|
|
int w, h;
|
|
tiSrc->Set();
|
|
if (tiSrc->m_eTT == eTT_Cubemap)
|
|
{
|
|
const GLenum cubefaces[6] =
|
|
{
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,
|
|
};
|
|
for (int i=0; i<tiSrc->m_nMips; i++)
|
|
{
|
|
int tgt = cubefaces[tiSrc->m_CubeSide];
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_WIDTH, &w);
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_HEIGHT, &h);
|
|
if (!w || !h)
|
|
{
|
|
ti->Release(false);
|
|
return NULL;
|
|
}
|
|
if (tiSrc->m_ETF == eTF_DXT1 || tiSrc->m_ETF == eTF_DXT3 || tiSrc->m_ETF == eTF_DXT5)
|
|
{
|
|
int mip_size;
|
|
glGetTexLevelParameteriv(tgt, i, GL_TEXTURE_IMAGE_SIZE_ARB, &mip_size);
|
|
byte *data = new byte[mip_size];
|
|
glGetCompressedTexImageARB(tgt, i, data);
|
|
tgt = cubefaces[ti->m_CubeSide];
|
|
glCompressedTexImage2DARB(tgt, i, ti->m_DstFormat, w, h, 0, mip_size, data);
|
|
delete [] data;
|
|
}
|
|
else
|
|
{
|
|
byte *data = new byte[w*h*4];
|
|
glGetTexImage(tgt, i, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
tgt = cubefaces[ti->m_CubeSide];
|
|
glTexImage2D(tgt, i, tiSrc->m_DstFormat, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
delete [] data;
|
|
}
|
|
}
|
|
}
|
|
return ti;
|
|
}
|
|
|
|
STexPic *CGLTexMan::CreateTexture(const char *name, int wdt, int hgt, int depth, uint flags, uint flags2, byte *dst, ETexType eTT, float fAmount1, float fAmount2, int DXTSize, STexPic *ti, int bind, ETEX_Format eTF, const char *szSourceName)
|
|
{
|
|
byte *dst1 = NULL;
|
|
int m;
|
|
int i;
|
|
|
|
GLenum tgt = GL_TEXTURE_2D;
|
|
int DxtBlockSize = 0;
|
|
int DxtOneSize = 0;
|
|
bool bMips;
|
|
|
|
int w = ilog2(wdt);
|
|
int h = ilog2(hgt);
|
|
assert (w == wdt && h == hgt);
|
|
|
|
if (!ti)
|
|
{
|
|
ti = TextureInfoForName(name, -1, eTT, flags, flags2, bind);
|
|
|
|
ti->m_bBusy = true;
|
|
ti->m_Flags = flags;
|
|
ti->m_Flags2 = flags2;
|
|
ti->m_Bind = TX_FIRSTBIND + ti->m_Id;
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->m_Height = hgt;
|
|
ti->m_Width = wdt;
|
|
ti->m_Depth = depth;
|
|
ti->m_nMips = 0;
|
|
ti->m_ETF = eTF_8888;
|
|
eTF = eTF_8888;
|
|
bind = ti->m_Bind;
|
|
}
|
|
if (szSourceName)
|
|
ti->m_SourceName = szSourceName;
|
|
|
|
if ((ti->m_Flags & FT_NOMIPS) || ti->m_nMips == 1)
|
|
{
|
|
bMips = false;
|
|
ti->m_Flags |= FT_NOMIPS;
|
|
}
|
|
else
|
|
bMips = true;
|
|
if (ti->m_Flags & FT_DXT)
|
|
{
|
|
DxtBlockSize = (ti->m_Flags & FT_DXT1) ? 8 : 16;
|
|
DxtOneSize = ((wdt+3)/4)*((hgt+3)/4)*DxtBlockSize;
|
|
}
|
|
ti->m_DXTSize = DXTSize;
|
|
ti->m_fAmount1 = fAmount1;
|
|
ti->m_fAmount2 = fAmount2;
|
|
|
|
if (dst)
|
|
{
|
|
if (ti->m_Flags & FT_CONV_GREY)
|
|
ti->m_pData32 = ConvertRGB_Gray(dst, ti, ti->m_Flags, eTF);
|
|
if (ti->m_Flags & FT_NODOWNLOAD)
|
|
{
|
|
if (ti->m_Flags & FT_DXT)
|
|
ti->m_pData32 = ImgConvertDXT_RGBA(dst, ti, DXTSize);
|
|
else
|
|
ti->m_pData32 = dst;
|
|
return ti;
|
|
}
|
|
|
|
int dstFormat = 0;
|
|
int srcFormat = GL_BGRA_EXT;
|
|
int SizeSrc = 0;
|
|
if (eTF == eTF_8888 || eTF == eTF_RGBA)
|
|
{
|
|
srcFormat = GL_BGRA_EXT;
|
|
SizeSrc = wdt * hgt * 4;
|
|
}
|
|
else
|
|
if (eTF == eTF_4444)
|
|
{
|
|
srcFormat = GL_BGRA_EXT;
|
|
int nSize = 0;
|
|
int w = wdt;
|
|
int h = hgt;
|
|
int i;
|
|
for (i=0; i<ti->m_nMips; i++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
nSize += TexSize(w, h, 1, GL_RGBA8);
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
dst1 = new byte[nSize];
|
|
w = wdt;
|
|
h = hgt;
|
|
byte *ds = dst1;
|
|
byte *sr = dst;
|
|
for (i=0; i<ti->m_nMips; i++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
for (int j=0; j<w*h; j++)
|
|
{
|
|
ds[0] = (sr[0]&0xf)<<4;
|
|
ds[1] = (sr[0]&0xf0);
|
|
ds[2] = (sr[1]&0xf)<<4;
|
|
ds[3] = (sr[1]&0xf0);
|
|
sr += 2;
|
|
ds += 4;
|
|
}
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
dst = dst1;
|
|
dstFormat = GL_RGBA4;
|
|
SizeSrc = nSize;
|
|
}
|
|
else
|
|
if (eTF == eTF_0888)
|
|
{
|
|
srcFormat = GL_BGR_EXT;
|
|
SizeSrc = wdt * hgt * 3;
|
|
}
|
|
else
|
|
if (eTF == eTF_8000)
|
|
{
|
|
SizeSrc = wdt * hgt;
|
|
srcFormat = GL_ALPHA8;
|
|
dstFormat = GL_ALPHA8;
|
|
ti->m_Flags |= FT_HASALPHA;
|
|
}
|
|
else
|
|
if (eTF == eTF_DXT1 || eTF == eTF_DXT3 || eTF == eTF_DXT5)
|
|
{
|
|
if (eTF == eTF_DXT1)
|
|
srcFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
else
|
|
if (eTF == eTF_DXT3)
|
|
srcFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
else
|
|
if (eTF == eTF_DXT5)
|
|
srcFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
}
|
|
else
|
|
if (eTF == eTF_0565 || eTF == eTF_0555)
|
|
srcFormat = GL_RGB5;
|
|
|
|
if (!(ti->m_Flags & FT_DXT) && !ti->m_pPalette)
|
|
{
|
|
if (dstFormat != GL_ALPHA8 && !(gRenDev->GetFeatures() & RFT_HWGAMMA))
|
|
{
|
|
if (!CRenderer::CV_r_noswgamma && ti->m_eTT != eTT_Bumpmap)
|
|
BuildImageGamma(ti->m_Width, ti->m_Height, dst, false);
|
|
}
|
|
}
|
|
if (ti->m_Flags2 & FT2_FORCEDXT)
|
|
{
|
|
if (!(ti->m_Flags & FT_HASALPHA))
|
|
dstFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
else
|
|
dstFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
}
|
|
else
|
|
if (ti->m_Flags & FT_DXT)
|
|
{
|
|
if (ti->m_Flags & FT_DXT1)
|
|
dstFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
else
|
|
if (ti->m_Flags & FT_DXT3)
|
|
dstFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
else
|
|
if (ti->m_Flags & FT_DXT5)
|
|
dstFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
|
else
|
|
{
|
|
Warning( VALIDATOR_FLAG_TEXTURE,ti->m_SearchName.c_str(),"Unknown DXT format for texture %s", ti->m_SearchName.c_str());
|
|
dstFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
}
|
|
srcFormat = dstFormat;
|
|
SizeSrc = DxtOneSize;
|
|
}
|
|
else
|
|
if (dstFormat == 0)
|
|
{
|
|
if (ti->m_Flags & FT_DYNAMIC)
|
|
{
|
|
if (ti->m_Flags & FT_HASALPHA)
|
|
dstFormat = GL_RGBA8;
|
|
else
|
|
dstFormat = GL_RGB8;
|
|
}
|
|
else
|
|
{
|
|
if (ti->m_eTT == eTT_Bumpmap)
|
|
{
|
|
if (CRenderer::CV_r_texbumpquality == 0)
|
|
{
|
|
if (ti->m_Flags & FT_HASALPHA)
|
|
dstFormat = GL_RGBA8;
|
|
else
|
|
dstFormat = GL_RGB8;
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_texbumpquality == 1 && SUPPORTS_GL_EXT_paletted_texture)
|
|
{
|
|
dstFormat = GL_COLOR_INDEX8_EXT;
|
|
dst1 = ConvertNMToPalettedFormat(dst, ti);
|
|
dst = dst1;
|
|
eTF = eTF_Index;
|
|
if (!m_bPaletteWasLoaded)
|
|
{
|
|
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
|
|
glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGBA, GL_UNSIGNED_BYTE, (void *)&m_NMPalette[0][0]);
|
|
m_bPaletteWasLoaded = true;
|
|
}
|
|
}
|
|
else
|
|
if ((CRenderer::CV_r_texbumpquality == 2 || strstr(ti->m_SourceName.c_str(), "_cct")) && SUPPORTS_GL_ARB_texture_compression)
|
|
{
|
|
dstFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
if (!CRenderer::CV_r_texhwdxtcompression)
|
|
{
|
|
ti->m_ETF = eTF_DXT1;
|
|
ti->m_Flags |= FT_DXT1;
|
|
dst1 = ImgConvertRGBA_DXT(dst, ti, DXTSize, ti->m_nMips, 24, true);
|
|
dst = dst1;
|
|
ti->m_DXTSize = DXTSize;
|
|
}
|
|
}
|
|
else
|
|
dstFormat = GL_RGB8;
|
|
}
|
|
else
|
|
if (ti->m_eTT == eTT_DSDTBump)
|
|
{
|
|
if (SUPPORTS_GL_NV_texture_shader)
|
|
dstFormat = GL_DSDT_MAG_NV;
|
|
else
|
|
dstFormat = GL_RGB8;
|
|
}
|
|
else
|
|
if (ti->m_Flags & FT_SKY)
|
|
{
|
|
if (CRenderer::CV_r_texskyquality == 0)
|
|
dstFormat = GL_RGB8;
|
|
else
|
|
if (CRenderer::CV_r_texskyquality == 1)
|
|
dstFormat = GL_RGB5;
|
|
else
|
|
if (CRenderer::CV_r_texskyquality == 2 && SUPPORTS_GL_ARB_texture_compression)
|
|
dstFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
else
|
|
dstFormat = GL_RGB8;
|
|
}
|
|
else
|
|
if (!(ti->m_Flags & FT_HASALPHA))
|
|
{
|
|
if (CRenderer::CV_r_texquality == 0)
|
|
dstFormat = GL_RGB8;
|
|
else
|
|
if (CRenderer::CV_r_texquality == 1)
|
|
dstFormat = GL_RGB5;
|
|
else
|
|
if (CRenderer::CV_r_texquality == 2 && SUPPORTS_GL_ARB_texture_compression)
|
|
dstFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
else
|
|
dstFormat = GL_RGB8;
|
|
}
|
|
else
|
|
if (ti->m_Flags & FT_FONT)
|
|
{
|
|
dstFormat = GL_ALPHA8;
|
|
}
|
|
else
|
|
{
|
|
if (CRenderer::CV_r_texquality == 0)
|
|
dstFormat = GL_RGBA8;
|
|
else
|
|
if (CRenderer::CV_r_texquality == 1)
|
|
dstFormat = GL_RGBA4;
|
|
else
|
|
if (CRenderer::CV_r_texquality == 2 && SUPPORTS_GL_ARB_texture_compression)
|
|
dstFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
else
|
|
dstFormat = GL_RGBA8;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ti->m_Flags & FT_FONT)
|
|
{
|
|
dstFormat = GL_ALPHA8;
|
|
}
|
|
}
|
|
ti->m_DstFormat = dstFormat;
|
|
ti->m_ETF = CGLTexMan::GetTexFormat(dstFormat);
|
|
bool bFirstCube = false;
|
|
if (ti->m_eTT == eTT_Cubemap)
|
|
{
|
|
ti->m_TargetType = GL_TEXTURE_CUBE_MAP_EXT;
|
|
int n = strlen(ti->m_SearchName.c_str()) - 4;
|
|
if (!strcmp(&ti->m_SearchName.c_str()[n], "posx"))
|
|
{
|
|
m_CurCubemapBind = bind;
|
|
m_CurCubemapFormat = ti->m_ETF;
|
|
tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT;
|
|
bFirstCube = true;
|
|
ti->m_CubeSide = 0;
|
|
m_LastCMSide = NULL;
|
|
}
|
|
else
|
|
if (!strcmp(&ti->m_SearchName.c_str()[n], "negx"))
|
|
{
|
|
tgt = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT;
|
|
ti->m_CubeSide = 1;
|
|
}
|
|
else
|
|
if (!strcmp(&ti->m_SearchName.c_str()[n], "posy"))
|
|
{
|
|
tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT;
|
|
ti->m_CubeSide = 2;
|
|
}
|
|
else
|
|
if (!strcmp(&ti->m_SearchName.c_str()[n], "negy"))
|
|
{
|
|
tgt = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT;
|
|
ti->m_CubeSide = 3;
|
|
}
|
|
else
|
|
if (!strcmp(&ti->m_SearchName.c_str()[n], "posz"))
|
|
{
|
|
tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT;
|
|
ti->m_CubeSide = 4;
|
|
}
|
|
else
|
|
if (!strcmp(&ti->m_SearchName.c_str()[n], "negz"))
|
|
{
|
|
tgt = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT;
|
|
ti->m_CubeSide = 5;
|
|
}
|
|
else
|
|
{
|
|
m_CurCubemapBind = bind;
|
|
m_CurCubemapFormat = ti->m_ETF;
|
|
tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT;
|
|
bFirstCube = true;
|
|
ti->m_CubeSide = 0;
|
|
m_LastCMSide = NULL;
|
|
}
|
|
if (!bFirstCube && m_CurCubemapFormat != ti->m_ETF)
|
|
{
|
|
if (m_CurCubemapFormat != eTF_0888 && ti->m_ETF != eTF_8888)
|
|
iLog->Log("Warning: CubeMap faces format mismath for texture '%s'\n", ti->m_SearchName.c_str());
|
|
}
|
|
|
|
if (tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT)
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, m_CurCubemapBind);
|
|
glEnable(GL_TEXTURE_CUBE_MAP_EXT);
|
|
CGLTexMan::m_TUState[m_CurStage].m_Target = GL_TEXTURE_CUBE_MAP_EXT;
|
|
}
|
|
else
|
|
{
|
|
if (ti->m_eTT == eTT_3D)
|
|
ti->m_TargetType = GL_TEXTURE_3D_EXT;
|
|
else
|
|
if (ti->m_eTT == eTT_Rectangle)
|
|
ti->m_TargetType = GL_TEXTURE_RECTANGLE_NV;
|
|
else
|
|
ti->m_TargetType = GL_TEXTURE_2D;
|
|
|
|
if (CGLTexMan::m_TUState[m_CurStage].m_Target && CGLTexMan::m_TUState[m_CurStage].m_Target != ti->m_TargetType)
|
|
glDisable(CGLTexMan::m_TUState[m_CurStage].m_Target);
|
|
|
|
CGLTexMan::m_TUState[m_CurStage].m_Target = ti->m_TargetType;
|
|
glBindTexture(ti->m_TargetType, ti->m_Bind);
|
|
glEnable(ti->m_TargetType);
|
|
|
|
tgt = ti->m_TargetType;
|
|
}
|
|
CGLTexMan::m_TUState[m_CurStage].m_Bind = ti->m_Bind;
|
|
|
|
if (ti->m_pPalette && (ti->m_pData || dst))
|
|
{
|
|
if (!(ti->m_Flags & FT_PALETTED) || !(gRenDev->GetFeatures() & RFT_PALTEXTURE))
|
|
{
|
|
byte *d = gRenDev->m_TexMan->m_TexData;
|
|
byte *src = ti->m_pData ? ti->m_pData : dst;
|
|
for (m=0; m<ti->m_Width * ti->m_Height; m++)
|
|
{
|
|
int l = ti->m_pData[m];
|
|
*(uint *)d = *(uint *)&ti->m_pPalette[l];
|
|
d += 4;
|
|
}
|
|
int nMips = 0;
|
|
if (!CGLRenderer::CV_gl_mipprocedures || (ti->m_Flags & FT_NOMIPS))
|
|
nMips = 1;
|
|
srcFormat = GL_BGRA_EXT;
|
|
dstFormat = GL_RGBA8;
|
|
if (!(ti->m_Flags & FT_HASALPHA))
|
|
dstFormat = GL_RGB8;
|
|
BuildMips(tgt, gRenDev->m_TexMan->m_TexData, ti->m_Width, ti->m_Height, ti->m_Depth, ti, srcFormat, dstFormat, 0, 0, nMips);
|
|
}
|
|
else
|
|
{
|
|
if (!ti->m_p8to24table)
|
|
ti->m_p8to24table = new uint [256];
|
|
if (!ti->m_p15to8table)
|
|
ti->m_p15to8table = new uchar [32768];
|
|
uint *table = ti->m_p8to24table;
|
|
SRGBPixel *pal = ti->m_pPalette;
|
|
uint as = 255;
|
|
uint r, g, b, a;
|
|
uint v;
|
|
for (i=0; i<256; i++)
|
|
{
|
|
r = pal->red;
|
|
g = pal->green;
|
|
b = pal->blue;
|
|
a = pal->alpha;
|
|
as &= a;
|
|
pal++;
|
|
|
|
v = (a<<24) + (r<<0) + (g<<8) + (b<<16);
|
|
*table++ = v;
|
|
}
|
|
if (as < 255)
|
|
ti->m_bAlphaPal = 1;
|
|
|
|
for (i=0; i<(1<<15); i++)
|
|
{
|
|
/* Maps
|
|
0000 0000 0000 0000
|
|
0000 0000 0001 1111 = Red = 0x1F
|
|
0000 0011 1110 0000 = Blue = 0x03E0
|
|
0111 1100 0000 0000 = Grn = 0x7C00
|
|
*/
|
|
r = ((i & 0x1F) << 3)+4;
|
|
g = ((i & 0x03E0) >> 2)+4;
|
|
b = ((i & 0x7C00) >> 7)+4;
|
|
uchar *pal = (uchar *)ti->m_p8to24table;
|
|
uint v;
|
|
int j,k,l;
|
|
int r1,g1,b1;
|
|
for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4)
|
|
{
|
|
r1 = r-pal[0];
|
|
g1 = g-pal[1];
|
|
b1 = b-pal[2];
|
|
j = (r1*r1)+(g1*g1)+(b1*b1);
|
|
if (j<l)
|
|
{
|
|
k = v;
|
|
l = j;
|
|
}
|
|
}
|
|
ti->m_p15to8table[i] = k;
|
|
}
|
|
|
|
glColorTableEXT( tgt, GL_RGBA, 256, GL_BGRA_EXT, GL_UNSIGNED_BYTE, ti->m_pPalette );
|
|
GLuint SourceFormat = GL_COLOR_INDEX;
|
|
GLuint InternalFormat = GL_COLOR_INDEX8_EXT;
|
|
byte *src = ti->m_pData ? ti->m_pData : dst;
|
|
if (CGLRenderer::CV_gl_mipprocedures && !(ti->m_Flags & FT_NOMIPS))
|
|
{
|
|
BuildMips8(tgt, ti, src, false);
|
|
}
|
|
else
|
|
{
|
|
ti->m_Flags |= FT_NOMIPS;
|
|
glTexImage2D(tgt, 0, InternalFormat, ti->m_Width, ti->m_Height, 0, SourceFormat, GL_UNSIGNED_BYTE, src);
|
|
ti->m_Size = TexSize(ti->m_Width, ti->m_Height, ti->m_Depth, InternalFormat);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int nMips = ti->m_nMips;
|
|
if (ti->m_Flags & FT_NOMIPS)
|
|
nMips = 1;
|
|
if (IsDXTFormat(dstFormat))
|
|
{
|
|
bool bComp = ((gRenDev->GetFeatures() & RFT_COMPRESSTEXTURE) != 0);
|
|
if (!bComp)
|
|
{
|
|
dst1 = ImgConvertDXT_RGBA(dst, ti, DXTSize);
|
|
dst = dst1;
|
|
dstFormat = GL_RGBA8;
|
|
}
|
|
else
|
|
{
|
|
DxtBlockSize = (dstFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ? 8 : 16;
|
|
DxtOneSize = ((wdt+3)/4)*((hgt+3)/4)*DxtBlockSize;
|
|
}
|
|
}
|
|
BuildMips(tgt, dst, wdt, hgt, depth, ti, srcFormat, dstFormat, DxtBlockSize, DXTSize, nMips);
|
|
}
|
|
if (ti->m_eTT == eTT_Cubemap)
|
|
{
|
|
if (tgt == GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT)
|
|
{
|
|
ti->SetFilter();
|
|
ti->SetWrapping();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ti->SetFilter();
|
|
ti->SetWrapping();
|
|
}
|
|
|
|
if (tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT)
|
|
{
|
|
int nnn = 0;
|
|
SetTexture(0, eTT_Cubemap);
|
|
}
|
|
else
|
|
if (tgt == GL_TEXTURE_2D)
|
|
SetTexture(0, eTT_Base);
|
|
} // if (dst)
|
|
if (ti->m_Flags & FT_NOMIPS)
|
|
ti->m_nMips = 1;
|
|
if (ti->m_eTT == eTT_Cubemap)
|
|
{
|
|
ti->m_Size *= 6;
|
|
if (m_LastCMSide)
|
|
m_LastCMSide->m_NextCMSide = ti;
|
|
if (tgt == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT)
|
|
m_LastCMSide = NULL;
|
|
else
|
|
m_LastCMSide = ti;
|
|
}
|
|
if (ti->m_eTT != eTT_Cubemap || !ti->m_CubeSide)
|
|
{
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
//sTestStr.AddElem(ti);
|
|
}
|
|
CheckTexLimits(NULL);
|
|
if (m_Streamed == 2)
|
|
ti->Unload();
|
|
|
|
SAFE_DELETE_ARRAY (dst1);
|
|
|
|
return ti;
|
|
}
|
|
|
|
//============================================================================
|
|
|
|
void CGLTexMan::BuildMipsSub(byte* src, int wdt, int hgt)
|
|
{
|
|
int wd;
|
|
int i;
|
|
byte *src1, *dst1;
|
|
int num;
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, wdt, hgt, GL_BGRA_EXT, GL_UNSIGNED_BYTE, src);
|
|
num = 1;
|
|
while (wdt!=1 && hgt!=1)
|
|
{
|
|
wd = wdt<<2;
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
if (wdt < 1)
|
|
wdt = 1;
|
|
if (hgt < 1)
|
|
hgt = 1;
|
|
//if (wdt == 1 || hgt == 1) // Riva TNT Bug
|
|
// break;
|
|
|
|
src1 = dst1 = src;
|
|
for (i=0; i<hgt; i++)
|
|
{
|
|
byte *src2 = src1;
|
|
int j;
|
|
for (j=0; j<wdt; j++)
|
|
{
|
|
dst1[0] = (src2[0]+src2[4]+src2[wd]+src2[wd+4])>>2;
|
|
dst1[1] = (src2[1]+src2[5]+src2[wd+1]+src2[wd+5])>>2;
|
|
dst1[2] = (src2[2]+src2[6]+src2[wd+2]+src1[wd+6])>>2;
|
|
dst1[3] = (src2[3]+src2[7]+src2[wd+3]+src2[wd+7])>>2;
|
|
dst1 += 4;
|
|
src2 += 8;
|
|
}
|
|
src1 += wd<<1;
|
|
}
|
|
glTexSubImage2D(GL_TEXTURE_2D, num, 0, 0, wdt, hgt, GL_BGRA_EXT, GL_UNSIGNED_BYTE, src);
|
|
num++;
|
|
}
|
|
}
|
|
|
|
void CGLTexMan::BuildMipsSub_DSDT(byte* src, int wdt, int hgt)
|
|
{
|
|
int wd;
|
|
int i;
|
|
byte *src1, *dst1;
|
|
int num;
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, wdt, hgt, GL_DSDT_MAG_NV, GL_UNSIGNED_BYTE, src);
|
|
num = 1;
|
|
while (wdt!=1 && hgt!=1)
|
|
{
|
|
wd = wdt<<2;
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
if (wdt < 1)
|
|
wdt = 1;
|
|
if (hgt < 1)
|
|
hgt = 1;
|
|
//if (wdt == 1 || hgt == 1) // Riva TNT Bug
|
|
// break;
|
|
|
|
src1 = dst1 = src;
|
|
for (i=0; i<hgt; i++)
|
|
{
|
|
byte *src2 = src1;
|
|
int j;
|
|
for (j=0; j<wdt; j++)
|
|
{
|
|
dst1[0] = (src2[0]+src2[3]+src2[wd]+src2[wd+3])>>2;
|
|
dst1[1] = (src2[1]+src2[4]+src2[wd+1]+src2[wd+4])>>2;
|
|
dst1[2] = (src2[2]+src2[5]+src2[wd+2]+src1[wd+5])>>2;
|
|
dst1 += 3;
|
|
src2 += 6;
|
|
}
|
|
src1 += wd<<1;
|
|
}
|
|
glTexSubImage2D(GL_TEXTURE_2D, num, 0, 0, wdt, hgt, GL_DSDT_MAG_NV, GL_UNSIGNED_BYTE, src);
|
|
num++;
|
|
}
|
|
}
|
|
|
|
|
|
_inline void CGLTexMan::mfMakeS8T8_EdgePix(int x, int y, byte *src, byte *dst, int wdt, int hgt, int lSrcPitch, int lDstPitch)
|
|
{
|
|
int x1 = x-1==-1 ? wdt : x-1;
|
|
int y1 = y-1==-1 ? hgt : y-1;
|
|
LONG v00 = src[y*lSrcPitch+x]; // Get the current pixel
|
|
LONG v01 = src[y*lSrcPitch+((x+1)&wdt)]; // and the pixel to the right
|
|
LONG vM1 = src[y*lSrcPitch+x1]; // and the pixel to the left
|
|
LONG v10 = src[((y+1)&hgt)*lSrcPitch+x]; // and the pixel one line below.
|
|
LONG v1M = src[y1*lSrcPitch+x]; // and the pixel one line above.
|
|
|
|
LONG iDu = (vM1-v01); // The delta-u bump value
|
|
LONG iDv = (v1M-v10); // The delta-v bump value
|
|
|
|
if ( (v00 < vM1) && (v00 < v01) ) // If we are at valley
|
|
{
|
|
iDu = vM1-v00; // Choose greater of 1st order diffs
|
|
if ( iDu < v00-v01 )
|
|
iDu = v00-v01;
|
|
}
|
|
|
|
byte *ds = &dst[y*lDstPitch+(x*3)];
|
|
|
|
ds[0] = (byte)iDu;
|
|
ds[1] = (byte)iDv;
|
|
ds[2] = 255;
|
|
}
|
|
|
|
void CGLTexMan::UpdateTextureRegion(STexPic *pic, byte *data, int X, int Y, int USize, int VSize)
|
|
{
|
|
pic->Set();
|
|
switch(pic->m_ETF)
|
|
{
|
|
case eTF_8888:
|
|
glTexSubImage2D(pic->m_TargetType, 0, X, Y, USize, VSize, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
|
|
break;
|
|
case eTF_8000:
|
|
{
|
|
int nSize = USize*VSize;
|
|
byte *pBuf = new byte[nSize];
|
|
for (int i=0; i<nSize; i++)
|
|
{
|
|
pBuf[i] = data[i*4+3];
|
|
}
|
|
glTexSubImage2D(pic->m_TargetType, 0, X, Y, USize, VSize, GL_ALPHA, GL_UNSIGNED_BYTE, pBuf);
|
|
delete [] pBuf;
|
|
break;
|
|
}
|
|
default:
|
|
assert(0);
|
|
}
|
|
//pic->SaveTGA("Font.tga", 0);
|
|
}
|
|
|
|
void CGLTexMan::UpdateTextureData(STexPic *pic, byte *data, int USize, int VSize, bool bProc, int State, bool bPal)
|
|
{
|
|
pic->Set();
|
|
|
|
if (State == GS_BUMP)
|
|
{
|
|
if (pic->m_eTT == eTT_DSDTBump)
|
|
{
|
|
int x, y;
|
|
byte *dst = new byte [USize * VSize * 3];
|
|
byte *src = data;
|
|
int wdt = USize;
|
|
int hgt = VSize;
|
|
int lSrcPitch = wdt;
|
|
int lDstPitch = wdt*3;
|
|
byte *pDst = dst+lDstPitch+3;
|
|
byte *pSrc = src+lSrcPitch+1;
|
|
for(y=1; y<hgt-1; y++ )
|
|
{
|
|
byte* pDstT = pDst;
|
|
byte* pSrcB0 = (BYTE*)pSrc;
|
|
byte* pSrcB1 = ( pSrcB0 + lSrcPitch );
|
|
byte* pSrcB2 = ( pSrcB0 - lSrcPitch );
|
|
|
|
for(x=1; x<wdt-1; x++ )
|
|
{
|
|
int v00 = *(pSrcB0+0); // Get the current pixel
|
|
int v01 = *(pSrcB0+1); // and the pixel to the right
|
|
int vM1 = *(pSrcB0-1); // and the pixel to the left
|
|
int v10 = *(pSrcB1+0); // and the pixel one line below.
|
|
int v1M = *(pSrcB2+0); // and the pixel one line above.
|
|
|
|
int iDu = (vM1-v01); // The delta-u bump value
|
|
int iDv = (v1M-v10); // The delta-v bump value
|
|
|
|
if ( (v00 < vM1) && (v00 < v01) ) // If we are at valley
|
|
{
|
|
iDu = vM1-v00; // Choose greater of 1st order diffs
|
|
if ( iDu < v00-v01 )
|
|
iDu = v00-v01;
|
|
}
|
|
|
|
pDstT[0] = (byte)iDu;
|
|
pDstT[1] = (byte)iDv;
|
|
pDstT[2] = 255;
|
|
|
|
pDstT += 3;
|
|
|
|
pSrcB0+=1; // Move one pixel to the left (src is 32-bpp)
|
|
pSrcB1+=1;
|
|
pSrcB2+=1;
|
|
}
|
|
pSrc += lSrcPitch; // Move to the next line
|
|
pDst += lDstPitch;
|
|
}
|
|
int UMask = wdt-1;
|
|
int VMask = hgt-1;
|
|
for (x=1; x<wdt-1; x++)
|
|
{
|
|
mfMakeS8T8_EdgePix(x, 0, src, dst, UMask, VMask, lSrcPitch, lDstPitch);
|
|
mfMakeS8T8_EdgePix(x, hgt-1, src, dst, UMask, VMask, lSrcPitch, lDstPitch);
|
|
}
|
|
for (y=0; y<hgt; y++)
|
|
{
|
|
mfMakeS8T8_EdgePix(0, y, src, dst, UMask, VMask, lSrcPitch, lDstPitch);
|
|
mfMakeS8T8_EdgePix(wdt-1, y, src, dst, UMask, VMask, lSrcPitch, lDstPitch);
|
|
}
|
|
if (CGLRenderer::CV_gl_mipprocedures)
|
|
BuildMipsSub(dst, USize, VSize);
|
|
else
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, USize, VSize, GL_DSDT_MAG_NV, GL_BYTE, dst);
|
|
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_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
|
|
pic->m_Flags |= FT_NOMIPS;
|
|
}
|
|
delete [] dst;
|
|
}
|
|
else
|
|
{
|
|
int nMips, nSize;
|
|
byte *dst = GenerateNormalMap(data, USize, VSize, CGLRenderer::CV_gl_mipprocedures ? 0 : FT_NOMIPS, 0, eTT_Bumpmap, 50.0f, pic, nMips, nSize, eTF_8888);
|
|
int w = USize;
|
|
int h = VSize;
|
|
if (nMips == 1)
|
|
{
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA8, GL_UNSIGNED_BYTE, dst);
|
|
pic->m_nMips = 1;
|
|
}
|
|
else
|
|
if (nMips > 1)
|
|
{
|
|
byte *data = dst;
|
|
for (int l=0; l<nMips; l++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
glTexSubImage2D(GL_TEXTURE_2D, l, 0, 0, w, h, GL_RGBA8, GL_UNSIGNED_BYTE, data);
|
|
data += w*h*4;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
pic->m_nMips = nMips;
|
|
}
|
|
delete [] dst;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (bPal)
|
|
{
|
|
GLuint SourceFormat = GL_COLOR_INDEX;
|
|
GLuint InternalFormat = GL_COLOR_INDEX8_EXT;
|
|
if (CGLRenderer::CV_gl_mipprocedures && !(pic->m_Flags & FT_NOMIPS))
|
|
{
|
|
BuildMips8(GL_TEXTURE_2D, pic, data, true);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GetMinFilter());
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GetMagFilter());
|
|
}
|
|
else
|
|
{
|
|
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, USize, VSize, SourceFormat, GL_UNSIGNED_BYTE, data );
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
pic->m_Flags |= FT_NOMIPS;
|
|
}
|
|
return;
|
|
}
|
|
if (CGLRenderer::CV_gl_mipprocedures)
|
|
BuildMipsSub((byte *)data, USize, VSize);
|
|
else
|
|
{
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, USize, VSize, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
pic->m_Flags |= FT_NOMIPS;
|
|
}
|
|
}
|
|
|
|
//TODO:replace with ARB_Buffer_Region and move into the class
|
|
void ClearBufferWithQuad(int x2,int y2,int x1,int y1,float fR,float fG,float fB,STexPic *pImage, int Side)
|
|
{
|
|
if (pImage)
|
|
{
|
|
if (gRenDev->CV_r_ReplaceCubeMap==1)
|
|
pImage = (STexPic *)gRenDev->EF_LoadTexture("textures/cube_face", 0, 0, eTT_Cubemap);
|
|
gRenDev->Set2DMode(true, 256, 256);
|
|
Vec3d crd[4];
|
|
if (pImage->m_eTT == eTT_Cubemap)
|
|
{
|
|
switch(Side)
|
|
{
|
|
case 0: //posx
|
|
crd[0] = Vec3d(1,1,1);
|
|
crd[1] = Vec3d(1,-1,1);
|
|
crd[2] = Vec3d(1,-1,-1);
|
|
crd[3] = Vec3d(1,1,-1);
|
|
break;
|
|
case 1: //negx
|
|
crd[0] = Vec3d(-1,1,1);
|
|
crd[1] = Vec3d(-1,-1,1);
|
|
crd[2] = Vec3d(-1,-1,-1);
|
|
crd[3] = Vec3d(-1,1,-1);
|
|
break;
|
|
case 2: //posy
|
|
crd[0] = Vec3d(1,1,1);
|
|
crd[1] = Vec3d(-1,1,1);
|
|
crd[2] = Vec3d(-1,1,-1);
|
|
crd[3] = Vec3d(1,1,-1);
|
|
break;
|
|
case 3: //negy
|
|
crd[0] = Vec3d(1,-1,1);
|
|
crd[1] = Vec3d(-1,-1,1);
|
|
crd[2] = Vec3d(-1,-1,-1);
|
|
crd[3] = Vec3d(1,-1,-1);
|
|
break;
|
|
case 4: //posz
|
|
crd[0] = Vec3d(1,1,1);
|
|
crd[1] = Vec3d(-1,1,1);
|
|
crd[2] = Vec3d(-1,-1,1);
|
|
crd[3] = Vec3d(1,-1,1);
|
|
break;
|
|
case 5: //negz
|
|
crd[0] = Vec3d(1,1,-1);
|
|
crd[1] = Vec3d(-1,1,-1);
|
|
crd[2] = Vec3d(-1,-1,-1);
|
|
crd[3] = Vec3d(1,-1,-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_STENCIL_TEST);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDepthMask(1);
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
pImage->Set();
|
|
glEnable(pImage->m_TargetType);
|
|
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glColor3f(fR,fG,fB);
|
|
|
|
glTexCoord3f(crd[0][0], crd[0][1], crd[0][2]);
|
|
glVertex3f(0.0f, 0.0f, 0.0f); // Top Left
|
|
|
|
glTexCoord3f(crd[1][0], crd[1][1], crd[1][2]);
|
|
glVertex3f(0.0f, 256.0f, 0.0f); // Bottom Left
|
|
|
|
glTexCoord3f(crd[2][0], crd[2][1], crd[2][2]);
|
|
glVertex3f(256.0f, 256.0f, 0.0f); // Bottom Right
|
|
|
|
glTexCoord3f(crd[3][0], crd[3][1], crd[3][2]);
|
|
glVertex3f(256.0f, 0.0f, 0.0f); // Top Right
|
|
|
|
glEnd();
|
|
|
|
if (pImage->m_eTT == eTT_Cubemap)
|
|
glDisable(pImage->m_TargetType);
|
|
|
|
gRenDev->Set2DMode(false, 256, 256);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glEnable(GL_CULL_FACE);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
{
|
|
/*int width = 256;
|
|
int height = 256;
|
|
byte *pic = new byte [width * height * 4];
|
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
WriteTGA(pic,width,height,"EndCube.tga");
|
|
delete [] pic;*/
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//glClearColor(1,0,0,0);
|
|
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
//glScissor(0, 0, x2, y2);
|
|
//glDisable (GL_SCISSOR_TEST);
|
|
gcpOGL->EF_ClearBuffers(true, false);
|
|
//glScissor(0, 0, gcpOGL->GetWidth(), gcpOGL->GetHeight());
|
|
/*gcpOGL->m_bWasCleared = true;
|
|
glClearColor(gcpOGL->m_vClearColor.x,gcpOGL->m_vClearColor.y,gcpOGL->m_vClearColor.z,0);
|
|
if (gRenDev->GetStencilBpp())
|
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
else
|
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
|
|
}
|
|
}
|
|
|
|
|
|
void CGLTexMan::CreateBufRegion(int Width, int Height)
|
|
{
|
|
if (SUPPORTS_WGL_ARB_buffer_region)
|
|
{
|
|
for (int i=0; i<m_BufRegions.Num(); i++)
|
|
{
|
|
SBufRegion *br = &m_BufRegions[i];
|
|
if (br->m_Width == Width && br->m_Height == Height)
|
|
break;
|
|
}
|
|
if (i == m_BufRegions.Num())
|
|
{
|
|
SBufRegion b;
|
|
b.m_Width = Width;
|
|
b.m_Height = Height;
|
|
b.m_BRHandle = wglCreateBufferRegionARB(gcpOGL->m_CurrContext->m_hDC, 0, WGL_DEPTH_BUFFER_BIT_ARB | WGL_BACK_COLOR_BUFFER_BIT_ARB);
|
|
if (b.m_BRHandle)
|
|
{
|
|
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
|
|
// Copy the framebuffer to the buffer region (only depth).
|
|
wglSaveBufferRegionARB(b.m_BRHandle, 0, 0, Width, Height);
|
|
}
|
|
m_BufRegions.AddElem(b);
|
|
}
|
|
}
|
|
}
|
|
|
|
STextureTarget *CGLTexMan::CreateTextureTarget(int Bind, int Width, int Height)
|
|
{
|
|
int i;
|
|
|
|
if (!SUPPORTS_WGL_ARB_render_texture)
|
|
return NULL;
|
|
|
|
for (i=0; i<m_TexTargets.Num(); i++)
|
|
{
|
|
STextureTarget *pTT = &m_TexTargets[i];
|
|
if (pTT->m_Bind == Bind)
|
|
return pTT;
|
|
}
|
|
STextureTarget texT;
|
|
texT.m_Bind = Bind;
|
|
texT.m_Width = Width;
|
|
texT.m_Height = Height;
|
|
texT.m_DrawCount = 0;
|
|
texT.m_pBuffer = new CPBuffer(Width, Height, FPB_SINGLE | FPB_DRAWTOTEXTURE | FPB_DEPTH);
|
|
texT.m_pBuffer->mfInitialize(true);
|
|
m_TexTargets.AddElem(texT);
|
|
|
|
return &m_TexTargets[i];
|
|
}
|
|
|
|
static _inline int sLimitSizeByScreenRes(int size)
|
|
{
|
|
while(true)
|
|
{
|
|
if (size>gRenDev->GetWidth() || size>gRenDev->GetHeight())
|
|
size >>= 1;
|
|
else
|
|
break;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
void CGLTexMan::ClearBuffer(int Width, int Height, bool bEnd,STexPic *pImage, int Side)
|
|
{
|
|
SBufRegion *br = NULL;
|
|
if (SUPPORTS_WGL_ARB_buffer_region)
|
|
{
|
|
for (int i=0; i<m_BufRegions.Num(); i++)
|
|
{
|
|
br = &m_BufRegions[i];
|
|
if (br->m_Width == Width && br->m_Height == Height)
|
|
break;
|
|
}
|
|
if (i == m_BufRegions.Num())
|
|
return;
|
|
}
|
|
// Clear the frame buffer (only depth)
|
|
if (br && br->m_BRHandle)
|
|
{
|
|
// Restore the buffer region.
|
|
wglRestoreBufferRegionARB(br->m_BRHandle, 0, 0, Width, Height, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if (bEnd)
|
|
ClearBufferWithQuad(Width, Height,0,0,0,0,0,NULL,0);
|
|
else
|
|
ClearBufferWithQuad(Width, Height,0,0,1,1,1,pImage,Side);
|
|
}
|
|
|
|
}
|
|
|
|
//===================================================================================
|
|
|
|
void CGLTexMan::DrawCubeSide( const float *angle, Vec3d& Pos, int tex_size, int side, int RendFlags)
|
|
{
|
|
if (!iSystem)
|
|
return;
|
|
|
|
CRenderer * renderer = gRenDev;
|
|
CCamera tmp_camera = renderer->GetCamera();
|
|
CCamera prevCamera = tmp_camera;
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
float fMinDist = 0.25f;
|
|
|
|
tmp_camera.Init(tex_size,tex_size, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
tmp_camera.SetPos(Pos);
|
|
tmp_camera.SetAngle(Vec3d(angle[0], angle[1], angle[2]));
|
|
tmp_camera.Update();
|
|
|
|
iSystem->SetViewCamera(tmp_camera);
|
|
gRenDev->SetCamera(tmp_camera);
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
gRenDev->SetViewport(tex_size*(int)angle[3], tex_size*(int)angle[4], tex_size, tex_size);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (DrawCubeSide %d)\n", side);
|
|
|
|
eng->DrawLowDetail(RendFlags);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (DrawCubeSide %d)\n", side);
|
|
|
|
iSystem->SetViewCamera(prevCamera);
|
|
gRenDev->SetCamera(prevCamera);
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
static const GLenum cubefaces[6] =
|
|
{
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,
|
|
};
|
|
|
|
static float sAngles[6][5] =
|
|
{
|
|
{ 90, -90, 0, 0, 0 }, //posx
|
|
{ 90, 90, 0, 1, 0 }, //negx
|
|
{ 180, 180, 0, 2, 0 }, //posy
|
|
{ 0, 180, 0, 0, 1 }, //negy
|
|
{ 90, 180, 0, 1, 1 }, //posz
|
|
{ 90, 0, 0, 2, 1 }, //negz
|
|
};
|
|
|
|
int gEnvFrame;
|
|
|
|
|
|
bool CGLTexMan::ScanEnvironmentCM (const char *name, int size, Vec3d& Pos)
|
|
{
|
|
char szName[256];
|
|
|
|
ClearBuffer(size,size,true,NULL,0);
|
|
int RendFlags = -1;
|
|
RendFlags &= ~DLD_ENTITIES;
|
|
int vX, vY, vWidth, vHeight;
|
|
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
StripExtension(name, szName);
|
|
|
|
int *pFR = (int *)gRenDev->EF_Query(EFQ_Pointer2FrameID);
|
|
for(int n=0; n<6; n++)
|
|
{
|
|
(*pFR)++;
|
|
|
|
DrawCubeSide( &sAngles[n][0], Pos, size, n, RendFlags);
|
|
static char* cubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
|
|
char str[256];
|
|
int width = size;
|
|
int height = size;
|
|
byte *pic = new byte [width * height * 4];
|
|
glReadPixels(size*(int)sAngles[n][3], size*(int)sAngles[n][4], width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
sprintf(str, "%s_%s.jpg", szName, cubefaces[n]);
|
|
WriteJPG(pic, width, height, str);
|
|
delete [] pic;
|
|
}
|
|
|
|
gRenDev->SetViewport(vX, vY, vWidth, vHeight);
|
|
ClearBuffer(size,size,true,NULL,0);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CGLTexMan::GetAverageColor(SEnvTexture *cm, int nSide)
|
|
{
|
|
}
|
|
|
|
void CGLTexMan::ScanEnvironmentCube(SEnvTexture *cm, int RendFlags, int Size, bool bLightCube)
|
|
{
|
|
if (cm->m_bInprogress)
|
|
return;
|
|
|
|
CRenderer * renderer = gRenDev;
|
|
int tex_size;
|
|
switch (CRenderer::CV_r_envcmresolution)
|
|
{
|
|
case 0:
|
|
tex_size = 64;
|
|
break;
|
|
case 1:
|
|
tex_size = 128;
|
|
break;
|
|
case 2:
|
|
tex_size = 256;
|
|
break;
|
|
case 3:
|
|
default:
|
|
tex_size = 512;
|
|
break;
|
|
}
|
|
while(true)
|
|
{
|
|
if (tex_size*3>renderer->GetWidth() || tex_size*2>renderer->GetHeight())
|
|
tex_size >>= 1;
|
|
else
|
|
break;
|
|
}
|
|
if (tex_size <= 8)
|
|
return;
|
|
|
|
int n;
|
|
Vec3d cur_pos;
|
|
|
|
cm->m_bInprogress = true;
|
|
int tid = TO_ENVIRONMENT_CUBE_MAP_REAL + cm->m_Id;
|
|
if (!(cm->m_Tex->m_Flags & FT_ALLOCATED) || tex_size != cm->m_TexSize)
|
|
{
|
|
cm->m_Tex->m_Flags |= FT_ALLOCATED;
|
|
SetTexture(tid, eTT_Cubemap);
|
|
cm->m_TexSize = tex_size;
|
|
for(int n=0; n<6; n++)
|
|
{
|
|
glTexImage2D(cubefaces[n], 0, GL_RGB, tex_size, tex_size, 0, GL_RGB, GL_FLOAT, 0);
|
|
}
|
|
SetTexture(0, eTT_Cubemap);
|
|
}
|
|
|
|
CreateBufRegion(tex_size, tex_size);
|
|
ClearBuffer(tex_size,tex_size,true,NULL,0);
|
|
//gRenDev->EF_SaveDLights();
|
|
|
|
int Start, End;
|
|
if (!cm->m_bReady || CRenderer::CV_r_envcmwrite)
|
|
{
|
|
Start = 0;
|
|
End = 6;
|
|
}
|
|
else
|
|
{
|
|
Start = cm->m_MaskReady;
|
|
End = cm->m_MaskReady+1;
|
|
}
|
|
int vX, vY, vWidth, vHeight;
|
|
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
gRenDev->EF_PushFog();
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
Vec3d Pos;
|
|
gRenDev->m_RP.m_pRE->mfCenter(Pos, gRenDev->m_RP.m_pCurObject);
|
|
Pos += cm->m_CamPos;
|
|
|
|
int *pFR = (int *)gRenDev->EF_Query(EFQ_Pointer2FrameID);
|
|
for(n=Start; n<End; n++)
|
|
{
|
|
*pFR++;
|
|
DrawCubeSide( &sAngles[n][0], Pos, tex_size, n, RendFlags);
|
|
if (CRenderer::CV_r_envcmwrite)
|
|
{
|
|
static char* cubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
|
|
char str[256];
|
|
int width = tex_size;
|
|
int height = tex_size;
|
|
byte *pic = new byte [width * height * 4];
|
|
glReadPixels(tex_size*(int)sAngles[n][3], tex_size*(int)sAngles[n][4], width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
sprintf(str, "Cube_%s.jpg", cubefaces[n]);
|
|
WriteJPG(pic, width, height, str);
|
|
delete [] pic;
|
|
}
|
|
}
|
|
CRenderer::CV_r_envcmwrite = 0;
|
|
|
|
cm->m_Tex->m_Bind = tid;
|
|
SetTexture(tid, eTT_Cubemap);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
|
|
|
|
for(n=Start; n<End; n++ )
|
|
{
|
|
glCopyTexSubImage2D(cubefaces[n], 0, 0, 0, (int)(tex_size*sAngles[n][3]), (int)(tex_size*sAngles[n][4]), tex_size, tex_size);
|
|
}
|
|
|
|
gRenDev->SetViewport(vX, vY, vWidth, vHeight);
|
|
ClearBuffer(tex_size,tex_size,true,NULL,0);
|
|
cm->m_bInprogress = false;
|
|
cm->m_MaskReady = End;
|
|
if (cm->m_MaskReady == 6)
|
|
{
|
|
cm->m_MaskReady = 0;
|
|
cm->m_bReady = true;
|
|
}
|
|
SetTexture(0, eTT_Cubemap);
|
|
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
gRenDev->EF_PopFog();
|
|
//gRenDev->EF_RestoreDLights();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
static Matrix44 sMatrixLookAt( const Vec3d &dir,const Vec3d &up,float rollAngle=0 )
|
|
{
|
|
Matrix44 M;
|
|
// LookAt transform.
|
|
Vec3d xAxis,yAxis,zAxis;
|
|
Vec3d upVector = up;
|
|
|
|
yAxis = GetNormalized(-dir);
|
|
|
|
//if (zAxis.x == 0.0 && zAxis.z == 0) up.Set( -zAxis.y,0,0 ); else up.Set( 0,1.0f,0 );
|
|
|
|
xAxis = GetNormalized(upVector.Cross(yAxis));
|
|
zAxis = GetNormalized(xAxis.Cross(yAxis));
|
|
|
|
// OpenGL kind of matrix.
|
|
M[0][0] = xAxis.x;
|
|
M[1][0] = yAxis.x;
|
|
M[2][0] = zAxis.x;
|
|
M[3][0] = 0;
|
|
|
|
M[0][1] = xAxis.y;
|
|
M[1][1] = yAxis.y;
|
|
M[2][1] = zAxis.y;
|
|
M[3][1] = 0;
|
|
|
|
M[0][2] = xAxis.z;
|
|
M[1][2] = yAxis.z;
|
|
M[2][2] = zAxis.z;
|
|
M[3][2] = 0;
|
|
|
|
M[0][3] = 0;
|
|
M[1][3] = 0;
|
|
M[2][3] = 0;
|
|
M[3][3] = 1;
|
|
|
|
if (rollAngle != 0)
|
|
{
|
|
Matrix44 RollMtx;
|
|
RollMtx.SetIdentity();
|
|
|
|
float cossin[2];
|
|
cry_sincosf(rollAngle*gf_DEGTORAD, cossin);
|
|
|
|
RollMtx[0][0] = cossin[0]; RollMtx[2][0] = -cossin[1];
|
|
RollMtx[0][2] = cossin[1]; RollMtx[2][2] = cossin[0];
|
|
|
|
// Matrix multiply.
|
|
M = RollMtx * M;
|
|
}
|
|
|
|
return M;
|
|
}
|
|
|
|
void CGLTexMan::ScanEnvironmentTexture(SEnvTexture *cm, SShader *pSH, SRenderShaderResources *pRes, int RendFlags, bool bUseExistingREs)
|
|
{
|
|
static float Smat[16] =
|
|
{
|
|
0.5f, 0, 0, 0,
|
|
0, 0.5f, 0, 0,
|
|
0, 0, 0.5f, 0,
|
|
0.5f, 0.5f, 0.5f, 1.0f
|
|
};
|
|
|
|
if (cm->m_bInprogress)
|
|
return;
|
|
|
|
CRenderer * rn = gRenDev;
|
|
int tex_size;
|
|
|
|
bool bUseClipPlanes = false;
|
|
bool bUseReflection = false;
|
|
if (pSH)
|
|
{
|
|
if (pSH->m_Flags3 & (EF3_CLIPPLANE_BACK | EF3_CLIPPLANE_FRONT))
|
|
bUseClipPlanes = true;
|
|
if (bUseClipPlanes || (pSH->m_Flags3 & EF3_REFLECTION))
|
|
bUseReflection = true;
|
|
}
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
float fMinDist = 0.25f;
|
|
|
|
ECull eCull = eCULL_None;
|
|
if (pSH)
|
|
eCull = pSH->m_eCull;
|
|
if (pRes && (pRes->m_ResFlags & MTLFLAG_2SIDED))
|
|
eCull = eCULL_None;
|
|
|
|
bool bWater = (pSH && ((pSH->m_nPreprocess & FSPR_SCANTEXWATER) != 0));
|
|
Plane Pl, PlTr;
|
|
float plane[4];
|
|
CCObject *obj = rn->m_RP.m_pCurObject;
|
|
if (bUseClipPlanes || bUseReflection)
|
|
{
|
|
if (!bWater)
|
|
rn->m_RP.m_pRE->mfGetPlane(Pl);
|
|
else
|
|
{
|
|
Pl.n = Vec3d(0,0,1);
|
|
Pl.d = eng->GetWaterLevel();
|
|
}
|
|
if (obj)
|
|
{
|
|
rn->m_RP.m_FrameObject++;
|
|
PlTr = TransformPlane(obj->GetMatrix(), Pl);
|
|
}
|
|
else
|
|
PlTr = Pl;
|
|
if (pSH && pSH->m_Flags3 & EF3_CLIPPLANE_BACK)
|
|
{
|
|
PlTr.n = -PlTr.n;
|
|
PlTr.d = -PlTr.d;
|
|
}
|
|
if (eCull != eCULL_None)
|
|
{
|
|
CCamera tmp_camera = rn->GetCamera();
|
|
Vec3d pos = tmp_camera.GetPos();
|
|
float dot = pos.Dot(PlTr.n) - PlTr.d;
|
|
if (dot <= 0.1f)
|
|
return;
|
|
}
|
|
plane[0] = PlTr.n[0];
|
|
plane[1] = PlTr.n[1];
|
|
plane[2] = PlTr.n[2];
|
|
plane[3] = -PlTr.d;
|
|
|
|
if (!bWater)
|
|
fMinDist = rn->m_RP.m_pRE->mfMinDistanceToCamera(obj);
|
|
}
|
|
|
|
switch (CRenderer::CV_r_envtexresolution)
|
|
{
|
|
case 0:
|
|
tex_size = 64;
|
|
break;
|
|
case 1:
|
|
tex_size = 128;
|
|
break;
|
|
case 2:
|
|
default:
|
|
tex_size = 256;
|
|
break;
|
|
case 3:
|
|
tex_size = 512;
|
|
break;
|
|
}
|
|
tex_size = sLimitSizeByScreenRes(tex_size);
|
|
if (tex_size <= 8)
|
|
return;
|
|
|
|
Vec3d cur_pos;
|
|
|
|
int tid = TO_ENVIRONMENT_TEX_MAP_REAL + cm->m_Id;
|
|
if (!(cm->m_Tex->m_Flags & FT_ALLOCATED) || tex_size != cm->m_TexSize)
|
|
{
|
|
cm->m_Tex->m_Flags |= FT_ALLOCATED;
|
|
cm->m_TexSize = tex_size;
|
|
SetTexture(tid, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_size, tex_size, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
cm->m_bInprogress = true;
|
|
CreateBufRegion(tex_size,tex_size);
|
|
ClearBuffer(tex_size,tex_size,true,NULL,0);
|
|
//rn->EF_SaveDLights();
|
|
|
|
int vX, vY, vWidth, vHeight;
|
|
rn->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
rn->EF_PushFog();
|
|
rn->m_RP.m_bDrawToTexture = true;
|
|
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
|
|
int prevFlags = rn->m_RP.m_PersFlags;
|
|
|
|
{
|
|
CCamera tmp_camera = rn->GetCamera();
|
|
CCamera prevCamera = tmp_camera;
|
|
|
|
// camere reflection by plane
|
|
if (bUseReflection || (pSH && (pSH->m_Flags3 & EF3_CLIPPLANE_FRONT)))
|
|
{
|
|
// mirror case
|
|
Vec3d vPrevPos = tmp_camera.GetPos();
|
|
Matrix44 camMat = tmp_camera.GetVCMatrixD3D9();
|
|
Vec3d vPrevDir = Vec3d(-camMat(0,2), -camMat(1,2), -camMat(2,2));
|
|
Vec3d vPrevUp = Vec3d(camMat(0,1), camMat(1,1), camMat(2,1));
|
|
Vec3d vNewDir = PlTr.MirrorVector(vPrevDir);
|
|
Vec3d vNewUp = PlTr.MirrorVector(vPrevUp);
|
|
Matrix44 m = sMatrixLookAt( vNewDir, vNewUp, tmp_camera.GetAngles()[1] );
|
|
|
|
float fDot = vPrevPos.Dot(PlTr.n) - PlTr.d;
|
|
Vec3d vNewPos = vPrevPos - PlTr.n * 2.0f*fDot;
|
|
Vec3d vNewOccPos = vPrevPos - PlTr.n * 0.99f*fDot;
|
|
if (fDot < 0)
|
|
{
|
|
plane[0] = -plane[0];
|
|
plane[1] = -plane[1];
|
|
plane[2] = -plane[2];
|
|
plane[3] = -plane[3];
|
|
}
|
|
|
|
CryQuat q = Quat( GetTransposed44(m) );
|
|
Vec3d vNewAngs = Ang3::GetAnglesXYZ(Matrix33(q));
|
|
vNewAngs = RAD2DEG(vNewAngs);
|
|
|
|
rn->m_RP.m_pRE->mfCenter(vNewOccPos, obj);
|
|
tmp_camera.SetAngle(vNewAngs);
|
|
tmp_camera.SetPos(vNewPos);
|
|
tmp_camera.SetOccPos(vNewOccPos);
|
|
tmp_camera.Init(tex_size, tex_size, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
tmp_camera.Update();
|
|
|
|
iSystem->SetViewCamera(tmp_camera);
|
|
rn->SetCamera(tmp_camera);
|
|
|
|
if (!cm->m_Tex->m_Matrix)
|
|
cm->m_Tex->m_Matrix = new float[16];
|
|
}
|
|
else
|
|
{
|
|
iSystem->SetViewCamera(tmp_camera);
|
|
rn->SetCamera(tmp_camera);
|
|
}
|
|
if (bUseClipPlanes || bUseReflection)
|
|
{
|
|
Plane p;
|
|
p.n.Set(plane[0], plane[1], plane[2]);
|
|
p.d = plane[3];
|
|
tmp_camera.SetFrustumPlane(FR_PLANE_NEAR, p);
|
|
}
|
|
|
|
if (!cm->m_Tex->m_Matrix)
|
|
cm->m_Tex->m_Matrix = new float[16];
|
|
|
|
float matProj[16], matView[16], m2[16];
|
|
|
|
glGetFloatv(GL_PROJECTION_MATRIX, matProj);
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, matView);
|
|
mathMatrixMultiply(m2, &Smat[0], matProj, g_CpuFlags);
|
|
mathMatrixMultiply(cm->m_Tex->m_Matrix, m2, matView, g_CpuFlags);
|
|
//SGLFuncs::glMultMatrix(cm->m_Tex->m_Matrix, m1, rn->m_RP.m_pCurObject->GetMatrix().GetData());
|
|
//memcpy(cm->m_Tex->m_Matrix, m1, 4*4*4);
|
|
|
|
if (bUseClipPlanes)
|
|
gcpOGL->EF_SetClipPlane(true, plane, bWater);
|
|
|
|
rn->SetViewport(0, 0, tex_size, tex_size);
|
|
|
|
if (rn->m_LogFile)
|
|
rn->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (ScanEnvironmentTexture)\n");
|
|
|
|
if (bUseExistingREs)
|
|
gcpOGL->EF_RenderPipeLine(CGLRenderer::EF_Flush);
|
|
else
|
|
eng->DrawLowDetail(RendFlags);
|
|
|
|
if (rn->m_LogFile)
|
|
rn->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (ScanEnvironmentTexture)\n");
|
|
|
|
iSystem->SetViewCamera(prevCamera);
|
|
rn->SetCamera(prevCamera);
|
|
}
|
|
|
|
if (bUseClipPlanes)
|
|
gcpOGL->EF_SetClipPlane(false, NULL, false);
|
|
|
|
rn->m_RP.m_PersFlags &= ~(RBPF_DRAWMIRROR | RBPF_DRAWPORTAL);
|
|
rn->m_RP.m_PersFlags |= prevFlags & (RBPF_DRAWMIRROR | RBPF_DRAWPORTAL);
|
|
|
|
cm->m_Tex->m_Bind = tid;
|
|
SetTexture(tid, 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);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tex_size, tex_size);
|
|
|
|
/*{
|
|
int width = tex_size;
|
|
int height = tex_size;
|
|
byte *pic = new byte [width * height * 4];
|
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
WriteJPG(pic, width, height, "Bug.jpg");
|
|
delete [] pic;
|
|
}*/
|
|
|
|
rn->SetViewport(vX, vY, vWidth, vHeight);
|
|
ClearBuffer(tex_size,tex_size,true,NULL,0);
|
|
cm->m_bInprogress = false;
|
|
cm->m_bReady = true;
|
|
cm->m_MaskReady = 1;
|
|
rn->m_RP.m_bDrawToTexture = false;
|
|
rn->EF_PopFog();
|
|
|
|
SetTexture(0, eTT_Base);
|
|
|
|
//rn->EF_RestoreDLights();
|
|
}
|
|
|
|
//========================================================================================
|
|
|
|
static CCamera sPrevCamera;
|
|
|
|
void CGLTexMan::StartCubeSide(CCObject *obj)
|
|
{
|
|
int tex_size = 256;
|
|
int numCM = obj->m_NumCM;
|
|
if (numCM < 0 || numCM > 16)
|
|
numCM = 0;
|
|
bool bCube = true;
|
|
if (obj->m_ObjFlags & FOB_TEXTURE)
|
|
bCube = false;
|
|
SEnvTexture *cm;
|
|
if (bCube)
|
|
cm = &gRenDev->m_TexMan->m_CustomCMaps[numCM];
|
|
else
|
|
cm = &gRenDev->m_TexMan->m_CustomTextures[numCM];
|
|
int tid = cm->m_Tex->m_Bind;
|
|
int n = obj->m_ObjFlags & FOB_CUBE_MASK;
|
|
switch (n)
|
|
{
|
|
case FOB_CUBE_POSX:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** Start cube side (POSX) ***\n");
|
|
n = 0;
|
|
break;
|
|
case FOB_CUBE_NEGX:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** Start cube side (NEGX) ***\n");
|
|
n = 1;
|
|
break;
|
|
case FOB_CUBE_POSY:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** Start cube side (POSY) ***\n");
|
|
n = 2;
|
|
break;
|
|
case FOB_CUBE_NEGY:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** Start cube side (NEGY) ***\n");
|
|
n = 3;
|
|
break;
|
|
case FOB_CUBE_POSZ:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** Start cube side (POSZ) ***\n");
|
|
n = 4;
|
|
break;
|
|
case FOB_CUBE_NEGZ:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** Start cube side (NEGZ) ***\n");
|
|
n = 5;
|
|
break;
|
|
}
|
|
if (!cm->m_MaskReady)
|
|
{
|
|
if (obj->m_ObjFlags & FOB_TEXTURE)
|
|
{
|
|
SetTexture(tid, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_size, tex_size, 0, GL_RGB, GL_FLOAT, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
else
|
|
{
|
|
SetTexture(tid, eTT_Cubemap);
|
|
for(int n=0; n<6; n++)
|
|
{
|
|
glTexImage2D(cubefaces[n], 0, GL_RGB, tex_size, tex_size, 0, GL_RGB, GL_FLOAT, 0);
|
|
}
|
|
SetTexture(0, eTT_Cubemap);
|
|
}
|
|
}
|
|
sPrevCamera = gRenDev->GetCamera();
|
|
CCamera tmp_camera= gRenDev->GetCamera();
|
|
tmp_camera.Init(tex_size,tex_size);
|
|
tmp_camera.SetPos(Vec3d(obj->m_Trans2[0], obj->m_Trans2[1], obj->m_Trans2[2]));
|
|
tmp_camera.SetAngle(Vec3d(obj->m_Angs2[0], obj->m_Angs2[1], obj->m_Angs2[2]));
|
|
tmp_camera.Update();
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport(0, 0, tex_size, tex_size);
|
|
|
|
gRenDev->SetCamera(tmp_camera);
|
|
//gRenDev->LoadMatrix(0);
|
|
//gRenDev->RotateMatrix(obj->m_Angs2.z, 0,0,1);
|
|
//gRenDev->RotateMatrix(obj->m_Angs2.y, 0,1,0);
|
|
//gRenDev->RotateMatrix(obj->m_Angs2.x, 1,0,0);
|
|
//gRenDev->TranslateMatrix(-obj->m_Trans2);
|
|
|
|
CreateBufRegion(tex_size, tex_size);
|
|
ClearBuffer(tex_size,tex_size,false,(STexPic*)obj->m_pLightImage, n);
|
|
|
|
/*int width = 256;
|
|
int height = 256;
|
|
byte *pic = new byte [width * height * 3];
|
|
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pic);
|
|
CImage::SaveTga(pic,FORMAT_24_BIT,width,height,"StartCube.tga",false);
|
|
delete [] pic;*/
|
|
}
|
|
|
|
void CGLTexMan::EndCubeSide(CCObject *obj, bool bNeedClear)
|
|
{
|
|
CRenderer * renderer = gRenDev;
|
|
int tex_size = 256;
|
|
int numCM = obj->m_NumCM;
|
|
if (numCM < 0 || numCM > 16)
|
|
numCM = 0;
|
|
bool bCube = true;
|
|
if (obj->m_ObjFlags & FOB_TEXTURE)
|
|
bCube = false;
|
|
SEnvTexture *cm;
|
|
if (bCube)
|
|
cm = &gRenDev->m_TexMan->m_CustomCMaps[numCM];
|
|
else
|
|
cm = &gRenDev->m_TexMan->m_CustomTextures[numCM];
|
|
int tid = cm->m_Tex->m_Bind;
|
|
|
|
int type;
|
|
ETexType eTT;
|
|
if (bCube)
|
|
{
|
|
type = GL_TEXTURE_CUBE_MAP_EXT;
|
|
eTT = eTT_Cubemap;
|
|
}
|
|
else
|
|
{
|
|
type = GL_TEXTURE_2D;
|
|
eTT = eTT_Base;
|
|
}
|
|
SetTexture(tid, eTT);
|
|
glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(type, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(type, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(type, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
|
|
|
|
int n = obj->m_ObjFlags & FOB_CUBE_MASK;
|
|
cm->m_MaskReady |= n >> FOB_CUBE_SHIFT;
|
|
if (cm->m_MaskReady == 0x3f || cm->m_MaskReady == 0x40)
|
|
cm->m_bReady = true;
|
|
switch (n)
|
|
{
|
|
case FOB_CUBE_POSX:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** End cube side (POSX) ***\n");
|
|
n = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT;
|
|
break;
|
|
case FOB_CUBE_POSY:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** End cube side (POSY) ***\n");
|
|
n = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT;
|
|
break;
|
|
case FOB_CUBE_POSZ:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** End cube side (POSZ) ***\n");
|
|
n = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT;
|
|
break;
|
|
case FOB_CUBE_NEGX:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** End cube side (NEGX) ***\n");
|
|
n = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT;
|
|
break;
|
|
case FOB_CUBE_NEGY:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** End cube side (NEGY) ***\n");
|
|
n = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT;
|
|
break;
|
|
case FOB_CUBE_NEGZ:
|
|
if (gcpOGL->m_LogFile)
|
|
gcpOGL->Logv(SRendItem::m_RecurseLevel, "*** End cube side (NEGZ) ***\n");
|
|
n = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT;
|
|
break;
|
|
case FOB_TEXTURE:
|
|
n = GL_TEXTURE_2D;
|
|
break;
|
|
}
|
|
|
|
glCopyTexSubImage2D(n, 0, 0, 0, 0, 0, tex_size, tex_size);
|
|
|
|
SetTexture(0, eTT);
|
|
|
|
/*int width = 800;
|
|
int height = 600;
|
|
byte *pic = new byte [width * height * 4];
|
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
WriteTGA(pic,width,height,"EndCube.tga");
|
|
delete [] pic;*/
|
|
|
|
if (bNeedClear)
|
|
ClearBuffer(tex_size,tex_size,true,NULL,0);
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
gRenDev->SetCamera(sPrevCamera);
|
|
}
|
|
|
|
inline void MultGLMatrix(const double *a, const double *b, double *product )
|
|
{
|
|
/* This matmul was contributed by Thomas Malik */
|
|
int i;
|
|
|
|
#define A(row,col) a[(col<<2)+row]
|
|
#define B(row,col) b[(col<<2)+row]
|
|
#define P(row,col) product[(col<<2)+row]
|
|
|
|
/* i-te Zeile */
|
|
for (i = 0; i < 4; i++) {
|
|
double ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
|
|
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
|
|
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
|
|
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
|
|
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
|
|
}
|
|
|
|
#undef A
|
|
#undef B
|
|
#undef P
|
|
}
|
|
|
|
inline void _multMatrices(float *dst, const float *a, const float *b)
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
dst[i * 4 + j] =
|
|
b[i * 4 + 0] * a[0 * 4 + j] +
|
|
b[i * 4 + 1] * a[1 * 4 + j] +
|
|
b[i * 4 + 2] * a[2 * 4 + j] +
|
|
b[i * 4 + 3] * a[3 * 4 + j];
|
|
}
|
|
}
|
|
}
|
|
|
|
void CGLTexMan::DrawToTexture(Plane& Pl, STexPic *Tex, int RendFlags)
|
|
{
|
|
static float Smat[16] =
|
|
{
|
|
0.5f, 0, 0, 0,
|
|
0, 0.5f, 0, 0,
|
|
0, 0, 0.5f, 0,
|
|
0.5f, 0.5f, 0.5f, 1.0f
|
|
};
|
|
|
|
if (Tex->m_Flags & FT_BUILD)
|
|
return;
|
|
float plane[4];
|
|
|
|
plane[0] = Pl.n[0];
|
|
plane[1] = Pl.n[1];
|
|
plane[2] = Pl.n[2];
|
|
plane[3] = -Pl.d;
|
|
|
|
int nWidth = sLimitSizeByScreenRes(512);
|
|
int nHeight = nWidth;
|
|
if (nWidth != Tex->m_Width || nHeight != Tex->m_Height)
|
|
{
|
|
int nSize = min(nWidth, nHeight);
|
|
Tex->m_Width = nSize;
|
|
Tex->m_Height = nSize;
|
|
Tex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
|
|
Tex->m_Flags |= FT_BUILD;
|
|
if (!(Tex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
Tex->m_Flags |= FT_ALLOCATED;
|
|
// Preallocate texture
|
|
AddToHash(Tex->m_Bind, Tex);
|
|
Tex->m_RefTex.m_VidTex = CreateTextureTarget(Tex->m_Bind, Tex->m_Width, Tex->m_Height);
|
|
if (!Tex->m_RefTex.m_VidTex)
|
|
{
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Tex->m_Width, Tex->m_Height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
Tex->m_Size = CGLTexMan::TexSize(Tex->m_Width, Tex->m_Height, 1, GL_RGB8);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
}
|
|
|
|
STextureTarget *tt = (STextureTarget *)Tex->m_RefTex.m_VidTex;
|
|
if (!tt)
|
|
{
|
|
CreateBufRegion(Tex->m_Width, Tex->m_Height);
|
|
ClearBuffer(Tex->m_Width, Tex->m_Height,true,NULL,0);
|
|
}
|
|
else
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, Tex->m_Bind);
|
|
if (tt->m_DrawCount)
|
|
tt->m_pBuffer->mfReleaseFromTexture();
|
|
tt->m_pBuffer->mfMakeCurrent();
|
|
// clear all pixels.
|
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
|
}
|
|
|
|
//gRenDev->EF_SaveDLights();
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
|
|
float fMinDist = min(SKY_BOX_SIZE*0.5f, eng->GetDistanceToSectorWithWater());
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
|
|
CCamera tmp_cam = gRenDev->GetCamera();
|
|
CCamera prevCamera = tmp_cam;
|
|
Vec3d vPrevPos = tmp_cam.GetPos();
|
|
Matrix44 camMat = tmp_cam.GetVCMatrixD3D9();
|
|
Vec3d vPrevDir = Vec3d(-camMat(0,2), -camMat(1,2), -camMat(2,2));
|
|
Vec3d vPrevUp = Vec3d(camMat(0,1), camMat(1,1), camMat(2,1));
|
|
Vec3d vNewDir = Pl.MirrorVector(vPrevDir);
|
|
Vec3d vNewUp = Pl.MirrorVector(vPrevUp);
|
|
Matrix44 mMir = sMatrixLookAt( vNewDir, vNewUp, tmp_cam.GetAngles()[1] );
|
|
|
|
float fDot = vPrevPos.Dot(Pl.n) - Pl.d;
|
|
Vec3d vNewPos = vPrevPos - Pl.n * 2.0f*fDot;
|
|
Vec3d vOccPos = vPrevPos - Pl.n * 0.99f*fDot;
|
|
|
|
CryQuat q = Quat( GetTransposed44(mMir) );
|
|
|
|
Vec3d vNewAngs = Ang3::GetAnglesXYZ(Matrix33(q));
|
|
vNewAngs = RAD2DEG(vNewAngs);
|
|
|
|
tmp_cam.SetAngle(vNewAngs);
|
|
tmp_cam.SetPos(vNewPos);
|
|
tmp_cam.SetOccPos(vOccPos);
|
|
tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
tmp_cam.Update();
|
|
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
|
|
gRenDev->EF_PushFog();
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
//iSystem->SetViewCamera(tmp_cam);
|
|
//gRenDev->SetCamera(tmp_cam);
|
|
eng->SetCamera(tmp_cam,false);
|
|
|
|
if (!Tex->m_Matrix)
|
|
Tex->m_Matrix = new float[16];
|
|
|
|
float matProj[16], matView[16], m2[16];
|
|
|
|
glGetFloatv(GL_PROJECTION_MATRIX, matProj);
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, matView);
|
|
mathMatrixMultiply(m2, &Smat[0], matProj, g_CpuFlags);
|
|
mathMatrixMultiply(Tex->m_Matrix, m2, matView, g_CpuFlags);
|
|
//SGLFuncs::glMultMatrix(Tex->m_Matrix, m1, &gRenDev->m_ObjMatrix.m_values[0][0]);
|
|
|
|
gcpOGL->EF_SetClipPlane(true, plane, false);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (DrawToTexture)\n");
|
|
|
|
eng->DrawLowDetail(RendFlags);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (End DrawToTexture)\n");
|
|
|
|
gcpOGL->EF_SetClipPlane(false, plane, false);
|
|
Tex->m_Flags &= ~FT_BUILD;
|
|
|
|
/*int width = 512;
|
|
int height = 512;
|
|
byte *pic = new byte [width * height * 4];
|
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
WriteJPG(pic,width,height,"WaterMap.jpg");
|
|
delete [] pic;*/
|
|
|
|
if (tt)
|
|
{
|
|
tt->m_DrawCount++;
|
|
tt->m_pBuffer->mfMakeMainCurrent();
|
|
glBindTexture(GL_TEXTURE_2D, Tex->m_Bind);
|
|
tt->m_pBuffer->mfTextureBind();
|
|
}
|
|
else
|
|
{
|
|
glReadBuffer(GL_BACK);
|
|
SetTexture(Tex->m_Bind, 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);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
//glTexImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
//glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 0, 0, Tex->m_Width, Tex->m_Height, 0);
|
|
|
|
ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL,0);
|
|
}
|
|
SetTexture(0, eTT_Base);
|
|
|
|
gRenDev->SetCamera(prevCamera);
|
|
iSystem->SetViewCamera(prevCamera);
|
|
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
gRenDev->EF_PopFog();
|
|
|
|
//gRenDev->EF_RestoreDLights();
|
|
}
|
|
|
|
// ===============================================================
|
|
// FlashBang fx
|
|
// Last Update: 03/05/2003
|
|
|
|
// render flashbang fx
|
|
void CGLTexMan::DrawFlashBangMap(int iId, int iRenderFlags, CREFlashBang *pRE)
|
|
{
|
|
if (!iSystem || pRE->GetFlashTimeOut()!=1.0f)
|
|
{
|
|
return;
|
|
}
|
|
/*
|
|
I3DEngine *pEng = (I3DEngine *)iSystem->GetI3DEngine(); // get engine interface
|
|
STexPic *pTex = gRenDev->m_TexMan->m_Text_FlashBangMap; // get flashbang texture
|
|
STexPic *pScreenTex = gRenDev->m_TexMan->m_Text_ScreenMap;
|
|
|
|
if(pTex->m_Flags & FT_BUILD)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pTex->m_Flags |= FT_BUILD;
|
|
|
|
// recreate flashbang texture if needed
|
|
if(CRenderer::CV_r_flashbangsize != gRenDev->m_RP.m_FlashBangSize)
|
|
{
|
|
if (CRenderer::CV_r_flashbangsize <= 64)
|
|
CRenderer::CV_r_flashbangsize = 64;
|
|
else
|
|
if (CRenderer::CV_r_flashbangsize <= 128)
|
|
CRenderer::CV_r_flashbangsize = 128;
|
|
else
|
|
if (CRenderer::CV_r_flashbangsize <= 256)
|
|
CRenderer::CV_r_flashbangsize = 256;
|
|
else
|
|
if (CRenderer::CV_r_flashbangsize <= 512)
|
|
CRenderer::CV_r_flashbangsize = 512;
|
|
|
|
CRenderer::CV_r_flashbangsize = sLimitSizeByScreenRes(CRenderer::CV_r_flashbangsize);
|
|
gRenDev->m_RP.m_FlashBangSize = CRenderer::CV_r_flashbangsize;
|
|
pTex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
|
|
// set properties
|
|
float fMaxDist = pEng->GetMaxViewDistance(),
|
|
fMinDist = 0.25f;
|
|
|
|
int nTexWidth = gRenDev->m_RP.m_FlashBangSize,
|
|
nTexHeight = gRenDev->m_RP.m_FlashBangSize;
|
|
|
|
// create screen texture
|
|
if (!(pTex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
pTex->m_Width = pTex->m_WidthReal = nTexWidth;
|
|
pTex->m_Height = pTex->m_HeightReal = nTexHeight;
|
|
pTex->m_Flags |= FT_ALLOCATED;
|
|
|
|
// Preallocate texture
|
|
AddToHash(pTex->m_Bind, pTex);
|
|
|
|
// create texture
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, pTex->m_Width, pTex->m_Height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
// create texture ?
|
|
CreateBufRegion(pTex->m_Width, pTex->m_Height);
|
|
|
|
// setup viewport
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport( 0, 0, pTex->m_Width, pTex->m_Height );
|
|
|
|
// save states
|
|
if(gRenDev->m_LogFile)
|
|
{
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** StartFlashBangMap... ***\n");
|
|
}
|
|
|
|
// setup flags
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
// get scene into texture
|
|
|
|
// set screen texture
|
|
SetTexture(pScreenTex->m_Bind, eTT_Rectangle);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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);
|
|
|
|
// set renderstate
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
// screen aligned quad
|
|
struct_VERTEX_FORMAT_P3F_TEX2F pScreenData[]=
|
|
{
|
|
800, 600, 0, (float)pScreenTex->m_Width, 0,
|
|
800, 0, 0, (float)pScreenTex->m_Width, (float)pScreenTex->m_Height,
|
|
0, 600, 0, 0, 0,
|
|
0, 0, 0, 0, (float)pScreenTex->m_Height,
|
|
};
|
|
|
|
// set screen mode
|
|
gRenDev->Set2DMode(true, 800, 600);
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pScreenData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
gRenDev->Set2DMode(false, 800, 600);
|
|
|
|
// render flashbang flash
|
|
STexPic *pFlashBangFlash = gRenDev->m_TexMan->m_Text_FlashBangFlash;
|
|
|
|
gRenDev->EnableBlend(true);
|
|
glBlendFunc(GL_DST_COLOR, GL_ONE);
|
|
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
// get flashbang properties
|
|
float fPosX, fPosY, fSizeX, fSizeY;
|
|
pRE->GetProperties(fPosX, fPosY, fSizeX, fSizeY);
|
|
gRenDev->Draw2dImage(fPosX-fSizeX*0.5f, fPosY-fSizeY*0.5f, fSizeX, fSizeY, pFlashBangFlash->GetTextureID());
|
|
gRenDev->EnableBlend(false);
|
|
|
|
// set texture/texture state
|
|
SetTexture(pTex->m_Bind, 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);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
// get screen
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, pTex->m_Width, pTex->m_Height);
|
|
|
|
// blur screen texture
|
|
|
|
// get renderer
|
|
static CGLRenderer *pRenderer = gcpOGL;
|
|
// get vertex program
|
|
CCGVProgram_GL *vpBlur=(CCGVProgram_GL *) gRenDev->m_RP.m_VPBlur;//(CCGVProgram_GL *) CVProgram::mfForName("CGVProgBlur", true);
|
|
// get fragment program
|
|
CPShader *fpBlur=gRenDev->m_RP.m_RCBlur;//CPShader::mfForName("RCBlur", false);
|
|
|
|
assert(pRenderer && "CREFlashBang::mfDraw - Invalid CGLRenderer pointer");
|
|
assert(vpBlur && "CREFlashBang::mfDraw - Invalid CCGVProgram_GL pointer");
|
|
assert(fpBlur && "CREFlashBang::mfDraw - Invalid CPShader pointer");
|
|
|
|
// setup vertex/fragment program
|
|
|
|
// set current vertex/fragment program
|
|
vpBlur->mfSet(true, NULL);
|
|
fpBlur->mfSet(true, NULL);
|
|
|
|
// enable vertex/fragment programs
|
|
pRenderer->EF_CommitVS();
|
|
pRenderer->EF_CommitPS();
|
|
|
|
// setup texture offsets, for texture neighboors sampling
|
|
float s1=1.0f/(float)(CRenderer::CV_r_flashbangsize);
|
|
float t1=1.0f/(float)(CRenderer::CV_r_flashbangsize);
|
|
float s_off=s1*0.5f;
|
|
float t_off=t1*0.5f;
|
|
|
|
float fOffset0[]={ s1*0.5f+s_off, t1+t_off, 0.0f, 0.0f};
|
|
float fOffset1[]={ -s1+s_off, t1*0.5f+t_off, 0.0f, 0.0f};
|
|
float fOffset2[]={-s1*0.5f+s_off, -t1+t_off, 0.0f, 0.0f};
|
|
float fOffset3[]={ s1+s_off, -t1*0.5f+t_off, 0.0f, 0.0f};
|
|
|
|
// set vertex program consts
|
|
vpBlur->mfParameter4f("Offset0", fOffset0);
|
|
vpBlur->mfParameter4f("Offset1", fOffset1);
|
|
vpBlur->mfParameter4f("Offset2", fOffset2);
|
|
vpBlur->mfParameter4f("Offset3", fOffset3);
|
|
|
|
// screen aligned quad
|
|
static struct_VERTEX_FORMAT_P3F_TEX2F pData[]=
|
|
{
|
|
1, 1, 0, 1-s_off, t_off,
|
|
1, 0, 0, 1-s_off, 1-t_off,
|
|
0, 1, 0, s_off, t_off,
|
|
0, 0, 0, s_off, 1-t_off,
|
|
};
|
|
|
|
// render quad
|
|
|
|
// set render/texture state
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
pRenderer->EF_SelectTMU(0);
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
|
|
pRenderer->EF_SelectTMU(1);
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
|
|
pRenderer->EF_SelectTMU(2);
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
|
|
pRenderer->EF_SelectTMU(3);
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
|
|
// set screen mode
|
|
gRenDev->Set2DMode(true, 1, 1);
|
|
|
|
// get projection/modelview matrix
|
|
float fMatrixModelView[16];
|
|
float fMatrixProjection[16];
|
|
gRenDev->GetModelViewMatrix(fMatrixModelView);
|
|
gRenDev->GetProjectionMatrix(fMatrixProjection);
|
|
|
|
Matrix44 pModelView(fMatrixModelView),
|
|
pProjection(fMatrixProjection),
|
|
pWorldViewProj=GetTransposed44(pModelView*pProjection);
|
|
|
|
// pass orthoprojection matrix into vertex shader
|
|
SCGBind *pModelViewProj = vpBlur->mfGetParameterBind("ModelViewOrthoProj");
|
|
|
|
if(pModelViewProj)
|
|
{
|
|
vpBlur->mfParameter(pModelViewProj, pWorldViewProj.GetData(), 4);
|
|
}
|
|
|
|
// blur texture
|
|
for(int iBlurPasses=0; iBlurPasses<2;iBlurPasses++)
|
|
{
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, pTex->m_Width, pTex->m_Height);
|
|
}
|
|
|
|
// restore previous states
|
|
gRenDev->Set2DMode(false, 1, 1);
|
|
|
|
// set flags
|
|
pTex->m_Flags &= ~FT_BUILD;
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
gRenDev->ResetToDefault();
|
|
//ClearBuffer(pTex->m_Width, pTex->m_Height, true, NULL,0);
|
|
*/
|
|
// set flags
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** EndFlashBangMap... ***\n");
|
|
}
|
|
|
|
// ===============================================================
|
|
// Glare fx
|
|
// Last Update: 07/05/2003
|
|
|
|
void CGLTexMan::DrawToTextureForGlare(int Id)
|
|
{
|
|
if (!iSystem)
|
|
return;
|
|
/*
|
|
// get data
|
|
I3DEngine *pEng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
CREGlare *pRE = gRenDev->m_RP.m_pREGlare;
|
|
STexPic *pTex = gRenDev->m_TexMan->m_Text_Glare;
|
|
STexPic *pScreenTex = gRenDev->m_TexMan->m_Text_ScreenMap;
|
|
|
|
if((pTex->m_Flags & FT_BUILD) || (pScreenTex->m_Flags & FT_BUILD))
|
|
{
|
|
return;
|
|
}
|
|
|
|
pTex->m_Flags |= FT_BUILD;
|
|
|
|
if(CRenderer::CV_r_glaresize != gRenDev->m_RP.m_GlareSize)
|
|
{
|
|
if (CRenderer::CV_r_glaresize <= 32)
|
|
CRenderer::CV_r_glaresize = 32;
|
|
else
|
|
if (CRenderer::CV_r_glaresize <= 64)
|
|
CRenderer::CV_r_glaresize = 64;
|
|
else
|
|
if (CRenderer::CV_r_glaresize <= 128)
|
|
CRenderer::CV_r_glaresize = 128;
|
|
else
|
|
CRenderer::CV_r_glaresize = 256;
|
|
|
|
CRenderer::CV_r_glaresize = sLimitSizeByScreenRes(CRenderer::CV_r_glaresize);
|
|
gRenDev->m_RP.m_GlareSize = CRenderer::CV_r_glaresize;
|
|
pTex->m_Flags &= ~FT_ALLOCATED;
|
|
pRE->m_GlareWidth = pRE->m_GlareHeight = gRenDev->m_RP.m_GlareSize;
|
|
pRE->mfInit();
|
|
}
|
|
|
|
int nTexWidth = pRE->m_GlareWidth;
|
|
int nTexHeight = pRE->m_GlareHeight;
|
|
|
|
// create texture if necessary
|
|
if (!(pTex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
pTex->m_Width = pTex->m_WidthReal = nTexWidth;
|
|
pTex->m_Height = pTex->m_HeightReal = nTexHeight;
|
|
pTex->m_Flags |= FT_ALLOCATED;
|
|
// Preallocate texture
|
|
AddToHash(pTex->m_Bind, pTex);
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, pTex->m_Width, pTex->m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
// get/set states
|
|
CCamera pTempCam = gRenDev->GetCamera();
|
|
CCamera pPrevCamera = pTempCam;
|
|
|
|
// get current screen
|
|
StartScreenTexMap(0);
|
|
EndScreenTexMap();
|
|
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
|
|
// compute screen luminosity if necessary
|
|
if(CRenderer::CV_r_glare==2)
|
|
{
|
|
static int iFrameCounter=0;
|
|
if(iFrameCounter%4==0)
|
|
{
|
|
gRenDev->ResetToDefault();
|
|
// get average screen luminosity
|
|
gRenDev->SetViewport( 0, 0, 2, 2);
|
|
pEng->SetCamera(pTempCam);
|
|
CreateBufRegion(2, 2);
|
|
|
|
// set screen texture
|
|
SetTexture(pScreenTex->m_Bind, eTT_Rectangle);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
// set renderstate
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
// screen aligned quad
|
|
static struct_VERTEX_FORMAT_P3F_TEX2F pScrData[]=
|
|
{
|
|
1, 1, 0, (float)pScreenTex->m_Width, 0,
|
|
1, 0, 0, (float)pScreenTex->m_Width, (float)pScreenTex->m_Height,
|
|
0, 1, 0, 0, 0,
|
|
0, 0, 0, 0, (float)pScreenTex->m_Height,
|
|
};
|
|
|
|
// set screen mode
|
|
gRenDev->Set2DMode(true, 1, 1);
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pScrData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
gRenDev->Set2DMode(false, 1, 1);
|
|
|
|
// copy 4 pixels
|
|
static unsigned char pBits[3*2*2];
|
|
glReadPixels(0, 0, 2, 2, GL_RGB, GL_UNSIGNED_BYTE, pBits);
|
|
|
|
//// get pixels luminosity
|
|
//float fAvgGlareAmount=0;
|
|
//for(int iY=0; iY<3*2*2; iY++)
|
|
//{
|
|
// fAvgGlareAmount+=pCurrPixel[iY];
|
|
//}
|
|
//fAvgGlareAmount /= 3.0f*2.0f*2.0f;
|
|
//fAvgGlareAmount /= 255.f;
|
|
|
|
// get pixels luminosity
|
|
float fAvgGlareAmount=0;
|
|
|
|
for(int iY=0; iY<2*2; iY++)
|
|
{
|
|
float fAvgRgb=0;
|
|
|
|
fAvgRgb+=pBits[iY*3];
|
|
fAvgRgb+=pBits[iY*3+1];
|
|
fAvgRgb+=pBits[iY*3+2];
|
|
|
|
fAvgRgb/=3.0f;
|
|
|
|
fAvgGlareAmount+= fAvgRgb;
|
|
}
|
|
|
|
fAvgGlareAmount /= 2.0f*2.0f;
|
|
fAvgGlareAmount /= 255.f;
|
|
|
|
// average pixels luminosity
|
|
CRenderer::CV_r_glareamountdynamic=fAvgGlareAmount;
|
|
|
|
iFrameCounter=0;
|
|
}
|
|
|
|
iFrameCounter++;
|
|
}
|
|
|
|
gRenDev->ResetToDefault();
|
|
CreateBufRegion(pTex->m_Width, pTex->m_Height);
|
|
|
|
// resize screen to fit glare texture
|
|
gRenDev->SetViewport( 0, 0, pTex->m_Width, pTex->m_Height );
|
|
pEng->SetCamera(pTempCam);
|
|
|
|
//gRenDev->ResetToDefault();
|
|
// create texture ?
|
|
//CreateBufRegion(pTex->m_Width, pTex->m_Height);
|
|
// clear texture ?
|
|
//ClearBuffer(pTex->m_Width, pTex->m_Height, true, NULL, 0);
|
|
|
|
// get renderer
|
|
CGLRenderer *pRenderer = gcpOGL;
|
|
// get fragment program
|
|
CCGPShader_GL *fpGlareMap=(CCGPShader_GL *)gRenDev->m_RP.m_RCGlareMap; //CPShader::mfForName("RCGlareMap", false);
|
|
assert(fpGlareMap && "CGLTexMan::DrawToTextureForGlare - Invalid CPShader pointer");
|
|
|
|
// set fragment program
|
|
fpGlareMap->mfSet(true, 0);
|
|
pRenderer->EF_CommitPS();
|
|
|
|
// set constants
|
|
float pGlareProps[]= { 0.33f, 0.61f, 0.11f, 0.0f };
|
|
fpGlareMap->mfParameter4f("Glare", pGlareProps);
|
|
|
|
// set screen texture
|
|
SetTexture(pScreenTex->m_Bind, eTT_Rectangle);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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);
|
|
|
|
// set renderstate
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
// screen aligned quad
|
|
static struct_VERTEX_FORMAT_P3F_TEX2F pScreenData[]=
|
|
{
|
|
800, 600, 0, (float)pScreenTex->m_Width, 0,
|
|
800, 0, 0, (float)pScreenTex->m_Width, (float)pScreenTex->m_Height,
|
|
0, 600, 0, 0, 0,
|
|
0, 0, 0, 0, (float)pScreenTex->m_Height,
|
|
};
|
|
|
|
// set screen mode
|
|
gRenDev->Set2DMode(true, 800, 600);
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pScreenData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
|
|
// get screen
|
|
SetTexture(pTex->m_Bind, eTT_Base);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, pTex->m_Width, pTex->m_Height);
|
|
|
|
//if (CRenderer::CV_r_glare == 3)
|
|
//{
|
|
// glReadPixels (0, 0, pTex->m_Width, pTex->m_Height, GL_RGBA, GL_UNSIGNED_BYTE, pRE->m_pGlarePixels);
|
|
// CRenderer::CV_r_glare = 1;
|
|
// WriteJPG((byte *)pRE->m_pGlarePixels, pTex->m_Width, pTex->m_Height, "Glare.jpg");
|
|
//}
|
|
|
|
// blur texture
|
|
|
|
// get vertex program
|
|
CCGVProgram_GL *vpBlur=(CCGVProgram_GL *) gRenDev->m_RP.m_VPBlur;//(CCGVProgram_GL *) CVProgram::mfForName("CGVProgBlur", true);
|
|
// get fragment program
|
|
CPShader *fpBlur=gRenDev->m_RP.m_RCBlur;//CPShader::mfForName("RCBlur", false);
|
|
|
|
assert(pRenderer && "CGLTexMan::DrawToTextureForGlare - Invalid CGLRenderer pointer");
|
|
assert(vpBlur && "CGLTexMan::DrawToTextureForGlare - Invalid CCGVProgram_GL pointer");
|
|
assert(fpBlur && "CGLTexMan::DrawToTextureForGlare - Invalid CPShader pointer");
|
|
|
|
// setup vertex/fragment program
|
|
|
|
// set current vertex/fragment program
|
|
vpBlur->mfSet(true, 0);
|
|
fpBlur->mfSet(true, 0);
|
|
|
|
// enable vertex/fragment programs
|
|
pRenderer->EF_CommitVS();
|
|
pRenderer->EF_CommitPS();
|
|
|
|
// setup texture offsets, for texture neighboors sampling
|
|
float s1=1.0f/(float) pTex->m_Width;
|
|
float t1=1.0f/(float) pTex->m_Height;
|
|
float s_off=0;//s1*0.5f;
|
|
float t_off=0;//t1*0.5f;
|
|
|
|
float fOffset0[]={ s1*0.5f+s_off, t1+t_off, 0.0f, 0.0f};
|
|
float fOffset1[]={ -s1+s_off, t1*0.5f+t_off, 0.0f, 0.0f};
|
|
float fOffset2[]={-s1*0.5f+s_off, -t1+t_off, 0.0f, 0.0f};
|
|
float fOffset3[]={ s1+s_off, -t1*0.5f+t_off, 0.0f, 0.0f};
|
|
|
|
// set vertex program consts
|
|
vpBlur->mfParameter4f("Offset0", fOffset0);
|
|
vpBlur->mfParameter4f("Offset1", fOffset1);
|
|
vpBlur->mfParameter4f("Offset2", fOffset2);
|
|
vpBlur->mfParameter4f("Offset3", fOffset3);
|
|
|
|
float fMinS = 0;
|
|
float fMinT = 0;
|
|
float fMaxS = 1.0f - fMinS;
|
|
float fMaxT = 1.0f - fMinT;
|
|
|
|
// screen aligned quad
|
|
static struct_VERTEX_FORMAT_P3F_TEX2F pData[]=
|
|
{
|
|
800, 600, 0, fMaxS, fMinT,
|
|
800, 0, 0, fMaxS, fMaxT,
|
|
0, 600, 0, fMinS, fMinT,
|
|
0, 0, 0, fMinS, fMaxT,
|
|
};
|
|
|
|
// render quad
|
|
|
|
// set render/texture state
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
pRenderer->EF_SelectTMU(0);
|
|
SetTexture(pTex->m_Bind, 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);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
pRenderer->EF_SelectTMU(1);
|
|
SetTexture(pTex->m_Bind, 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);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
pRenderer->EF_SelectTMU(2);
|
|
SetTexture(pTex->m_Bind, 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);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
pRenderer->EF_SelectTMU(3);
|
|
SetTexture(pTex->m_Bind, 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);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
// get projection/modelview matrix
|
|
float fMatrixModelView[16];
|
|
float fMatrixProjection[16];
|
|
gRenDev->GetModelViewMatrix(fMatrixModelView);
|
|
gRenDev->GetProjectionMatrix(fMatrixProjection);
|
|
|
|
Matrix44 pModelView(fMatrixModelView),
|
|
pProjection(fMatrixProjection),
|
|
pWorldViewProj=GetTransposed44(pModelView*pProjection);
|
|
|
|
// pass orthoprojection matrix into vertex shader
|
|
SCGBind *pModelViewProj = vpBlur->mfGetParameterBind("ModelViewOrthoProj");
|
|
if(pModelViewProj)
|
|
vpBlur->mfParameter(pModelViewProj, pWorldViewProj.GetData(), 4);
|
|
|
|
// blur texture
|
|
for(int iBlurPasses=0; iBlurPasses<CRenderer::CV_r_glareboxsize;iBlurPasses++)
|
|
{
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, pTex->m_Width, pTex->m_Height);
|
|
}
|
|
|
|
vpBlur->mfSet(false, 0);
|
|
fpBlur->mfSet(false, 0);
|
|
|
|
// restore previous states
|
|
gRenDev->EnableDepthWrites(true);
|
|
gRenDev->EnableDepthTest(true);
|
|
// ClearBuffer(pTex->m_Width, pTex->m_Height, true, NULL,0);
|
|
gRenDev->Set2DMode(false, 800, 600);
|
|
|
|
// restore screen...
|
|
gRenDev->ResetToDefault();
|
|
// set screen texture
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
SetTexture(pScreenTex->m_Bind, eTT_Rectangle);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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);
|
|
|
|
// set renderstate
|
|
gRenDev->EnableDepthWrites(false);
|
|
gRenDev->EnableDepthTest(false);
|
|
|
|
// set screen mode
|
|
gRenDev->Set2DMode(true, 800, 600);
|
|
gRenDev->DrawTriStrip(&(CVertexBuffer (pScreenData,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
gRenDev->Set2DMode(false, 800, 600);
|
|
|
|
gRenDev->SetCamera(pPrevCamera);
|
|
iSystem->SetViewCamera(pPrevCamera);
|
|
|
|
// restore flags/states
|
|
gRenDev->ResetToDefault();
|
|
//SetTexture(0, eTT_Base);
|
|
pTex->m_Flags &= ~FT_BUILD;
|
|
*/
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
|
|
}
|
|
|
|
//==================================================================================
|
|
// Heat map
|
|
|
|
_inline void GLQuad(float wdt, float hgt)
|
|
{
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
|
glVertex3f(0, 0, 0);
|
|
|
|
glTexCoord2f(1.0f, 0);
|
|
glVertex3f(wdt, 0, 0);
|
|
|
|
glTexCoord2f(1.0f, 1.0f);
|
|
glVertex3f(wdt, hgt, 0);
|
|
|
|
glTexCoord2f(0, 1.0f);
|
|
glVertex3f(0, hgt, 0);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void CGLTexMan::EndHeatMap()
|
|
{
|
|
gRenDev->m_RP.m_PersFlags &= ~(RBPF_DRAWHEATMAP | RBPF_NOCLEARBUF);
|
|
|
|
STexPic *Tex = gRenDev->m_TexMan->m_Text_HeatMap;
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** End Draw scene to texture for heat ***\n");
|
|
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
if (SUPPORTS_GL_SGIS_generate_mipmap && CRenderer::CV_r_heatmapmips)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
if (CRenderer::CV_r_heattype != 1)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
}
|
|
else
|
|
{
|
|
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_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
|
|
if (SUPPORTS_GL_SGIS_generate_mipmap && CRenderer::CV_r_heatmapmips)
|
|
{
|
|
if (CRenderer::CV_r_heattype != 1)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
}
|
|
|
|
gRenDev->SetCamera(m_PrevCamera);
|
|
iSystem->SetViewCamera(m_PrevCamera);
|
|
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
|
|
if (CRenderer::CV_r_heattype == 1)
|
|
{
|
|
int i;
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0.0, gRenDev->GetWidth(), 0.0, gRenDev->GetHeight(), -20.0, 0.0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
gRenDev->SetCullMode(R_CULL_NONE);
|
|
gRenDev->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
|
|
float wdt = (float)Tex->m_Width;
|
|
float hgt = (float)Tex->m_Height;
|
|
gRenDev->SetState(GS_NODEPTHTEST);
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
|
|
glColor4f(1,1,1,1);
|
|
|
|
GLQuad(wdt, hgt);
|
|
|
|
gRenDev->EF_SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
|
|
for (i=0; i<4; i++)
|
|
{
|
|
float fOffs = (i+1)*(Tex->m_Width/1024.0f);
|
|
float fAlpha = 0.1f;
|
|
glColor4f(1,1,1,fAlpha);
|
|
|
|
glPushMatrix();
|
|
glTranslatef(fOffs,0,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(-fOffs,0,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0,fOffs,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0,-fOffs,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
}
|
|
|
|
float fRandU = RandomNum() * 2.0f;
|
|
float fRandV = RandomNum() * 2.0f;
|
|
gRenDev->SetState(GS_BLSRC_DSTCOL | GS_BLDST_SRCCOL | GS_NODEPTHTEST);
|
|
STexPic *tp = gRenDev->m_TexMan->LoadTexture("Textures/Defaults/HeatNoise", 0, 0);
|
|
tp->Set();
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(fRandU, fRandV);
|
|
glVertex3f(0, 0, 0);
|
|
|
|
glTexCoord2f(4.0f+fRandU, fRandV);
|
|
glVertex3f(wdt, 0, 0);
|
|
|
|
glTexCoord2f(4.0f+fRandU, 4.0f+fRandV);
|
|
glVertex3f(wdt, hgt, 0);
|
|
|
|
glTexCoord2f(fRandU, 4.0f+fRandV);
|
|
glVertex3f(0, hgt, 0);
|
|
|
|
glEnd();
|
|
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
if (SUPPORTS_GL_SGIS_generate_mipmap && CRenderer::CV_r_heatmapmips)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
|
|
if (SUPPORTS_GL_SGIS_generate_mipmap && CRenderer::CV_r_heatmapmips)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
|
|
}
|
|
|
|
if (CRenderer::CV_r_heatmapsave)
|
|
{
|
|
CRenderer::CV_r_heatmapsave = 0;
|
|
Tex->SaveJPG("HeatMap.jpg", false);
|
|
}
|
|
|
|
SetTexture(0, eTT_Base);
|
|
|
|
//ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL,0);
|
|
|
|
Tex->m_Flags &= ~FT_BUILD;
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
|
|
gRenDev->ResetToDefault();
|
|
}
|
|
|
|
void CGLTexMan::StartHeatMap(int Id)
|
|
{
|
|
if (!iSystem)
|
|
return;
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
|
|
STexPic *Tex = gRenDev->m_TexMan->m_Text_HeatMap;
|
|
if (Tex->m_Flags & FT_BUILD)
|
|
return;
|
|
|
|
if (CRenderer::CV_r_heatsize != gRenDev->m_RP.m_HeatSize)
|
|
{
|
|
if (CRenderer::CV_r_heatsize <= 64)
|
|
CRenderer::CV_r_heatsize = 64;
|
|
else
|
|
if (CRenderer::CV_r_heatsize <= 128)
|
|
CRenderer::CV_r_heatsize = 128;
|
|
else
|
|
if (CRenderer::CV_r_heatsize <= 256)
|
|
CRenderer::CV_r_heatsize = 256;
|
|
else
|
|
if (CRenderer::CV_r_heatsize <= 512)
|
|
CRenderer::CV_r_heatsize = 512;
|
|
|
|
CRenderer::CV_r_heatsize = sLimitSizeByScreenRes(CRenderer::CV_r_heatsize);
|
|
gRenDev->m_RP.m_HeatSize = CRenderer::CV_r_heatsize;
|
|
Tex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
int nTexWidth = gRenDev->m_RP.m_HeatSize;
|
|
int nTexHeight = gRenDev->m_RP.m_HeatSize;
|
|
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
float fMinDist = 0.25f;
|
|
|
|
Tex->m_Flags |= FT_BUILD;
|
|
if (!(Tex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
Tex->m_Width = nTexWidth;
|
|
Tex->m_Height = nTexHeight;
|
|
Tex->m_Flags |= FT_ALLOCATED;
|
|
// Preallocate texture
|
|
AddToHash(Tex->m_Bind, Tex);
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Tex->m_Width, Tex->m_Height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
CreateBufRegion(Tex->m_Width, Tex->m_Height);
|
|
ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL, 0);
|
|
|
|
CCamera tmp_cam = gRenDev->GetCamera();
|
|
m_PrevCamera = tmp_cam;
|
|
//tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
//tmp_cam.Update();
|
|
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
|
|
|
|
eng->SetCamera(tmp_cam,false);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Start Draw scene to texture for heat ***\n");
|
|
|
|
gRenDev->m_RP.m_PersFlags |= RBPF_DRAWHEATMAP | RBPF_NOCLEARBUF;
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
//int nDrawFlags = DLD_INDOORS | DLD_ADD_LIGHTSOURCES | DLD_ENTITIES | DLD_PARTICLES | DLD_STATIC_OBJECTS | DLD_FAR_SPRITES | DLD_TERRAIN_FULLRES | DLD_TERRAIN_LIGHT | DLD_TERRAIN_WATER | DLD_NEAR_OBJECTS;
|
|
//eng->DrawLowDetail(nDrawFlags);
|
|
}
|
|
|
|
void CGLTexMan::EndNightMap()
|
|
{
|
|
STexPic *Tex = gRenDev->m_TexMan->m_Text_NightVisMap;
|
|
gRenDev->m_RP.m_PersFlags &= ~(RBPF_DRAWNIGHTMAP | RBPF_NOCLEARBUF);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** End Draw scene to texture for night ***\n");
|
|
|
|
SetTexture(Tex->m_Bind, 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_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
|
|
gRenDev->SetCamera(m_PrevCamera);
|
|
iSystem->SetViewCamera(m_PrevCamera);
|
|
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
|
|
if (CRenderer::CV_r_nighttype == 1)
|
|
{
|
|
int i;
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0.0, gRenDev->GetWidth(), 0.0, gRenDev->GetHeight(), -20.0, 0.0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
gRenDev->SetCullMode(R_CULL_NONE);
|
|
gRenDev->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
|
|
float wdt = (float)Tex->m_Width;
|
|
float hgt = (float)Tex->m_Height;
|
|
gRenDev->EF_SetState(GS_NODEPTHTEST);
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
|
|
glColor4f(1,1,1,1);
|
|
|
|
GLQuad(wdt, hgt);
|
|
|
|
gRenDev->EF_SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
|
|
for (i=0; i<4; i++)
|
|
{
|
|
float fOffs = (i+1)*(Tex->m_Width/1024.0f);
|
|
float fAlpha = 0.1f;
|
|
glColor4f(1,1,1,fAlpha);
|
|
|
|
glPushMatrix();
|
|
glTranslatef(fOffs,0,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(-fOffs,0,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0,fOffs,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0,-fOffs,0);
|
|
GLQuad(wdt, hgt);
|
|
glPopMatrix();
|
|
}
|
|
|
|
float fRandU = RandomNum() * 2.0f;
|
|
float fRandV = RandomNum() * 2.0f;
|
|
gRenDev->EF_SetState(GS_BLSRC_DSTCOL | GS_BLDST_SRCCOL | GS_NODEPTHTEST);
|
|
STexPic *tp = gRenDev->m_TexMan->LoadTexture("Textures/Defaults/HeatNoise", 0, 0);
|
|
tp->Set();
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(fRandU, fRandV);
|
|
glVertex3f(0, 0, 0);
|
|
|
|
glTexCoord2f(4.0f+fRandU, fRandV);
|
|
glVertex3f(wdt, 0, 0);
|
|
|
|
glTexCoord2f(4.0f+fRandU, 4.0f+fRandV);
|
|
glVertex3f(wdt, hgt, 0);
|
|
|
|
glTexCoord2f(fRandU, 4.0f+fRandV);
|
|
glVertex3f(0, hgt, 0);
|
|
|
|
glEnd();
|
|
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
|
|
}
|
|
|
|
if (CRenderer::CV_r_nightmapsave)
|
|
{
|
|
CRenderer::CV_r_nightmapsave = 0;
|
|
Tex->SaveJPG("NightMap.jpg", false);
|
|
}
|
|
|
|
SetTexture(0, eTT_Base);
|
|
|
|
//ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL,0);
|
|
|
|
Tex->m_Flags &= ~FT_BUILD;
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
|
|
gRenDev->ResetToDefault();
|
|
}
|
|
|
|
void CGLTexMan::StartNightMap(int Id)
|
|
{
|
|
if (!iSystem)
|
|
return;
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
|
|
STexPic *Tex = gRenDev->m_TexMan->m_Text_NightVisMap;
|
|
if (Tex->m_Flags & FT_BUILD)
|
|
return;
|
|
|
|
if (CRenderer::CV_r_nightsize != gRenDev->m_RP.m_NightSize)
|
|
{
|
|
if (CRenderer::CV_r_nightsize <= 64)
|
|
CRenderer::CV_r_nightsize = 64;
|
|
else
|
|
if (CRenderer::CV_r_nightsize <= 128)
|
|
CRenderer::CV_r_nightsize = 128;
|
|
else
|
|
if (CRenderer::CV_r_nightsize <= 256)
|
|
CRenderer::CV_r_nightsize = 256;
|
|
else
|
|
if (CRenderer::CV_r_nightsize <= 512)
|
|
CRenderer::CV_r_nightsize = 512;
|
|
|
|
CRenderer::CV_r_nightsize = sLimitSizeByScreenRes(CRenderer::CV_r_nightsize);
|
|
gRenDev->m_RP.m_NightSize = CRenderer::CV_r_nightsize;
|
|
Tex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
int nTexWidth = gRenDev->m_RP.m_NightSize;
|
|
int nTexHeight = gRenDev->m_RP.m_NightSize;
|
|
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
float fMinDist = 0.25f;
|
|
|
|
Tex->m_Flags |= FT_BUILD;
|
|
if (!(Tex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
Tex->m_Width = nTexWidth;
|
|
Tex->m_Height = nTexHeight;
|
|
Tex->m_Flags |= FT_ALLOCATED;
|
|
// Preallocate texture
|
|
AddToHash(Tex->m_Bind, Tex);
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Tex->m_Width, Tex->m_Height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
CreateBufRegion(Tex->m_Width, Tex->m_Height);
|
|
ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL, 0);
|
|
|
|
CCamera tmp_cam = gRenDev->GetCamera();
|
|
m_PrevCamera = tmp_cam;
|
|
//tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
//tmp_cam.Update();
|
|
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
|
|
|
|
eng->SetCamera(tmp_cam,false);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Start Draw scene to texture for night ***\n");
|
|
|
|
gRenDev->m_RP.m_PersFlags |= RBPF_DRAWNIGHTMAP | RBPF_NOCLEARBUF;
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
//int nDrawFlags = DLD_INDOORS | DLD_ADD_LIGHTSOURCES | DLD_ENTITIES | DLD_PARTICLES | DLD_STATIC_OBJECTS | DLD_FAR_SPRITES | DLD_TERRAIN_FULLRES | DLD_TERRAIN_LIGHT;
|
|
//eng->DrawLowDetail(nDrawFlags);
|
|
}
|
|
|
|
void CGLTexMan::StartRefractMap(int Id)
|
|
{
|
|
}
|
|
void CGLTexMan::EndRefractMap()
|
|
{
|
|
}
|
|
|
|
|
|
void CGLTexMan::StartScreenMap(int Id)
|
|
{
|
|
STexPic *tx = gRenDev->m_TexMan->m_Text_EnvScr;
|
|
|
|
// tiago: added
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
int width = m_TempWidth;
|
|
int height = m_TempHeight;
|
|
|
|
if (!(tx->m_Flags & FT_ALLOCATED))
|
|
{
|
|
tx->m_Flags |= FT_ALLOCATED;
|
|
tx->m_Flags2 |= FT2_RECTANGLE;
|
|
tx->m_TargetType = GL_TEXTURE_RECTANGLE_NV;
|
|
tx->m_Width = width;
|
|
tx->m_Height = height;
|
|
SetTexture(tx->m_Bind, eTT_Rectangle);
|
|
glTexImage2D(tx->m_TargetType, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
}
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
gRenDev->m_RP.m_PersFlags |= RBPF_DRAWSCREENMAP;// | RBPF_NOCLEARBUF;
|
|
}
|
|
|
|
void CGLTexMan::EndScreenMap()
|
|
{
|
|
STexPic *tx = gRenDev->m_TexMan->m_Text_EnvScr;
|
|
SetTexture(tx->m_Bind, eTT_Rectangle);
|
|
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, 0, 0, tx->m_Width, tx->m_Height);
|
|
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);
|
|
SetTexture(0, eTT_Rectangle);
|
|
gRenDev->m_RP.m_PersFlags &= ~(RBPF_DRAWSCREENMAP);// | RBPF_NOCLEARBUF);
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
// ===============================================================
|
|
// ScreenTexMap - get screen sized texture, for shared use
|
|
// Last Update: 17/09/2003
|
|
|
|
// prepare screen texture
|
|
void CGLTexMan::StartScreenTexMap(int Id)
|
|
{
|
|
if(gRenDev)
|
|
{
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Begin of StartScreenTexMap ***\n");
|
|
}
|
|
|
|
// for screen texture, only rectangular textures used, if not supported, no screen fx's
|
|
if(!SUPPORTS_GL_NV_texture_rectangle && !SUPPORTS_GL_EXT_texture_rectangle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
STexPic *tx = gRenDev->m_TexMan->m_Text_ScreenMap;
|
|
|
|
// tiago: added
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
int width = m_TempWidth;
|
|
int height = m_TempHeight;
|
|
|
|
// recreate when necessary
|
|
if (!(tx->m_Flags & FT_ALLOCATED))
|
|
{
|
|
tx->m_Flags |= FT_ALLOCATED;
|
|
tx->m_Flags2 |= FT2_RECTANGLE;
|
|
|
|
|
|
if(SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
|
|
tx->m_TargetType = GL_TEXTURE_RECTANGLE_NV;
|
|
|
|
tx->m_Width = width;
|
|
tx->m_Height = height;
|
|
SetTexture(tx->m_Bind, eTT_Rectangle);
|
|
glTexImage2D(tx->m_TargetType, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
}
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
gRenDev->m_RP.m_PersFlags |= RBPF_DRAWSCREENTEXMAP; //| RBPF_NOCLEARBUF;
|
|
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
//glClear(GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
// get screen texture
|
|
void CGLTexMan::EndScreenTexMap()
|
|
{
|
|
if(gRenDev)
|
|
{
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** End of StartScreenTexMap ***\n");
|
|
}
|
|
|
|
// for screen texture, only rectangular textures used, if not supported, no screen fx's
|
|
if(!SUPPORTS_GL_NV_texture_rectangle && !SUPPORTS_GL_EXT_texture_rectangle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
STexPic *tx = gRenDev->m_TexMan->m_Text_ScreenMap;
|
|
SetTexture(tx->m_Bind, eTT_Rectangle);
|
|
|
|
unsigned int nTargetType;
|
|
|
|
if (SUPPORTS_GL_NV_texture_rectangle || SUPPORTS_GL_EXT_texture_rectangle)
|
|
nTargetType=GL_TEXTURE_RECTANGLE_NV;
|
|
|
|
glCopyTexSubImage2D(nTargetType, 0, 0, 0, 0, 0, tx->m_Width, tx->m_Height);
|
|
glTexParameteri(nTargetType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(nTargetType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(nTargetType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(nTargetType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
SetTexture(0, eTT_Rectangle);
|
|
|
|
gRenDev->m_RP.m_PersFlags &= ~(RBPF_DRAWSCREENTEXMAP); // | RBPF_NOCLEARBUF);
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
//==================================================================================
|
|
|
|
void CGLTexMan::DrawToTextureForRainMap(int Id)
|
|
{
|
|
if (!iSystem)
|
|
return;
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
|
|
STexPic *Tex = gRenDev->m_TexMan->m_Text_RainMap;
|
|
if (Tex->m_Flags & FT_BUILD)
|
|
return;
|
|
|
|
if (CRenderer::CV_r_rainmapsize != gRenDev->m_RP.m_RainMapSize)
|
|
{
|
|
if (CRenderer::CV_r_rainmapsize <= 64)
|
|
CRenderer::CV_r_rainmapsize = 64;
|
|
else
|
|
if (CRenderer::CV_r_rainmapsize <= 128)
|
|
CRenderer::CV_r_rainmapsize = 128;
|
|
else
|
|
if (CRenderer::CV_r_rainmapsize <= 256)
|
|
CRenderer::CV_r_rainmapsize = 256;
|
|
else
|
|
if (CRenderer::CV_r_rainmapsize <= 512)
|
|
CRenderer::CV_r_rainmapsize = 512;
|
|
|
|
CRenderer::CV_r_rainmapsize = sLimitSizeByScreenRes(CRenderer::CV_r_rainmapsize);
|
|
gRenDev->m_RP.m_RainMapSize = CRenderer::CV_r_rainmapsize;
|
|
Tex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
int nTexWidth = gRenDev->m_RP.m_RainMapSize;
|
|
int nTexHeight = gRenDev->m_RP.m_RainMapSize;
|
|
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
float fMinDist = 0.25f;
|
|
|
|
Tex->m_Flags |= FT_BUILD;
|
|
if (!(Tex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
Tex->m_Width = nTexWidth;
|
|
Tex->m_Height = nTexHeight;
|
|
Tex->m_Flags |= FT_ALLOCATED;
|
|
// Preallocate texture
|
|
AddToHash(Tex->m_Bind, Tex);
|
|
SetTexture(Tex->m_Bind, eTT_Base);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Tex->m_Width, Tex->m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
SetTexture(0, eTT_Base);
|
|
}
|
|
|
|
CreateBufRegion(Tex->m_Width, Tex->m_Height);
|
|
ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL, 0);
|
|
|
|
//gRenDev->EF_SaveDLights();
|
|
|
|
CCamera tmp_cam = gRenDev->GetCamera();
|
|
CCamera prevCamera = tmp_cam;
|
|
//tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
//tmp_cam.Update();
|
|
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
|
|
gRenDev->EF_PushFog();
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
eng->SetCamera(tmp_cam,false);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Draw scene to texture for rainmap ***\n");
|
|
|
|
eng->DrawRain();
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (DrawToTextureForRainMap)\n");
|
|
|
|
SetTexture(Tex->m_Bind, 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_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Tex->m_Width, Tex->m_Height);
|
|
|
|
gRenDev->SetCamera(prevCamera);
|
|
iSystem->SetViewCamera(prevCamera);
|
|
/*
|
|
{
|
|
byte *pic = new byte [nTexWidth * nTexHeight * 4];
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
::WriteTGA(pic,nTexWidth,nTexHeight,"RainMapAlpha.tga", 32);
|
|
delete [] pic;
|
|
}
|
|
*/
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
|
|
SetTexture(0, eTT_Base);
|
|
|
|
//ClearBuffer(Tex->m_Width, Tex->m_Height, true, NULL,0);
|
|
|
|
Tex->m_Flags &= ~FT_BUILD;
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
gRenDev->EF_PopFog();
|
|
|
|
gRenDev->ResetToDefault();
|
|
//gRenDev->EF_RestoreDLights();
|
|
}
|
|
|
|
//==================================================================================
|
|
extern int nTexSize;
|
|
extern int nFrameTexSize;
|
|
|
|
int TexCallback( const VOID* arg1, const VOID* arg2 )
|
|
{
|
|
STexPic **pi1 = (STexPic **)arg1;
|
|
STexPic **pi2 = (STexPic **)arg2;
|
|
STexPic *ti1 = *pi1;
|
|
STexPic *ti2 = *pi2;
|
|
if (ti1->m_Size > ti2->m_Size)
|
|
return -1;
|
|
if (ti1->m_Size < ti2->m_Size)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void CGLTexMan::Update()
|
|
{
|
|
CGLRenderer *rd = gcpOGL;
|
|
int i;
|
|
char buf[256]="";
|
|
|
|
CheckTexLimits(NULL);
|
|
|
|
if (CRenderer::CV_r_texresolution != m_CurTexResolution || CRenderer::CV_r_texbumpresolution != m_CurTexBumpResolution || CRenderer::CV_r_texquality != m_CurTexQuality || CRenderer::CV_r_texbumpquality != m_CurTexBumpQuality || CRenderer::CV_r_texskyquality != m_CurTexSkyQuality || CRenderer::CV_r_texskyresolution != m_CurTexSkyResolution || CRenderer::CV_r_texmaxsize != m_CurTexMaxSize || CRenderer::CV_r_texminsize != m_CurTexMinSize)
|
|
{
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
STexPic *tp = m_Textures[i];
|
|
if (!tp || !tp->m_bBusy)
|
|
continue;
|
|
if (!(tp->m_Flags2 & FT2_WASLOADED))
|
|
continue;
|
|
if (tp->m_Flags & FT_NOREMOVE)
|
|
continue;
|
|
if (tp->m_eTT == eTT_Cubemap)
|
|
{
|
|
//if (tp->m_CubeSide > 0)
|
|
continue;
|
|
if (CRenderer::CV_r_texmaxsize != m_CurTexMaxSize || CRenderer::CV_r_texminsize != m_CurTexMinSize || CRenderer::CV_r_texresolution != m_CurTexResolution || CRenderer::CV_r_texquality != m_CurTexQuality)
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), tp->m_Flags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
else
|
|
if (tp->m_eTT == eTT_Bumpmap || tp->m_eTT == eTT_DSDTBump)
|
|
{
|
|
if (CRenderer::CV_r_texmaxsize != m_CurTexMaxSize || CRenderer::CV_r_texminsize != m_CurTexMinSize || CRenderer::CV_r_texbumpresolution != m_CurTexBumpResolution || CRenderer::CV_r_texbumpquality != m_CurTexBumpQuality )
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), tp->m_Flags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (tp->m_Flags & FT_SKY)
|
|
{
|
|
if (CRenderer::CV_r_texmaxsize != m_CurTexMaxSize || CRenderer::CV_r_texminsize != m_CurTexMinSize || CRenderer::CV_r_texskyresolution != m_CurTexSkyResolution || CRenderer::CV_r_texskyquality != m_CurTexSkyQuality)
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), tp->m_Flags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CRenderer::CV_r_texmaxsize != m_CurTexMaxSize || CRenderer::CV_r_texminsize != m_CurTexMinSize || CRenderer::CV_r_texresolution != m_CurTexResolution || CRenderer::CV_r_texquality != m_CurTexQuality)
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), tp->m_Flags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_CurTexResolution = CRenderer::CV_r_texresolution;
|
|
m_CurTexBumpResolution = CRenderer::CV_r_texbumpresolution;
|
|
m_CurTexQuality = CRenderer::CV_r_texquality;
|
|
m_CurTexBumpQuality = CRenderer::CV_r_texbumpquality;
|
|
m_CurTexSkyResolution = CRenderer::CV_r_texskyresolution;
|
|
m_CurTexSkyQuality = CRenderer::CV_r_texskyquality;
|
|
m_CurTexMaxSize = CRenderer::CV_r_texmaxsize;
|
|
m_CurTexMinSize = CRenderer::CV_r_texminsize;
|
|
}
|
|
|
|
if (CRenderer::CV_r_logusedtextures == 1 || CRenderer::CV_r_logusedtextures == 3 || CRenderer::CV_r_logusedtextures == 4 || CRenderer::CV_r_logusedtextures == 5)
|
|
{
|
|
FILE *fp = NULL;
|
|
TArray<STexPic *> Texs;
|
|
int Size = 0;
|
|
int PartSize = 0;
|
|
|
|
static char *sTexType[] =
|
|
{
|
|
"Base","Cubemap","AutoCubemap","Bump","DSDTBump","Rectangle"
|
|
};
|
|
static char *sTexFormat[] =
|
|
{
|
|
"Unknown","Index8","HSV","0888","8888","RGBA","8000","0565","0555","4444","1555","DXT1","DXT3","DXT5","SIGNED_HILO16","SIGNED_HILO8","SIGNED_RGB8","RGB8","DSDT_MAG","DSDT","0088"
|
|
};
|
|
|
|
if (CRenderer::CV_r_logusedtextures == 1 || CRenderer::CV_r_logusedtextures == 3 || CRenderer::CV_r_logusedtextures == 5)
|
|
{
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
if (CRenderer::CV_r_logusedtextures == 3 && m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind == gRenDev->m_TexMan->m_Text_NoTexture->m_Bind)
|
|
{
|
|
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
|
|
Texs.AddElem(m_Textures[i]);
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_logusedtextures == 1 && m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && (m_Textures[i]->m_Flags2 & FT2_WASLOADED) && !(m_Textures[i]->m_Flags2 & FT2_WASUNLOADED))
|
|
{
|
|
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
|
|
Texs.AddElem(m_Textures[i]);
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_logusedtextures == 5 && m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && !(m_Textures[i]->m_Flags2 & FT2_WASLOADED))
|
|
{
|
|
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
|
|
Texs.AddElem(m_Textures[i]);
|
|
}
|
|
}
|
|
if (CRenderer::CV_r_logusedtextures == 3)
|
|
fp = fxopen("MissingTextures.txt", "w");
|
|
else
|
|
if (CRenderer::CV_r_logusedtextures == 1)
|
|
fp = fxopen("UsedTextures.txt", "w");
|
|
else
|
|
fp = fxopen("UsedFuncTextures.txt", "w");
|
|
fprintf(fp, "*** All loaded textures: ***\n");
|
|
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
fprintf(fp, "%d\t\tType: %s\t\tFormat: %s\t\t(%s)\n", Texs[i]->m_Size, sTexType[Texs[i]->m_eTT], sTexFormat[Texs[i]->m_ETF], *Texs[i]->m_SearchName);
|
|
Size += Texs[i]->m_Size;
|
|
PartSize += Texs[i]->m_LoadedSize;
|
|
}
|
|
fprintf(fp, "*** Total Size: %d\n\n", Size, PartSize, PartSize);
|
|
|
|
Texs.Free();
|
|
}
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
if (m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && m_Textures[i]->m_AccessFrame == rd->GetFrameID())
|
|
{
|
|
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
|
|
Texs.AddElem(m_Textures[i]);
|
|
}
|
|
}
|
|
if (fp)
|
|
fprintf(fp, "\n\n*** Textures used in current frame: ***\n");
|
|
else
|
|
rd->TextToScreenColor(4,13, 1,1,0,1, "*** Textures used in current frame: ***");
|
|
int nY = 17;
|
|
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
|
|
Size = 0;
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
if (fp)
|
|
fprintf(fp, "%.3fKb\t\tType: %s\t\tFormat: %s\t\t(%s)\n", Texs[i]->m_Size/1024.0f, sTexType[Texs[i]->m_eTT], sTexFormat[Texs[i]->m_ETF], Texs[i]->m_SearchName.c_str());
|
|
else
|
|
{
|
|
sprintf(buf, "%.3fKb Type: %s Format: %s (%s)", Texs[i]->m_Size/1024.0f, sTexType[Texs[i]->m_eTT], sTexFormat[Texs[i]->m_ETF], Texs[i]->m_SearchName.c_str());
|
|
rd->TextToScreenColor(4,nY, 0,1,0,1, buf);
|
|
nY += 3;
|
|
}
|
|
Size += Texs[i]->m_Size;
|
|
}
|
|
if (fp)
|
|
{
|
|
fprintf(fp, "*** Total Size: %.3fMb\n\n", Size/(1024.0f*1024.0f));
|
|
fclose (fp);
|
|
}
|
|
else
|
|
{
|
|
sprintf(buf, "*** Total Size: %.3fMb", Size/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,nY+1, 0,1,1,1, buf);
|
|
}
|
|
|
|
if (CRenderer::CV_r_logusedtextures != 4)
|
|
CRenderer::CV_r_logusedtextures = 0;
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_logusedtextures == 2)
|
|
{
|
|
//char *str = GetTexturesStatusText();
|
|
|
|
TArray<STexPic *> Texs;
|
|
TArray<STexPic *> TexsNM;
|
|
int i;
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
if (m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind)
|
|
{
|
|
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
|
|
{
|
|
/*for (int nn = 0; nn<sTestStr.Num(); nn++)
|
|
{
|
|
if (sTestStr[nn] == m_Textures[i])
|
|
break;
|
|
}
|
|
if (nn == sTestStr.Num())
|
|
{
|
|
int nnn = 0;
|
|
}*/
|
|
Texs.AddElem(m_Textures[i]);
|
|
if (m_Textures[i]->m_eTT == eTT_Bumpmap || m_Textures[i]->m_eTT == eTT_DSDTBump)
|
|
TexsNM.AddElem(m_Textures[i]);
|
|
}
|
|
}
|
|
}
|
|
int SizeNOTO = 0;
|
|
int nNOTO = 0;
|
|
for (i=0; i<TX_FIRSTBIND; i++)
|
|
{
|
|
if (BindSizes[i])
|
|
{
|
|
STexPic *tp = GetByID(i);
|
|
if (!tp)
|
|
{
|
|
nNOTO++;
|
|
SizeNOTO += BindSizes[i];
|
|
}
|
|
}
|
|
}
|
|
/*for (int nn = 0; nn<sTestTx.Num(); nn++)
|
|
{
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
if (sTestTx[nn] == Texs[i])
|
|
break;
|
|
}
|
|
if (i == Texs.Num())
|
|
{
|
|
int nnn = 0;
|
|
}
|
|
}*/
|
|
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
|
|
int AllSize = 0;
|
|
int AllSizeNM = 0;
|
|
int Size = 0;
|
|
int PartSize = 0;
|
|
int NonStrSize = 0;
|
|
int SizeNM = 0;
|
|
int PartSizeNM = 0;
|
|
int nLoaded = 0;
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
AllSize += Texs[i]->m_Size;
|
|
if (!Texs[i]->IsStreamed())
|
|
NonStrSize += Texs[i]->m_Size;
|
|
if (!(Texs[i]->m_Flags2 & FT2_WASUNLOADED))
|
|
{
|
|
nLoaded++;
|
|
Size += Texs[i]->m_Size;
|
|
if (Texs[i]->m_LoadedSize)
|
|
PartSize += Texs[i]->m_LoadedSize;
|
|
else
|
|
PartSize += Texs[i]->m_Size;
|
|
}
|
|
}
|
|
for (i=0; i<TexsNM.Num(); i++)
|
|
{
|
|
AllSizeNM += Texs[i]->m_Size;
|
|
if (!(Texs[i]->m_Flags2 & FT2_WASUNLOADED))
|
|
{
|
|
SizeNM += TexsNM[i]->m_Size;
|
|
if (TexsNM[i]->m_LoadedSize)
|
|
PartSizeNM += TexsNM[i]->m_LoadedSize;
|
|
else
|
|
PartSizeNM += TexsNM[i]->m_Size;
|
|
}
|
|
}
|
|
sprintf(buf, "All API's textures: FullSize: %.3fMb (nNoTO: %d, SizeNoTO: %.3fMb)", nTexSize/(1024.0f*1024.0f), nNOTO, SizeNOTO/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,10, 1,1,0,1, buf);
|
|
sprintf(buf, "All texture objects: %d (Size: %.3fMb, NonStreamed: %.3fMb)", Texs.Num(), AllSize/(1024.0f*1024.0f), NonStrSize/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,13, 1,1,0,1, buf);
|
|
sprintf(buf, "All loaded texture objects: %d (All MIPS: %.3fMb, Loaded MIPS: %.3fMb)", nLoaded, Size/(1024.0f*1024.0f), PartSize/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,16, 1,1,0,1, buf);
|
|
sprintf(buf, "All Normal Maps: %d (FullSize: %.3fMb, All MIPS: %.3fMb, Loaded MIPS: %.3fMb)", TexsNM.Num(), AllSizeNM/(1024.0f*1024.0f), SizeNM/(1024.0f*1024.0f), PartSizeNM/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,19, 1,1,0,1, buf);
|
|
|
|
Texs.Free();
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
if (m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && m_Textures[i]->m_AccessFrame == rd->GetFrameID())
|
|
{
|
|
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
|
|
Texs.AddElem(m_Textures[i]);
|
|
}
|
|
}
|
|
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
|
|
Size = 0;
|
|
PartSize = 0;
|
|
NonStrSize = 0;
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
Size += Texs[i]->m_Size;
|
|
if (Texs[i]->m_LoadedSize)
|
|
PartSize += Texs[i]->m_LoadedSize;
|
|
else
|
|
PartSize += Texs[i]->m_Size;
|
|
if (!Texs[i]->IsStreamed())
|
|
NonStrSize += Texs[i]->m_Size;
|
|
}
|
|
sprintf(buf, "Current tex. objects: %d (Size: %.3fMb, Loaded: %.3f, NonStreamed: %.3f)", Texs.Num(), Size/(1024.0f*1024.0f), PartSize/(1024.0f*1024.0f), NonStrSize/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,24, 1,0,0,1, buf);
|
|
int n = 0;
|
|
Size = 0;
|
|
for (i=0; i<16384; i++)
|
|
{
|
|
if (BindFrame[i] == rd->GetFrameID())
|
|
{
|
|
if (i < TX_FIRSTBIND)
|
|
Size += BindSizes[i];
|
|
n++;
|
|
}
|
|
}
|
|
sprintf(buf, "Current API textures: %d (Size: %.3f, SizeNoManaged: %.3f)", n, nFrameTexSize/(1024.0f*1024.0f), Size/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,27, 1,0,0,1, buf);
|
|
|
|
{ // count shadow map memory
|
|
float nShadowMapSize = 0;
|
|
int nShadowMapCount= 0;
|
|
for(int i=0; i<MAX_DYNAMIC_SHADOW_MAPS_COUNT; i++)
|
|
{
|
|
if(((CGLRenderer*)rd)->m_ShadowTexIDBuffer[i].nTexId)
|
|
{
|
|
nShadowMapSize += ((CGLRenderer*)rd)->m_ShadowTexIDBuffer[i].nTexSize*((CGLRenderer*)rd)->m_ShadowTexIDBuffer[i].nTexSize*3;
|
|
nShadowMapCount++;
|
|
}
|
|
}
|
|
|
|
sprintf(buf, "Allocated shadow maps: %d (%.2f mb)", nShadowMapCount, nShadowMapSize/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,30, 1,0,0,1, buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
//==================================================================================
|
|
|
|
STexPic *CGLRenderer::EF_MakePhongTexture(int Exp)
|
|
{
|
|
char name[128];
|
|
|
|
sprintf(name, "$Phong_%d", Exp);
|
|
STexPic *tp = m_TexMan->LoadTexture(name, 0, 0, eTT_Base);
|
|
if (tp->m_Flags & FT_ALLOCATED)
|
|
return tp;
|
|
tp->m_Flags |= FT_ALLOCATED;
|
|
tp->m_Bind = TX_FIRSTBIND + tp->m_Id;
|
|
//sTestStr.AddElem(tp);
|
|
tp->Set();
|
|
tp->m_Flags &= ~FT_NOTFOUND;
|
|
CGLTexMan *tm = (CGLTexMan *)m_TexMan;
|
|
tm->MakePhongLookupTexture((float)Exp, tp);
|
|
m_TexMan->SetTexture(0, eTT_Base);
|
|
|
|
return tp;
|
|
}
|
|
|
|
bool CGLRenderer::EF_SetLightHole(Vec3d vPos, Vec3d vNormal, int idTex, float fScale, bool bAdditive)
|
|
{
|
|
static const GLenum cubefaces[6] =
|
|
{
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,
|
|
};
|
|
|
|
assert(idTex);
|
|
|
|
//ITexPic *pi = EF_LoadTexture("ricochet32b", 0, 0, eTT_Base);
|
|
//idTex = pi->GetTextureID();
|
|
|
|
ResetToDefault();
|
|
|
|
STexPic *Pic = m_TexMan->GetByID(idTex);
|
|
if (!Pic)
|
|
Pic = gRenDev->m_TexMan->m_Text_White;
|
|
assert(Pic->m_Flags2 & FT2_WASLOADED);
|
|
//Pic = (STexPic *)EF_LoadTexture("textures/decal/default", 0, 0, eTT_Base);
|
|
|
|
/*static bool bFreeze;
|
|
static float fLastTime;
|
|
static Vec3d sPos;
|
|
bool bGo = false;
|
|
if ((GetAsyncKeyState('F') & 0x8000))
|
|
bFreeze = 1;
|
|
else
|
|
if ((GetAsyncKeyState('U') & 0x8000))
|
|
bFreeze = 0;
|
|
if ((GetAsyncKeyState('G') & 0x8000) && m_RP.m_RealTime-fLastTime > 1.0f)
|
|
{
|
|
fLastTime = m_RP.m_RealTime;
|
|
bGo = true;
|
|
}
|
|
if (!bFreeze)
|
|
sPos = GetCamera().GetPos();
|
|
SetMaterialColor(1,1,1,1);
|
|
DrawBall(sPos[0], sPos[1], sPos[2], 0.05f);
|
|
|
|
if (!bGo)
|
|
return false;
|
|
|
|
vPos = sPos;*/
|
|
|
|
// Looking for opposite light source
|
|
int i;
|
|
//vNormal = Vec3d(0,1,0);
|
|
for (i=0; i<m_RP.m_DLights[SRendItem::m_RecurseLevel].Num(); i++)
|
|
{
|
|
CDLight *dl = m_RP.m_DLights[SRendItem::m_RecurseLevel][i];
|
|
if (!dl || !dl->m_pLightImage)
|
|
continue;
|
|
Vec3d p = vPos - dl->m_Origin;
|
|
p.Normalize();
|
|
float d = p.Dot(vNormal);
|
|
if (d >= 0.5f)
|
|
break;
|
|
}
|
|
if (i == m_RP.m_DLights[SRendItem::m_RecurseLevel].Num())
|
|
return false;
|
|
|
|
CDLight *pLight = m_RP.m_DLights[SRendItem::m_RecurseLevel][i];
|
|
|
|
assert(pLight);
|
|
|
|
/*if ((GetAsyncKeyState('R') & 0x8000) && m_RP.m_RealTime-fLastTime > 1.0f)
|
|
{
|
|
fLastTime = m_RP.m_RealTime;
|
|
STexPic *pImage = (STexPic *)pLight->m_pLightImage;
|
|
char name[128];
|
|
strcpy(name, *pImage->m_FullName);
|
|
pImage->Release(false);
|
|
pLight->m_pLightImage = EF_LoadTexture(name, FT_CLAMP, FT2_FORCECUBEMAP | FT2_NODXT, eTT_Cubemap);
|
|
bGo = false;
|
|
}*/
|
|
|
|
float frustMatr[16];
|
|
float viewMatr[16];
|
|
|
|
Vec3d PosL = pLight->m_Origin;
|
|
Vec3d TargL = pLight->m_Origin + pLight->m_Orientation.m_vForward;
|
|
//pLight->m_fLightFrustumAngle = 45.0f;
|
|
makeProjectionMatrix( pLight->m_fLightFrustumAngle*2, 1, 1, 99999.0f, frustMatr);
|
|
SGLFuncs::gluLookAt( PosL.x, PosL.y, PosL.z, TargL.x, TargL.y, TargL.z, pLight->m_Orientation.m_vUp[0], pLight->m_Orientation.m_vUp[1], pLight->m_Orientation.m_vUp[2], viewMatr);
|
|
|
|
const int vp[4] = {0,0,1,1};
|
|
float px, py, pz;
|
|
SGLFuncs::gluProject(vPos.x,vPos.y,vPos.z, viewMatr, frustMatr, vp, &px, &py, &pz);
|
|
int Side = 0;
|
|
if (px>=0 && px<=1.0f && py>=0 && py<=1.0f)
|
|
{
|
|
STexPic *pImage = (STexPic *)((ITexPic*)pLight->m_pLightImage);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0.0, m_width, 0.0, m_height, -9999.0, 9999.0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
Vec3d crd[4];
|
|
switch(Side)
|
|
{
|
|
case 0: //posx
|
|
crd[0] = Vec3d(1,1,1);
|
|
crd[1] = Vec3d(1,-1,1);
|
|
crd[2] = Vec3d(1,-1,-1);
|
|
crd[3] = Vec3d(1,1,-1);
|
|
break;
|
|
case 1: //negx
|
|
crd[0] = Vec3d(-1,1,1);
|
|
crd[1] = Vec3d(-1,-1,1);
|
|
crd[2] = Vec3d(-1,-1,-1);
|
|
crd[3] = Vec3d(-1,1,-1);
|
|
break;
|
|
case 2: //posy
|
|
crd[0] = Vec3d(1,1,1);
|
|
crd[1] = Vec3d(-1,1,1);
|
|
crd[2] = Vec3d(-1,1,-1);
|
|
crd[3] = Vec3d(1,1,-1);
|
|
break;
|
|
case 3: //negy
|
|
crd[0] = Vec3d(1,-1,1);
|
|
crd[1] = Vec3d(-1,-1,1);
|
|
crd[2] = Vec3d(-1,-1,-1);
|
|
crd[3] = Vec3d(1,-1,-1);
|
|
break;
|
|
case 4: //posz
|
|
crd[0] = Vec3d(1,1,1);
|
|
crd[1] = Vec3d(-1,1,1);
|
|
crd[2] = Vec3d(-1,-1,1);
|
|
crd[3] = Vec3d(1,-1,1);
|
|
break;
|
|
case 5: //negz
|
|
crd[0] = Vec3d(1,1,-1);
|
|
crd[1] = Vec3d(-1,1,-1);
|
|
crd[2] = Vec3d(-1,-1,-1);
|
|
crd[3] = Vec3d(1,-1,-1);
|
|
break;
|
|
}
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_STENCIL_TEST);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDepthMask(1);
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
pImage->Set();
|
|
glEnable(pImage->m_TargetType);
|
|
|
|
float fWdt = (float)pImage->m_Width;
|
|
float fHgt = (float)pImage->m_Height;
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glColor3f(1,1,1);
|
|
|
|
glTexCoord3f(crd[0][0], crd[0][1], crd[0][2]);
|
|
glVertex3f(0.0f, 0.0f, 0.0f); // Top Left
|
|
|
|
glTexCoord3f(crd[1][0], crd[1][1], crd[1][2]);
|
|
glVertex3f(0.0f, fHgt, 0.0f); // Bottom Left
|
|
|
|
glTexCoord3f(crd[2][0], crd[2][1], crd[2][2]);
|
|
glVertex3f(fWdt, fHgt, 0.0f); // Bottom Right
|
|
|
|
glTexCoord3f(crd[3][0], crd[3][1], crd[3][2]);
|
|
glVertex3f(fWdt, 0.0f, 0.0f); // Top Right
|
|
|
|
glEnd();
|
|
|
|
if (pImage->m_eTT == eTT_Cubemap)
|
|
glDisable(pImage->m_TargetType);
|
|
|
|
float posx = (1.0f-px) * (float)pImage->m_Width;
|
|
float posy = (1.0f-py) * (float)pImage->m_Height;
|
|
|
|
pImage = (STexPic *)Pic;
|
|
pImage->Set();
|
|
float fs = (float)fWdt / 256.0f;
|
|
float fSize = fScale / 2.0f * (float)pImage->m_Width * fs;
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_ONE, GL_ONE);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
|
glVertex3f(posx-fSize, posy-fSize, 0.0f);
|
|
|
|
glTexCoord2f(0, 1);
|
|
glVertex3f(posx-fSize, posy+fSize, 0.0f);
|
|
|
|
glTexCoord2f(1, 1);
|
|
glVertex3f(posx+fSize, posy+fSize, 0.0f);
|
|
|
|
glTexCoord2f(1, 0);
|
|
glVertex3f(posx+fSize, posy-fSize, 0.0f);
|
|
|
|
glEnd();
|
|
|
|
pImage = (STexPic *)((ITexPic*)pLight->m_pLightImage);
|
|
pImage->Set();
|
|
|
|
glCopyTexSubImage2D(cubefaces[Side], 0, 0, 0, 0, 0, pImage->m_Width, pImage->m_Height);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
if (pImage->m_eTT == eTT_Cubemap)
|
|
glDisable(pImage->m_TargetType);
|
|
glDisable(GL_BLEND);
|
|
|
|
m_TexMan->SetTexture(0, eTT_Cubemap);
|
|
//pImage->SaveJPG("LightCube");
|
|
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
float CGLTexMan::CalcFogVal(float fi, float fj)
|
|
{
|
|
float fDelta = fabsf(fj - fi);
|
|
if (fj > 0 && fi > 0)
|
|
return 0;
|
|
float fThr = -8;
|
|
if (fj < fThr && fi < fThr)
|
|
return 1.0f;
|
|
float f1, f2, ff;
|
|
if (fj > 0)
|
|
ff = fj;
|
|
else
|
|
if (fi > 0)
|
|
ff = fi;
|
|
else
|
|
ff = 0;
|
|
if (fi > fj)
|
|
{
|
|
f1 = fi;
|
|
f2 = fj;
|
|
}
|
|
else
|
|
{
|
|
f1 = fj;
|
|
f2 = fi;
|
|
}
|
|
if (f1 > 0)
|
|
f1 = 0;
|
|
if (f2 < fThr)
|
|
f2 = fThr;
|
|
fThr = 1.0f / 8.0f;
|
|
if (fDelta == 0)
|
|
return -(fThr * fi);
|
|
float fFog = (1.0f - ((f2 + f1) * fThr * -0.5f)) * (f1 - f2);
|
|
ff = ((fDelta - ff) - fFog) / fDelta;
|
|
float fMin = min(fi, fj) / -30.0f;
|
|
if (fMin >= 1.0f)
|
|
return 1;
|
|
return (1.0f - fMin) * ff + fMin;
|
|
}
|
|
|
|
void CGLTexMan::GenerateFogMaps()
|
|
{
|
|
int i, j;
|
|
{
|
|
float fdata[256];
|
|
byte Data1[128][128][4];
|
|
float f = 1.0f;
|
|
for (i=0; i<256; i++)
|
|
{
|
|
fdata[i] = f;
|
|
f *= 0.982f;
|
|
}
|
|
fdata[0] = 0;
|
|
fdata[255] = 0;
|
|
for (i=0; i<128; i++)
|
|
{
|
|
int ni = i - 64;
|
|
for (j=0; j<128; j++)
|
|
{
|
|
int nj = j - 64;
|
|
float m = (float)(nj*nj + ni*ni);
|
|
float fsq = m ? 1.0f / cry_sqrtf(m) : 1000000; // @todo: fix devide by zero !!!
|
|
int iIndexF = (int)((fsq * m) / 63.0f * 255.0f);
|
|
iIndexF = CLAMP(iIndexF, 0, 255);
|
|
int iFog = (int)((1.0f - fdata[iIndexF]) * 255.0f);
|
|
if (!i || i==127 || !j || j==127)
|
|
iFog = 255;
|
|
Data1[j][i][0] = Data1[j][i][1] = Data1[j][i][2] = 255;
|
|
Data1[j][i][3] = (byte)iFog;
|
|
}
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Fog = CreateTexture("$Fog", 128, 128, 1, FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT, &Data1[0][0][0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
/*byte Data2[64][64][4];
|
|
gcpOGL->EF_InitFogTables();
|
|
for (i=0; i<64; i++)
|
|
{
|
|
for (j=0; j<64; j++)
|
|
{
|
|
//float fFog = CalcFogVal((float)(i-32), (float)(j-32));
|
|
|
|
float fi = (float)i-63-10;
|
|
float fj = (float)j-32;
|
|
float fifi = fi/32.0f;
|
|
fifi *= fifi;
|
|
int nInd = (int)(((-fj/8.0f) * fifi) * 255.0f);
|
|
nInd = Clamp(nInd, 0, 255);
|
|
float fFog = SEvalFuncs::m_tFogFloats[nInd];
|
|
int iFog = Clamp(int(fFog*255.0f), 0, 255);
|
|
Data2[j][i][0] = Data2[j][i][1] = Data2[j][i][2] = 255;
|
|
Data2[j][i][3] = (byte)iFog;
|
|
}
|
|
}*/
|
|
|
|
//gRenDev->m_TexMan->m_Text_Fog_Enter = DownloadTexture("(FogEnter)", 64, 64, FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT, &Data2[0][0][0], eTT_Base, 0, NULL, 0, eTF_8888);
|
|
//gRenDev->m_TexMan->m_Text_Fog_Enter->SaveTGA("FogEnter.tga", false);
|
|
gRenDev->m_TexMan->m_Text_Fog_Enter = LoadTexture("Textures/FogEnter", FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT);
|
|
}
|
|
}
|
|
|
|
void CGLTexMan::GenerateFlareMap()
|
|
{
|
|
int i, j;
|
|
|
|
byte data[4][32][4];
|
|
for (i=0; i<32; i++)
|
|
{
|
|
float f = 1.0f - ((fabsf((float)i - 15.5f) - 0.5f) / 16.0f);
|
|
int n = (int)(f*f*255.0f);
|
|
for (j=0; j<4; j++)
|
|
{
|
|
byte b = n;
|
|
if (n < 0)
|
|
b = 0;
|
|
else
|
|
if (n > 255)
|
|
b = 255;
|
|
data[j][i][0] = b;
|
|
data[j][i][1] = b;
|
|
data[j][i][2] = b;
|
|
data[j][i][3] = 255;
|
|
}
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Flare = CreateTexture("$Flare", 32, 4, 1, FT_CLAMP | FT_NOREMOVE, FT2_NODXT, &data[0][0][0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
}
|
|
|
|
void CGLTexMan::GenerateGhostMap()
|
|
{
|
|
}
|
|
|
|
#define D3DCOLOR_ARGB(a,r,g,b) \
|
|
((DWORD)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
|
|
#define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b)
|
|
|
|
void CGLTexMan::GenerateDepthLookup()
|
|
{
|
|
int i;
|
|
|
|
DWORD data[2048];
|
|
DWORD* pMap = data;
|
|
for (i=0; i<2048; i++)
|
|
{
|
|
*pMap++ = D3DCOLOR_RGBA(i&0xFF, (i&0xFF00)>>3, 0, 0 );
|
|
}
|
|
gRenDev->m_TexMan->m_Text_DepthLookup = CreateTexture("$DepthMap", 2048, 1, 1, FT_CLAMP | FT_NOREMOVE | FT_NOMIPS | FT_PROJECTED, FT2_NODXT, (byte *)&data[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
DWORD data2[4][4];
|
|
pMap = &data2[0][0];
|
|
for (i=0; i<4*4; i++)
|
|
{
|
|
*pMap++ = D3DCOLOR_RGBA(0xff, 0xe0, 0, 0 );
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Depth = CreateTexture("$Depth", 4, 4, 1, FT_CLAMP | FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS, FT2_NODXT, (byte *)&data2[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
pMap = &data2[0][0];
|
|
for (i=0; i<4*4; i++)
|
|
{
|
|
*pMap++ = D3DCOLOR_RGBA(0xff, 0xff, 0xff, 0 );
|
|
}
|
|
gRenDev->m_TexMan->m_Text_WhiteShadow = CreateTexture("$WhiteShadow", 4, 4, 1, FT_CLAMP | FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS, FT2_NODXT, (byte *)&data2[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
byte data3[256];
|
|
byte *pbMap = &data3[0];
|
|
for (i=0; i<256; i++)
|
|
{
|
|
*pbMap++ = i;
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Gradient = CreateTexture("$AlphaGradient", 256, 1, 1, FT_CLAMP | FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS, FT2_NODXT, (byte *)&data3[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8000);
|
|
}
|
|
|
|
void CGLTexMan::GenerateFuncTextures()
|
|
{
|
|
if (gRenDev->GetFeatures() & RFT_BUMP)
|
|
{
|
|
m_Text_NormalizeCMap = LoadTexture("$NormalizeCMap", FT_NOREMOVE | FT_NOMIPS, FT2_NODXT, eTT_Cubemap, -1.0f, -1.0f, TO_NORMALIZE_CUBE_MAP);
|
|
//SNormalizeVector norm;
|
|
glEnable(GL_TEXTURE_CUBE_MAP_EXT);
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, TO_NORMALIZE_CUBE_MAP);
|
|
//sTestStr.AddElem(m_Text_NormalizeCMap);
|
|
//MakeCubeMap<SNormalizeVector>(norm, GL_RGB8, 256, false, m_Text_NormalizeCMap);
|
|
MakeNormalizeVectorCubeMap(128, gRenDev->m_TexMan->m_Text_NormalizeCMap);
|
|
glDisable(GL_TEXTURE_CUBE_MAP_EXT);
|
|
|
|
gRenDev->m_TexMan->m_Text_LightCMap = LoadTexture("$LightCMap", FT_NOREMOVE, FT2_NODXT, eTT_Cubemap, -1.0f, -1.0f, TO_LIGHT_CUBE_MAP);
|
|
SSingleLight f(16);
|
|
glEnable(GL_TEXTURE_CUBE_MAP_EXT);
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, TO_LIGHT_CUBE_MAP);
|
|
//sTestStr.AddElem(m_Text_LightCMap);
|
|
MakeCubeMap<SSingleLight>(f, GL_RGB8, 64, true, gRenDev->m_TexMan->m_Text_LightCMap);
|
|
//gRenDev->m_TexMan->m_Text_LightCMap->SaveJPG("CubeLight.jpg", false);
|
|
glDisable(GL_TEXTURE_CUBE_MAP_EXT);
|
|
}
|
|
|
|
GenerateFogMaps();
|
|
GenerateFlareMap();
|
|
GenerateGhostMap();
|
|
GenerateDepthLookup();
|
|
}
|
|
|
|
void STexPic::Preload (int Flags)
|
|
{
|
|
}
|