summaryrefslogtreecommitdiff
path: root/engine/gl_warp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine/gl_warp.cpp')
-rw-r--r--engine/gl_warp.cpp352
1 files changed, 352 insertions, 0 deletions
diff --git a/engine/gl_warp.cpp b/engine/gl_warp.cpp
new file mode 100644
index 0000000..881ac7a
--- /dev/null
+++ b/engine/gl_warp.cpp
@@ -0,0 +1,352 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+// gl_warp.c -- sky and water polygons
+
+#include "render_pch.h"
+#include "gl_water.h"
+#include "zone.h"
+#include "gl_model_private.h"
+#include "gl_matsysiface.h"
+#include "utlvector.h"
+#include "materialsystem/imesh.h"
+#include "materialsystem/imaterial.h"
+#include "tier2/tier2.h"
+#include "materialsystem/imaterialsystemhardwareconfig.h"
+#include "tier0/vprof.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define SQRT3INV (0.57735f) // a little less than 1 / sqrt(3)
+
+static ConVar r_drawskybox( "r_drawskybox", "1", FCVAR_CHEAT );
+
+extern ConVar mat_loadtextures;
+static IMaterial *skyboxMaterials[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
+
+// 1 = s, 2 = t, 3 = 2048
+int st_to_vec[6][3] =
+{
+ {3,-1,2},
+ {-3,1,2},
+
+ {1,3,2},
+ {-1,-3,2},
+
+ {-2,-1,3}, // 0 degrees yaw, look straight up
+ {2,-1,-3} // look straight down
+};
+
+// s = [0]/[2], t = [1]/[2]
+
+int skytexorder[6] = {0,2,1,3,4,5};
+#define SIGN(d) ((d)<0?-1:1)
+static int gFakePlaneType[6] = {1,-1,2,-2,3,-3};
+
+// (This is pasted from vtf.cpp - just for reference. It shows how the faces
+// of the engine's skybox are oriented and mapped).
+//
+// The vert ordering is lower-left, top-left, top-right, bottom-right.
+//
+// These were constructed for the engine skybox, which looks like this
+// (assuming X goes forward, Y goes left, and Z goes up).
+//
+// 6 ------------- 5
+// / /
+// / | / |
+// / | / |
+// 2 ------------- 1 |
+// | |
+// | |
+// | 7 ------|------ 4
+// | / | /
+// | / | /
+// / /
+// 3 ------------- 0
+//
+//int g_skybox_rightFaceVerts[4] = { 7, 6, 5, 4 };
+//int g_skybox_leftFaceVerts[4] = { 0, 1, 2, 3 };
+//int g_skybox_backFaceVerts[4] = { 3, 2, 6, 7 };
+//int g_skybox_frontFaceVerts[4] = { 4, 5, 1, 0 };
+//int g_skybox_upFaceVerts[4] = { 6, 2, 1, 5 };
+//int g_skybox_downFaceVerts[4] = { 3, 7, 4, 0 };
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void R_UnloadSkys( void )
+{
+ int i;
+
+ for ( i = 0; i < 6; i++ )
+ {
+ if( skyboxMaterials[i] )
+ {
+ skyboxMaterials[ i ]->DecrementReferenceCount();
+ skyboxMaterials[ i ] = NULL;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool R_LoadNamedSkys( const char *skyname )
+{
+ char name[ MAX_OSPATH ];
+ IMaterial *skies[ 6 ];
+ bool success = true;
+ const char *skyboxsuffix[ 6 ] = { "rt", "bk", "lf", "ft", "up", "dn" };
+
+ bool bUseDx8Skyboxes = ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 90 );
+ for ( int i = 0; i < 6; i++ )
+ {
+ skies[i] = NULL;
+ if ( bUseDx8Skyboxes )
+ {
+ Q_snprintf( name, sizeof( name ), "skybox/%s_dx80%s", skyname, skyboxsuffix[i] );
+ skies[i] = materials->FindMaterial( name, TEXTURE_GROUP_SKYBOX, false );
+ if( IsErrorMaterial( skies[i] ) )
+ {
+ skies[i] = NULL;
+ }
+ }
+
+ if ( skies[i] == NULL )
+ {
+ Q_snprintf( name, sizeof( name ), "skybox/%s%s", skyname, skyboxsuffix[i] );
+ skies[i] = materials->FindMaterial( name, TEXTURE_GROUP_SKYBOX );
+ }
+ if( !IsErrorMaterial( skies[i] ) )
+ continue;
+
+ success = false;
+ break;
+ }
+
+ if ( !success )
+ {
+ return false;
+ }
+
+ // Increment references
+ for ( int i = 0; i < 6; i++ )
+ {
+ // Unload any old skybox
+ if ( skyboxMaterials[ i ] )
+ {
+ skyboxMaterials[ i ]->DecrementReferenceCount();
+ skyboxMaterials[ i ] = NULL;
+ }
+
+ // Use the new one
+ assert( skies[ i ] );
+ skyboxMaterials[i] = skies[ i ];
+ skyboxMaterials[i]->IncrementReferenceCount();
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void R_LoadSkys( void )
+{
+ bool success = true;
+
+ char requestedsky[ 128 ];
+
+ ConVarRef skyname( "sv_skyname" );
+ if ( skyname.IsValid() )
+ {
+ Q_strncpy( requestedsky, skyname.GetString(), sizeof( requestedsky ) );
+ }
+ else
+ {
+ ConDMsg( "Unable to find skyname ConVar!!!\n" );
+ return;
+ }
+
+ // See if user's sky will work
+ if ( !R_LoadNamedSkys( requestedsky ) )
+ {
+ // Assume failure
+ success = false;
+
+ // See if user requested other than the default
+ if ( Q_stricmp( requestedsky, "sky_urb01" ) )
+ {
+ // Try the default
+ skyname.SetValue( "sky_urb01" );
+
+ // See if we could load that one now
+ if ( R_LoadNamedSkys( skyname.GetString() ) )
+ {
+ ConDMsg( "Unable to load sky %s, but successfully loaded %s\n", requestedsky, skyname.GetString() );
+ success = true;
+ }
+ }
+ }
+
+ if ( !success )
+ {
+ ConDMsg( "Unable to load sky %s\n", requestedsky );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+#pragma warning (disable : 4701)
+void MakeSkyVec( float s, float t, int axis, float zFar, Vector& position, Vector2D &texCoord )
+{
+ Vector v, b;
+ int j, k;
+ float width;
+
+ width = zFar * SQRT3INV;
+
+ if ( s < -1 )
+ s = -1;
+ else if ( s > 1 )
+ s = 1;
+ if ( t < -1 )
+ t = -1;
+ else if ( t > 1 )
+ t = 1;
+
+ b[0] = s*width;
+ b[1] = t*width;
+ b[2] = width;
+
+ for (j=0 ; j<3 ; j++)
+ {
+ k = st_to_vec[axis][j];
+ if (k < 0)
+ v[j] = -b[-k - 1];
+ else
+ v[j] = b[k - 1];
+ v[j] += CurrentViewOrigin()[j];
+ }
+
+ // avoid bilerp seam
+ s = (s+1)*0.5;
+ t = (t+1)*0.5;
+
+ if (s < 1.0/512)
+ s = 1.0/512;
+ else if (s > 511.0/512)
+ s = 511.0/512;
+ if (t < 1.0/512)
+ t = 1.0/512;
+ else if (t > 511.0/512)
+ t = 511.0/512;
+
+ t = 1.0 - t;
+ VectorCopy( v, position );
+ texCoord[0] = s;
+ texCoord[1] = t;
+}
+#pragma warning (default : 4701)
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void R_DrawSkyBox( float zFar, int nDrawFlags /*= 0x3F*/ )
+{
+ VPROF("R_DrawSkyBox");
+ tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s %x", __FUNCTION__, nDrawFlags );
+
+ int i;
+ Vector normal;
+
+ if ( !r_drawskybox.GetInt() || !mat_loadtextures.GetInt() )
+ {
+ return;
+ }
+
+ CMatRenderContextPtr pRenderContext( materials );
+
+ for (i=0 ; i<6 ; i++, nDrawFlags >>= 1 )
+ {
+ // Don't draw this panel of the skybox if the flag isn't set:
+ if ( !(nDrawFlags & 1) )
+ continue;
+
+ VectorCopy( vec3_origin, normal );
+ switch( gFakePlaneType[i] )
+ {
+ case 1:
+ normal[0] = 1;
+ break;
+
+ case -1:
+ normal[0] = -1;
+ break;
+
+ case 2:
+ normal[1] = 1;
+ break;
+
+ case -2:
+ normal[1] = -1;
+ break;
+
+ case 3:
+ normal[2] = 1;
+ break;
+
+ case -3:
+ normal[2] = -1;
+ break;
+ }
+
+ // Normals are reversed so looking at face dots to 1.0, looking away from is -1.0
+ // Reject backfacing surfaces on the inside of the cube to avoid binding their texture
+ // Assuming a 90 fov looking at face is 0 degrees, so reject at 107
+ if ( DotProduct( CurrentViewForward(), normal ) < -0.29289f )
+ continue;
+
+ Vector positionArray[4];
+ Vector2D texCoordArray[4];
+ if (skyboxMaterials[skytexorder[i]])
+ {
+ pRenderContext->Bind( skyboxMaterials[skytexorder[i]] );
+
+ MakeSkyVec( -1.0f, -1.0f, i, zFar, positionArray[0], texCoordArray[0] );
+ MakeSkyVec( -1.0f, 1.0f, i, zFar, positionArray[1], texCoordArray[1] );
+ MakeSkyVec( 1.0f, 1.0f, i, zFar, positionArray[2], texCoordArray[2] );
+ MakeSkyVec( 1.0f, -1.0f, i, zFar, positionArray[3], texCoordArray[3] );
+
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+
+ CMeshBuilder meshBuilder;
+ meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 4, 6 );
+
+ // meshbuilder Begin can fail if dynamic mesh is not available (eg, alt-tabbed away)
+ if ( meshBuilder.BaseVertexData() == NULL )
+ continue;
+
+ for (int j = 0; j < 4; ++j)
+ {
+ meshBuilder.Position3fv( positionArray[j].Base() );
+ meshBuilder.TexCoord2fv( 0, texCoordArray[j].Base() );
+ meshBuilder.AdvanceVertex();
+ }
+ CIndexBuilder &indexBuilder = meshBuilder;
+ indexBuilder.FastQuad( 0 );
+
+ meshBuilder.End();
+ pMesh->Draw();
+ }
+ }
+}