#5979: Cubemap support for opengl2.

This commit is contained in:
SmileTheory 2013-09-16 00:54:26 -07:00
parent 68a616c7f1
commit 7e875c6941
23 changed files with 1268 additions and 516 deletions

View file

@ -1805,6 +1805,14 @@ static int BSPSurfaceCompare(const void *a, const void *b)
else if(aa->fogIndex > bb->fogIndex)
return 1;
// by cubemapIndex
if(aa->cubemapIndex < bb->cubemapIndex)
return -1;
else if(aa->cubemapIndex > bb->cubemapIndex)
return 1;
return 0;
}
@ -2814,6 +2822,191 @@ qboolean R_GetEntityToken( char *buffer, int size ) {
}
}
#ifndef MAX_SPAWN_VARS
#define MAX_SPAWN_VARS 64
#endif
// derived from G_ParseSpawnVars() in g_spawn.c
qboolean R_ParseSpawnVars( char *spawnVarChars, int maxSpawnVarChars, int *numSpawnVars, char *spawnVars[MAX_SPAWN_VARS][2] )
{
char keyname[MAX_TOKEN_CHARS];
char com_token[MAX_TOKEN_CHARS];
int numSpawnVarChars = 0;
*numSpawnVars = 0;
// parse the opening brace
if ( !R_GetEntityToken( com_token, sizeof( com_token ) ) ) {
// end of spawn string
return qfalse;
}
if ( com_token[0] != '{' ) {
ri.Printf( PRINT_ALL, "R_ParseSpawnVars: found %s when expecting {",com_token );
}
// go through all the key / value pairs
while ( 1 ) {
int keyLength, tokenLength;
// parse key
if ( !R_GetEntityToken( keyname, sizeof( keyname ) ) ) {
ri.Printf( PRINT_ALL, "R_ParseSpawnVars: EOF without closing brace" );
}
if ( keyname[0] == '}' ) {
break;
}
// parse value
if ( !R_GetEntityToken( com_token, sizeof( com_token ) ) ) {
ri.Printf( PRINT_ALL, "R_ParseSpawnVars: EOF without closing brace" );
break;
}
if ( com_token[0] == '}' ) {
ri.Printf( PRINT_ALL, "R_ParseSpawnVars: closing brace without data" );
break;
}
if ( *numSpawnVars == MAX_SPAWN_VARS ) {
ri.Printf( PRINT_ALL, "R_ParseSpawnVars: MAX_SPAWN_VARS" );
break;
}
keyLength = strlen(keyname) + 1;
tokenLength = strlen(com_token) + 1;
if (numSpawnVarChars + keyLength + tokenLength > maxSpawnVarChars)
{
ri.Printf( PRINT_ALL, "R_ParseSpawnVars: MAX_SPAWN_VAR_CHARS" );
break;
}
strcpy(spawnVarChars + numSpawnVarChars, keyname);
spawnVars[ *numSpawnVars ][0] = spawnVarChars + numSpawnVarChars;
numSpawnVarChars += keyLength;
strcpy(spawnVarChars + numSpawnVarChars, com_token);
spawnVars[ *numSpawnVars ][1] = spawnVarChars + numSpawnVarChars;
numSpawnVarChars += tokenLength;
(*numSpawnVars)++;
}
return qtrue;
}
void R_LoadCubemapEntities(char *cubemapEntityName)
{
char spawnVarChars[2048];
int numSpawnVars;
char *spawnVars[MAX_SPAWN_VARS][2];
int numCubemaps = 0;
// count cubemaps
numCubemaps = 0;
while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars))
{
int i;
for (i = 0; i < numSpawnVars; i++)
{
if (!Q_stricmp(spawnVars[i][0], "classname") && !Q_stricmp(spawnVars[i][1], cubemapEntityName))
numCubemaps++;
}
}
if (!numCubemaps)
return;
tr.numCubemaps = numCubemaps;
tr.cubemapOrigins = ri.Hunk_Alloc( tr.numCubemaps * sizeof(*tr.cubemapOrigins), h_low);
tr.cubemaps = ri.Hunk_Alloc( tr.numCubemaps * sizeof(*tr.cubemaps), h_low);
numCubemaps = 0;
while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars))
{
int i;
qboolean isCubemap = qfalse;
qboolean positionSet = qfalse;
vec3_t origin;
for (i = 0; i < numSpawnVars; i++)
{
if (!Q_stricmp(spawnVars[i][0], "classname") && !Q_stricmp(spawnVars[i][1], cubemapEntityName))
isCubemap = qtrue;
if (!Q_stricmp(spawnVars[i][0], "origin"))
{
sscanf(spawnVars[i][1], "%f %f %f", &origin[0], &origin[1], &origin[2]);
positionSet = qtrue;
}
}
if (isCubemap && positionSet)
{
//ri.Printf(PRINT_ALL, "cubemap at %f %f %f\n", origin[0], origin[1], origin[2]);
VectorCopy(origin, tr.cubemapOrigins[numCubemaps]);
numCubemaps++;
}
}
}
void R_AssignCubemapsToWorldSurfaces(void)
{
world_t *w;
int i;
w = &s_worldData;
for (i = 0; i < w->numsurfaces; i++)
{
msurface_t *surf = &w->surfaces[i];
vec3_t surfOrigin;
if (surf->cullinfo.type & CULLINFO_SPHERE)
{
VectorCopy(surf->cullinfo.localOrigin, surfOrigin);
}
else if (surf->cullinfo.type & CULLINFO_BOX)
{
surfOrigin[0] = (surf->cullinfo.bounds[0][0] + surf->cullinfo.bounds[1][0]) * 0.5f;
surfOrigin[1] = (surf->cullinfo.bounds[0][1] + surf->cullinfo.bounds[1][1]) * 0.5f;
surfOrigin[2] = (surf->cullinfo.bounds[0][2] + surf->cullinfo.bounds[1][2]) * 0.5f;
}
else
{
//ri.Printf(PRINT_ALL, "surface %d has no cubemap\n", i);
continue;
}
surf->cubemapIndex = R_CubemapForPoint(surfOrigin);
//ri.Printf(PRINT_ALL, "surface %d has cubemap %d\n", i, surf->cubemapIndex);
}
}
void R_RenderAllCubemaps(void)
{
int i, j;
for (i = 0; i < tr.numCubemaps; i++)
{
tr.cubemaps[i] = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8);
}
for (i = 0; i < tr.numCubemaps; i++)
{
for (j = 0; j < 6; j++)
{
RE_ClearScene();
R_RenderCubemapSide(i, j, qfalse);
R_IssuePendingRenderCommands();
R_InitNextFrame();
}
}
}
/*
=================
@ -2866,6 +3059,7 @@ void R_MergeLeafSurfaces(void)
msurface_t *surf1;
shader_t *shader1;
int fogIndex1;
int cubemapIndex1;
int surfNum1;
surfNum1 = *(s_worldData.marksurfaces + leaf->firstmarksurface + j);
@ -2890,6 +3084,7 @@ void R_MergeLeafSurfaces(void)
continue;
fogIndex1 = surf1->fogIndex;
cubemapIndex1 = surf1->cubemapIndex;
s_worldData.surfacesViewCount[surfNum1] = surfNum1;
@ -2898,6 +3093,7 @@ void R_MergeLeafSurfaces(void)
msurface_t *surf2;
shader_t *shader2;
int fogIndex2;
int cubemapIndex2;
int surfNum2;
surfNum2 = *(s_worldData.marksurfaces + leaf->firstmarksurface + k);
@ -2920,6 +3116,11 @@ void R_MergeLeafSurfaces(void)
if (fogIndex1 != fogIndex2)
continue;
cubemapIndex2 = surf2->cubemapIndex;
if (cubemapIndex1 != cubemapIndex2)
continue;
s_worldData.surfacesViewCount[surfNum2] = surfNum1;
}
}
@ -3153,6 +3354,7 @@ void R_MergeLeafSurfaces(void)
vboSurf->shader = surf1->shader;
vboSurf->fogIndex = surf1->fogIndex;
vboSurf->cubemapIndex = surf1->cubemapIndex;
VectorCopy(bounds[0], vboSurf->bounds[0]);
VectorCopy(bounds[1], vboSurf->bounds[1]);
@ -3163,6 +3365,7 @@ void R_MergeLeafSurfaces(void)
mergedSurf->cullinfo.type = CULLINFO_BOX;
mergedSurf->data = (surfaceType_t *)vboSurf;
mergedSurf->fogIndex = surf1->fogIndex;
mergedSurf->cubemapIndex = surf1->cubemapIndex;
mergedSurf->shader = surf1->shader;
// redirect view surfaces to this surf
@ -3539,6 +3742,22 @@ void RE_LoadWorldMap( const char *name ) {
ri.Free(primaryLightGrid);
}
// load cubemaps
if (r_cubeMapping->integer)
{
R_LoadCubemapEntities("misc_cubemap");
if (!tr.numCubemaps)
{
// use deathmatch spawn points as cubemaps
R_LoadCubemapEntities("info_player_deathmatch");
}
if (tr.numCubemaps)
{
R_AssignCubemapsToWorldSurfaces();
}
}
// create static VBOS from the world
R_CreateWorldVBO();
if (r_mergeLeafSurfaces->integer)
@ -3555,5 +3774,11 @@ void RE_LoadWorldMap( const char *name ) {
R_BindNullVBO();
R_BindNullIBO();
// Render all cubemaps
if (r_cubeMapping->integer && tr.numCubemaps)
{
R_RenderAllCubemaps();
}
ri.FS_FreeFile( buffer.v );
}