Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
8.1 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. // gl_warp.c -- sky and water polygons
  9. #include "render_pch.h"
  10. #include "gl_water.h"
  11. #include "zone.h"
  12. #include "gl_model_private.h"
  13. #include "gl_matsysiface.h"
  14. #include "utlvector.h"
  15. #include "materialsystem/imesh.h"
  16. #include "materialsystem/imaterial.h"
  17. #include "tier2/tier2.h"
  18. #include "materialsystem/imaterialsystemhardwareconfig.h"
  19. #include "tier0/vprof.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. #define SQRT3INV (0.57735f) // a little less than 1 / sqrt(3)
  23. static ConVar r_drawskybox( "r_drawskybox", "1", FCVAR_CHEAT );
  24. extern ConVar mat_loadtextures;
  25. static IMaterial *skyboxMaterials[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
  26. static char currentloadedsky[ 128 ] = "";
  27. // 1 = s, 2 = t, 3 = 2048
  28. int st_to_vec[6][3] =
  29. {
  30. {3,-1,2},
  31. {-3,1,2},
  32. {1,3,2},
  33. {-1,-3,2},
  34. {-2,-1,3}, // 0 degrees yaw, look straight up
  35. {2,-1,-3} // look straight down
  36. };
  37. // s = [0]/[2], t = [1]/[2]
  38. int skytexorder[6] = {0,2,1,3,4,5};
  39. #define SIGN(d) ((d)<0?-1:1)
  40. static int gFakePlaneType[6] = {1,-1,2,-2,3,-3};
  41. // (This is pasted from vtf.cpp - just for reference. It shows how the faces
  42. // of the engine's skybox are oriented and mapped).
  43. //
  44. // The vert ordering is lower-left, top-left, top-right, bottom-right.
  45. //
  46. // These were constructed for the engine skybox, which looks like this
  47. // (assuming X goes forward, Y goes left, and Z goes up).
  48. //
  49. // 6 ------------- 5
  50. // / /
  51. // / | / |
  52. // / | / |
  53. // 2 ------------- 1 |
  54. // | |
  55. // | |
  56. // | 7 ------|------ 4
  57. // | / | /
  58. // | / | /
  59. // / /
  60. // 3 ------------- 0
  61. //
  62. //int g_skybox_rightFaceVerts[4] = { 7, 6, 5, 4 };
  63. //int g_skybox_leftFaceVerts[4] = { 0, 1, 2, 3 };
  64. //int g_skybox_backFaceVerts[4] = { 3, 2, 6, 7 };
  65. //int g_skybox_frontFaceVerts[4] = { 4, 5, 1, 0 };
  66. //int g_skybox_upFaceVerts[4] = { 6, 2, 1, 5 };
  67. //int g_skybox_downFaceVerts[4] = { 3, 7, 4, 0 };
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. void R_UnloadSkys( void )
  72. {
  73. int i;
  74. for ( i = 0; i < 6; i++ )
  75. {
  76. if( skyboxMaterials[i] )
  77. {
  78. skyboxMaterials[ i ]->DecrementReferenceCount();
  79. skyboxMaterials[ i ] = NULL;
  80. }
  81. }
  82. currentloadedsky[0] = 0;
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose:
  86. // Input : *name -
  87. // Output : Returns true on success, false on failure.
  88. //-----------------------------------------------------------------------------
  89. bool R_LoadNamedSkys( const char *skyname )
  90. {
  91. char name[ MAX_OSPATH ];
  92. IMaterial *skies[ 6 ];
  93. bool success = true;
  94. char *skyboxsuffix[ 6 ] = { "rt", "bk", "lf", "ft", "up", "dn" };
  95. for ( int i = 0; i < 6; i++ )
  96. {
  97. skies[i] = NULL;
  98. if ( skies[i] == NULL )
  99. {
  100. Q_snprintf( name, sizeof( name ), "skybox/%s%s", skyname, skyboxsuffix[i] );
  101. skies[i] = materials->FindMaterial( name, TEXTURE_GROUP_SKYBOX );
  102. }
  103. if( !IsErrorMaterial( skies[i] ) )
  104. continue;
  105. success = false;
  106. break;
  107. }
  108. if ( !success )
  109. {
  110. return false;
  111. }
  112. // Increment references
  113. for ( int i = 0; i < 6; i++ )
  114. {
  115. // Unload any old skybox
  116. if ( skyboxMaterials[ i ] )
  117. {
  118. skyboxMaterials[ i ]->DecrementReferenceCount();
  119. skyboxMaterials[ i ] = NULL;
  120. }
  121. // Use the new one
  122. assert( skies[ i ] );
  123. skyboxMaterials[i] = skies[ i ];
  124. skyboxMaterials[i]->IncrementReferenceCount();
  125. }
  126. return true;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose:
  130. //-----------------------------------------------------------------------------
  131. void R_LoadSkys( void )
  132. {
  133. const char *pDefault = "sky_urb01";
  134. bool success = true;
  135. static ConVarRef skyname( "sv_skyname" );
  136. if ( !skyname.IsValid() )
  137. {
  138. ConDMsg( "Unable to find skyname ConVar!!!\n" );
  139. return;
  140. }
  141. if ( !stricmp( skyname.GetString(), currentloadedsky ) )
  142. {
  143. // We already loaded this sky!
  144. return;
  145. }
  146. // See if user's sky will work
  147. if ( !R_LoadNamedSkys( skyname.GetString() ) )
  148. {
  149. // Assume failure
  150. success = false;
  151. // Try loading the default (if not already requested)
  152. if ( Q_stricmp( skyname.GetString(), pDefault ) && R_LoadNamedSkys( pDefault ) )
  153. {
  154. ConDMsg( "Unable to load sky %s, but successfully loaded %s\n", skyname.GetString(), pDefault );
  155. skyname.SetValue( pDefault );
  156. success = true;
  157. }
  158. }
  159. Q_strncpy( currentloadedsky, skyname.GetString(), sizeof( currentloadedsky ) );
  160. if ( !success )
  161. {
  162. ConDMsg( "Unable to load sky %s\n", skyname.GetString() );
  163. }
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Purpose:
  167. //-----------------------------------------------------------------------------
  168. #pragma warning (disable : 4701)
  169. void MakeSkyVec( float s, float t, int axis, float zFar, Vector& position, Vector2D &texCoord )
  170. {
  171. Vector v, b;
  172. int j, k;
  173. float width;
  174. static float flScale = SQRT3INV;
  175. width = zFar * flScale;
  176. if ( s < -1 )
  177. s = -1;
  178. else if ( s > 1 )
  179. s = 1;
  180. if ( t < -1 )
  181. t = -1;
  182. else if ( t > 1 )
  183. t = 1;
  184. b[0] = s*width;
  185. b[1] = t*width;
  186. b[2] = width;
  187. for (j=0 ; j<3 ; j++)
  188. {
  189. k = st_to_vec[axis][j];
  190. if (k < 0)
  191. v[j] = -b[-k - 1];
  192. else
  193. v[j] = b[k - 1];
  194. v[j] += CurrentViewOrigin()[j];
  195. }
  196. // avoid bilerp seam
  197. s = (s+1)*0.5;
  198. t = (t+1)*0.5;
  199. // AV - I'm commenting this out since our skyboxes aren't 512x512 and we don't
  200. // modify the textures to deal with the border seam fixup correctly.
  201. // The code below was causing seams in the skyboxes.
  202. /*
  203. if (s < 1.0/512)
  204. s = 1.0/512;
  205. else if (s > 511.0/512)
  206. s = 511.0/512;
  207. if (t < 1.0/512)
  208. t = 1.0/512;
  209. else if (t > 511.0/512)
  210. t = 511.0/512;
  211. */
  212. t = 1.0 - t;
  213. VectorCopy( v, position );
  214. texCoord[0] = s;
  215. texCoord[1] = t;
  216. }
  217. #pragma warning (default : 4701)
  218. //-----------------------------------------------------------------------------
  219. // Purpose:
  220. //-----------------------------------------------------------------------------
  221. void R_DrawSkyBox( float zFar, int nDrawFlags /*= 0x3F*/ )
  222. {
  223. VPROF("R_DrawSkyBox");
  224. int i;
  225. Vector normal;
  226. if ( !r_drawskybox.GetInt() || !mat_loadtextures.GetInt() )
  227. {
  228. return;
  229. }
  230. // Check whether the skybox textures have changed
  231. R_LoadSkys();
  232. CMatRenderContextPtr pRenderContext( materials );
  233. for (i=0 ; i<6 ; i++, nDrawFlags >>= 1 )
  234. {
  235. // Don't draw this panel of the skybox if the flag isn't set:
  236. if ( !(nDrawFlags & 1) )
  237. continue;
  238. VectorCopy( vec3_origin, normal );
  239. switch( gFakePlaneType[i] )
  240. {
  241. case 1:
  242. normal[0] = 1;
  243. break;
  244. case -1:
  245. normal[0] = -1;
  246. break;
  247. case 2:
  248. normal[1] = 1;
  249. break;
  250. case -2:
  251. normal[1] = -1;
  252. break;
  253. case 3:
  254. normal[2] = 1;
  255. break;
  256. case -3:
  257. normal[2] = -1;
  258. break;
  259. }
  260. // Normals are reversed so looking at face dots to 1.0, looking away from is -1.0
  261. // Reject backfacing surfaces on the inside of the cube to avoid binding their texture
  262. // Assuming a 90 fov looking at face is 0 degrees, so reject at 107
  263. // AV - Disabling this since it doesn't work in L4D and doesn't really buy us any perf
  264. //if ( DotProduct( CurrentViewForward(), normal ) < -0.29289f )
  265. // continue;
  266. Vector positionArray[4];
  267. Vector2D texCoordArray[4];
  268. if (skyboxMaterials[skytexorder[i]])
  269. {
  270. pRenderContext->Bind( skyboxMaterials[skytexorder[i]] );
  271. MakeSkyVec( -1.0f, -1.0f, i, zFar, positionArray[0], texCoordArray[0] );
  272. MakeSkyVec( -1.0f, 1.0f, i, zFar, positionArray[1], texCoordArray[1] );
  273. MakeSkyVec( 1.0f, 1.0f, i, zFar, positionArray[2], texCoordArray[2] );
  274. MakeSkyVec( 1.0f, -1.0f, i, zFar, positionArray[3], texCoordArray[3] );
  275. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  276. CMeshBuilder meshBuilder;
  277. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  278. for (int j = 0; j < 4; ++j)
  279. {
  280. meshBuilder.Position3fv( positionArray[j].Base() );
  281. meshBuilder.TexCoord2fv( 0, texCoordArray[j].Base() );
  282. meshBuilder.AdvanceVertex();
  283. }
  284. meshBuilder.End();
  285. pMesh->Draw();
  286. }
  287. }
  288. }