tr_backend_draw.cpp 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. idCVar r_drawEyeColor( "r_drawEyeColor", "0", CVAR_RENDERER | CVAR_BOOL, "Draw a colored box, red = left eye, blue = right eye, grey = non-stereo" );
  24. idCVar r_motionBlur( "r_motionBlur", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 - 5, log2 of the number of motion blur samples" );
  25. idCVar r_forceZPassStencilShadows( "r_forceZPassStencilShadows", "0", CVAR_RENDERER | CVAR_BOOL, "force Z-pass rendering for performance testing" );
  26. idCVar r_useStencilShadowPreload( "r_useStencilShadowPreload", "1", CVAR_RENDERER | CVAR_BOOL, "use stencil shadow preload algorithm instead of Z-fail" );
  27. idCVar r_skipShaderPasses( "r_skipShaderPasses", "0", CVAR_RENDERER | CVAR_BOOL, "" );
  28. idCVar r_skipInteractionFastPath( "r_skipInteractionFastPath", "1", CVAR_RENDERER | CVAR_BOOL, "" );
  29. idCVar r_useLightStencilSelect( "r_useLightStencilSelect", "0", CVAR_RENDERER | CVAR_BOOL, "use stencil select pass" );
  30. extern idCVar stereoRender_swapEyes;
  31. backEndState_t backEnd;
  32. /*
  33. ================
  34. SetVertexParm
  35. ================
  36. */
  37. static ID_INLINE void SetVertexParm( renderParm_t rp, const float * value ) {
  38. renderProgManager.SetUniformValue( rp, value );
  39. }
  40. /*
  41. ================
  42. SetVertexParms
  43. ================
  44. */
  45. static ID_INLINE void SetVertexParms( renderParm_t rp, const float * value, int num ) {
  46. for ( int i = 0; i < num; i++ ) {
  47. renderProgManager.SetUniformValue( (renderParm_t)( rp + i ), value + ( i * 4 ) );
  48. }
  49. }
  50. /*
  51. ================
  52. SetFragmentParm
  53. ================
  54. */
  55. static ID_INLINE void SetFragmentParm( renderParm_t rp, const float * value ) {
  56. renderProgManager.SetUniformValue( rp, value );
  57. }
  58. /*
  59. ================
  60. RB_SetMVP
  61. ================
  62. */
  63. void RB_SetMVP( const idRenderMatrix & mvp ) {
  64. SetVertexParms( RENDERPARM_MVPMATRIX_X, mvp[0], 4 );
  65. }
  66. /*
  67. ================
  68. RB_SetMVPWithStereoOffset
  69. ================
  70. */
  71. static void RB_SetMVPWithStereoOffset( const idRenderMatrix & mvp, const float stereoOffset ) {
  72. idRenderMatrix offset = mvp;
  73. offset[0][3] += stereoOffset;
  74. SetVertexParms( RENDERPARM_MVPMATRIX_X, offset[0], 4 );
  75. }
  76. static const float zero[4] = { 0, 0, 0, 0 };
  77. static const float one[4] = { 1, 1, 1, 1 };
  78. static const float negOne[4] = { -1, -1, -1, -1 };
  79. /*
  80. ================
  81. RB_SetVertexColorParms
  82. ================
  83. */
  84. static void RB_SetVertexColorParms( stageVertexColor_t svc ) {
  85. switch ( svc ) {
  86. case SVC_IGNORE:
  87. SetVertexParm( RENDERPARM_VERTEXCOLOR_MODULATE, zero );
  88. SetVertexParm( RENDERPARM_VERTEXCOLOR_ADD, one );
  89. break;
  90. case SVC_MODULATE:
  91. SetVertexParm( RENDERPARM_VERTEXCOLOR_MODULATE, one );
  92. SetVertexParm( RENDERPARM_VERTEXCOLOR_ADD, zero );
  93. break;
  94. case SVC_INVERSE_MODULATE:
  95. SetVertexParm( RENDERPARM_VERTEXCOLOR_MODULATE, negOne );
  96. SetVertexParm( RENDERPARM_VERTEXCOLOR_ADD, one );
  97. break;
  98. }
  99. }
  100. /*
  101. ================
  102. RB_DrawElementsWithCounters
  103. ================
  104. */
  105. void RB_DrawElementsWithCounters( const drawSurf_t *surf ) {
  106. // get vertex buffer
  107. const vertCacheHandle_t vbHandle = surf->ambientCache;
  108. idVertexBuffer * vertexBuffer;
  109. if ( vertexCache.CacheIsStatic( vbHandle ) ) {
  110. vertexBuffer = &vertexCache.staticData.vertexBuffer;
  111. } else {
  112. const uint64 frameNum = (int)( vbHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  113. if ( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) ) {
  114. idLib::Warning( "RB_DrawElementsWithCounters, vertexBuffer == NULL" );
  115. return;
  116. }
  117. vertexBuffer = &vertexCache.frameData[vertexCache.drawListNum].vertexBuffer;
  118. }
  119. const int vertOffset = (int)( vbHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
  120. // get index buffer
  121. const vertCacheHandle_t ibHandle = surf->indexCache;
  122. idIndexBuffer * indexBuffer;
  123. if ( vertexCache.CacheIsStatic( ibHandle ) ) {
  124. indexBuffer = &vertexCache.staticData.indexBuffer;
  125. } else {
  126. const uint64 frameNum = (int)( ibHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  127. if ( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) ) {
  128. idLib::Warning( "RB_DrawElementsWithCounters, indexBuffer == NULL" );
  129. return;
  130. }
  131. indexBuffer = &vertexCache.frameData[vertexCache.drawListNum].indexBuffer;
  132. }
  133. const int indexOffset = (int)( ibHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
  134. RENDERLOG_PRINTF( "Binding Buffers: %p:%i %p:%i\n", vertexBuffer, vertOffset, indexBuffer, indexOffset );
  135. if ( surf->jointCache ) {
  136. if ( !verify( renderProgManager.ShaderUsesJoints() ) ) {
  137. return;
  138. }
  139. } else {
  140. if ( !verify( !renderProgManager.ShaderUsesJoints() || renderProgManager.ShaderHasOptionalSkinning() ) ) {
  141. return;
  142. }
  143. }
  144. if ( surf->jointCache ) {
  145. idJointBuffer jointBuffer;
  146. if ( !vertexCache.GetJointBuffer( surf->jointCache, &jointBuffer ) ) {
  147. idLib::Warning( "RB_DrawElementsWithCounters, jointBuffer == NULL" );
  148. return;
  149. }
  150. assert( ( jointBuffer.GetOffset() & ( glConfig.uniformBufferOffsetAlignment - 1 ) ) == 0 );
  151. const GLuint ubo = reinterpret_cast< GLuint >( jointBuffer.GetAPIObject() );
  152. qglBindBufferRange( GL_UNIFORM_BUFFER, 0, ubo, jointBuffer.GetOffset(), jointBuffer.GetNumJoints() * sizeof( idJointMat ) );
  153. }
  154. renderProgManager.CommitUniforms();
  155. if ( backEnd.glState.currentIndexBuffer != (GLuint)indexBuffer->GetAPIObject() || !r_useStateCaching.GetBool() ) {
  156. qglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, (GLuint)indexBuffer->GetAPIObject() );
  157. backEnd.glState.currentIndexBuffer = (GLuint)indexBuffer->GetAPIObject();
  158. }
  159. if ( ( backEnd.glState.vertexLayout != LAYOUT_DRAW_VERT ) || ( backEnd.glState.currentVertexBuffer != (GLuint)vertexBuffer->GetAPIObject() ) || !r_useStateCaching.GetBool() ) {
  160. qglBindBufferARB( GL_ARRAY_BUFFER_ARB, (GLuint)vertexBuffer->GetAPIObject() );
  161. backEnd.glState.currentVertexBuffer = (GLuint)vertexBuffer->GetAPIObject();
  162. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_VERTEX );
  163. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_NORMAL );
  164. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_COLOR );
  165. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_COLOR2 );
  166. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_ST );
  167. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_TANGENT );
  168. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof( idDrawVert ), (void *)( DRAWVERT_XYZ_OFFSET ) );
  169. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_NORMAL, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( idDrawVert ), (void *)( DRAWVERT_NORMAL_OFFSET ) );
  170. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( idDrawVert ), (void *)( DRAWVERT_COLOR_OFFSET ) );
  171. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_COLOR2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( idDrawVert ), (void *)( DRAWVERT_COLOR2_OFFSET ) );
  172. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_ST, 2, GL_HALF_FLOAT, GL_TRUE, sizeof( idDrawVert ), (void *)( DRAWVERT_ST_OFFSET ) );
  173. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_TANGENT, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( idDrawVert ), (void *)( DRAWVERT_TANGENT_OFFSET ) );
  174. backEnd.glState.vertexLayout = LAYOUT_DRAW_VERT;
  175. }
  176. qglDrawElementsBaseVertex( GL_TRIANGLES,
  177. r_singleTriangle.GetBool() ? 3 : surf->numIndexes,
  178. GL_INDEX_TYPE,
  179. (triIndex_t *)indexOffset,
  180. vertOffset / sizeof ( idDrawVert ) );
  181. }
  182. /*
  183. ======================
  184. RB_GetShaderTextureMatrix
  185. ======================
  186. */
  187. static void RB_GetShaderTextureMatrix( const float *shaderRegisters, const textureStage_t *texture, float matrix[16] ) {
  188. matrix[0*4+0] = shaderRegisters[ texture->matrix[0][0] ];
  189. matrix[1*4+0] = shaderRegisters[ texture->matrix[0][1] ];
  190. matrix[2*4+0] = 0.0f;
  191. matrix[3*4+0] = shaderRegisters[ texture->matrix[0][2] ];
  192. matrix[0*4+1] = shaderRegisters[ texture->matrix[1][0] ];
  193. matrix[1*4+1] = shaderRegisters[ texture->matrix[1][1] ];
  194. matrix[2*4+1] = 0.0f;
  195. matrix[3*4+1] = shaderRegisters[ texture->matrix[1][2] ];
  196. // we attempt to keep scrolls from generating incredibly large texture values, but
  197. // center rotations and center scales can still generate offsets that need to be > 1
  198. if ( matrix[3*4+0] < -40.0f || matrix[12] > 40.0f ) {
  199. matrix[3*4+0] -= (int)matrix[3*4+0];
  200. }
  201. if ( matrix[13] < -40.0f || matrix[13] > 40.0f ) {
  202. matrix[13] -= (int)matrix[13];
  203. }
  204. matrix[0*4+2] = 0.0f;
  205. matrix[1*4+2] = 0.0f;
  206. matrix[2*4+2] = 1.0f;
  207. matrix[3*4+2] = 0.0f;
  208. matrix[0*4+3] = 0.0f;
  209. matrix[1*4+3] = 0.0f;
  210. matrix[2*4+3] = 0.0f;
  211. matrix[3*4+3] = 1.0f;
  212. }
  213. /*
  214. ======================
  215. RB_LoadShaderTextureMatrix
  216. ======================
  217. */
  218. static void RB_LoadShaderTextureMatrix( const float *shaderRegisters, const textureStage_t *texture ) {
  219. float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
  220. float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
  221. if ( texture->hasMatrix ) {
  222. float matrix[16];
  223. RB_GetShaderTextureMatrix( shaderRegisters, texture, matrix );
  224. texS[0] = matrix[0*4+0];
  225. texS[1] = matrix[1*4+0];
  226. texS[2] = matrix[2*4+0];
  227. texS[3] = matrix[3*4+0];
  228. texT[0] = matrix[0*4+1];
  229. texT[1] = matrix[1*4+1];
  230. texT[2] = matrix[2*4+1];
  231. texT[3] = matrix[3*4+1];
  232. RENDERLOG_PRINTF( "Setting Texture Matrix\n");
  233. renderLog.Indent();
  234. RENDERLOG_PRINTF( "Texture Matrix S : %4.3f, %4.3f, %4.3f, %4.3f\n", texS[0], texS[1], texS[2], texS[3] );
  235. RENDERLOG_PRINTF( "Texture Matrix T : %4.3f, %4.3f, %4.3f, %4.3f\n", texT[0], texT[1], texT[2], texT[3] );
  236. renderLog.Outdent();
  237. }
  238. SetVertexParm( RENDERPARM_TEXTUREMATRIX_S, texS );
  239. SetVertexParm( RENDERPARM_TEXTUREMATRIX_T, texT );
  240. }
  241. /*
  242. =====================
  243. RB_BakeTextureMatrixIntoTexgen
  244. =====================
  245. */
  246. static void RB_BakeTextureMatrixIntoTexgen( idPlane lightProject[3], const float *textureMatrix ) {
  247. float genMatrix[16];
  248. float final[16];
  249. genMatrix[0*4+0] = lightProject[0][0];
  250. genMatrix[1*4+0] = lightProject[0][1];
  251. genMatrix[2*4+0] = lightProject[0][2];
  252. genMatrix[3*4+0] = lightProject[0][3];
  253. genMatrix[0*4+1] = lightProject[1][0];
  254. genMatrix[1*4+1] = lightProject[1][1];
  255. genMatrix[2*4+1] = lightProject[1][2];
  256. genMatrix[3*4+1] = lightProject[1][3];
  257. genMatrix[0*4+2] = 0.0f;
  258. genMatrix[1*4+2] = 0.0f;
  259. genMatrix[2*4+2] = 0.0f;
  260. genMatrix[3*4+2] = 0.0f;
  261. genMatrix[0*4+3] = lightProject[2][0];
  262. genMatrix[1*4+3] = lightProject[2][1];
  263. genMatrix[2*4+3] = lightProject[2][2];
  264. genMatrix[3*4+3] = lightProject[2][3];
  265. R_MatrixMultiply( genMatrix, textureMatrix, final );
  266. lightProject[0][0] = final[0*4+0];
  267. lightProject[0][1] = final[1*4+0];
  268. lightProject[0][2] = final[2*4+0];
  269. lightProject[0][3] = final[3*4+0];
  270. lightProject[1][0] = final[0*4+1];
  271. lightProject[1][1] = final[1*4+1];
  272. lightProject[1][2] = final[2*4+1];
  273. lightProject[1][3] = final[3*4+1];
  274. }
  275. /*
  276. ======================
  277. RB_BindVariableStageImage
  278. Handles generating a cinematic frame if needed
  279. ======================
  280. */
  281. static void RB_BindVariableStageImage( const textureStage_t *texture, const float *shaderRegisters ) {
  282. if ( texture->cinematic ) {
  283. cinData_t cin;
  284. if ( r_skipDynamicTextures.GetBool() ) {
  285. globalImages->defaultImage->Bind();
  286. return;
  287. }
  288. // offset time by shaderParm[7] (FIXME: make the time offset a parameter of the shader?)
  289. // We make no attempt to optimize for multiple identical cinematics being in view, or
  290. // for cinematics going at a lower framerate than the renderer.
  291. cin = texture->cinematic->ImageForTime( backEnd.viewDef->renderView.time[0] + idMath::Ftoi( 1000.0f * backEnd.viewDef->renderView.shaderParms[11] ) );
  292. if ( cin.imageY != NULL ) {
  293. GL_SelectTexture( 0 );
  294. cin.imageY->Bind();
  295. GL_SelectTexture( 1 );
  296. cin.imageCr->Bind();
  297. GL_SelectTexture( 2 );
  298. cin.imageCb->Bind();
  299. } else {
  300. globalImages->blackImage->Bind();
  301. // because the shaders may have already been set - we need to make sure we are not using a bink shader which would
  302. // display incorrectly. We may want to get rid of RB_BindVariableStageImage and inline the code so that the
  303. // SWF GUI case is handled better, too
  304. renderProgManager.BindShader_TextureVertexColor();
  305. }
  306. } else {
  307. // FIXME: see why image is invalid
  308. if ( texture->image != NULL ) {
  309. texture->image->Bind();
  310. }
  311. }
  312. }
  313. /*
  314. ================
  315. RB_PrepareStageTexturing
  316. ================
  317. */
  318. static void RB_PrepareStageTexturing( const shaderStage_t * pStage, const drawSurf_t * surf ) {
  319. float useTexGenParm[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  320. // set the texture matrix if needed
  321. RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
  322. // texgens
  323. if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {
  324. // see if there is also a bump map specified
  325. const shaderStage_t *bumpStage = surf->material->GetBumpStage();
  326. if ( bumpStage != NULL ) {
  327. // per-pixel reflection mapping with bump mapping
  328. GL_SelectTexture( 1 );
  329. bumpStage->texture.image->Bind();
  330. GL_SelectTexture( 0 );
  331. RENDERLOG_PRINTF( "TexGen: TG_REFLECT_CUBE: Bumpy Environment\n" );
  332. if ( surf->jointCache ) {
  333. renderProgManager.BindShader_BumpyEnvironmentSkinned();
  334. } else {
  335. renderProgManager.BindShader_BumpyEnvironment();
  336. }
  337. } else {
  338. RENDERLOG_PRINTF( "TexGen: TG_REFLECT_CUBE: Environment\n" );
  339. if ( surf->jointCache ) {
  340. renderProgManager.BindShader_EnvironmentSkinned();
  341. } else {
  342. renderProgManager.BindShader_Environment();
  343. }
  344. }
  345. } else if ( pStage->texture.texgen == TG_SKYBOX_CUBE ) {
  346. renderProgManager.BindShader_SkyBox();
  347. } else if ( pStage->texture.texgen == TG_WOBBLESKY_CUBE ) {
  348. const int * parms = surf->material->GetTexGenRegisters();
  349. float wobbleDegrees = surf->shaderRegisters[ parms[0] ] * ( idMath::PI / 180.0f );
  350. float wobbleSpeed = surf->shaderRegisters[ parms[1] ] * ( 2.0f * idMath::PI / 60.0f );
  351. float rotateSpeed = surf->shaderRegisters[ parms[2] ] * ( 2.0f * idMath::PI / 60.0f );
  352. idVec3 axis[3];
  353. {
  354. // very ad-hoc "wobble" transform
  355. float s, c;
  356. idMath::SinCos( wobbleSpeed * backEnd.viewDef->renderView.time[0] * 0.001f, s, c );
  357. float ws, wc;
  358. idMath::SinCos( wobbleDegrees, ws, wc );
  359. axis[2][0] = ws * c;
  360. axis[2][1] = ws * s;
  361. axis[2][2] = wc;
  362. axis[1][0] = -s * s * ws;
  363. axis[1][2] = -s * ws * ws;
  364. axis[1][1] = idMath::Sqrt( idMath::Fabs( 1.0f - ( axis[1][0] * axis[1][0] + axis[1][2] * axis[1][2] ) ) );
  365. // make the second vector exactly perpendicular to the first
  366. axis[1] -= ( axis[2] * axis[1] ) * axis[2];
  367. axis[1].Normalize();
  368. // construct the third with a cross
  369. axis[0].Cross( axis[1], axis[2] );
  370. }
  371. // add the rotate
  372. float rs, rc;
  373. idMath::SinCos( rotateSpeed * backEnd.viewDef->renderView.time[0] * 0.001f, rs, rc );
  374. float transform[12];
  375. transform[0*4+0] = axis[0][0] * rc + axis[1][0] * rs;
  376. transform[0*4+1] = axis[0][1] * rc + axis[1][1] * rs;
  377. transform[0*4+2] = axis[0][2] * rc + axis[1][2] * rs;
  378. transform[0*4+3] = 0.0f;
  379. transform[1*4+0] = axis[1][0] * rc - axis[0][0] * rs;
  380. transform[1*4+1] = axis[1][1] * rc - axis[0][1] * rs;
  381. transform[1*4+2] = axis[1][2] * rc - axis[0][2] * rs;
  382. transform[1*4+3] = 0.0f;
  383. transform[2*4+0] = axis[2][0];
  384. transform[2*4+1] = axis[2][1];
  385. transform[2*4+2] = axis[2][2];
  386. transform[2*4+3] = 0.0f;
  387. SetVertexParms( RENDERPARM_WOBBLESKY_X, transform, 3 );
  388. renderProgManager.BindShader_WobbleSky();
  389. } else if ( ( pStage->texture.texgen == TG_SCREEN ) || ( pStage->texture.texgen == TG_SCREEN2 ) ) {
  390. useTexGenParm[0] = 1.0f;
  391. useTexGenParm[1] = 1.0f;
  392. useTexGenParm[2] = 1.0f;
  393. useTexGenParm[3] = 1.0f;
  394. float mat[16];
  395. R_MatrixMultiply( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
  396. RENDERLOG_PRINTF( "TexGen : %s\n", ( pStage->texture.texgen == TG_SCREEN ) ? "TG_SCREEN" : "TG_SCREEN2" );
  397. renderLog.Indent();
  398. float plane[4];
  399. plane[0] = mat[0*4+0];
  400. plane[1] = mat[1*4+0];
  401. plane[2] = mat[2*4+0];
  402. plane[3] = mat[3*4+0];
  403. SetVertexParm( RENDERPARM_TEXGEN_0_S, plane );
  404. RENDERLOG_PRINTF( "TEXGEN_S = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] );
  405. plane[0] = mat[0*4+1];
  406. plane[1] = mat[1*4+1];
  407. plane[2] = mat[2*4+1];
  408. plane[3] = mat[3*4+1];
  409. SetVertexParm( RENDERPARM_TEXGEN_0_T, plane );
  410. RENDERLOG_PRINTF( "TEXGEN_T = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] );
  411. plane[0] = mat[0*4+3];
  412. plane[1] = mat[1*4+3];
  413. plane[2] = mat[2*4+3];
  414. plane[3] = mat[3*4+3];
  415. SetVertexParm( RENDERPARM_TEXGEN_0_Q, plane );
  416. RENDERLOG_PRINTF( "TEXGEN_Q = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] );
  417. renderLog.Outdent();
  418. } else if ( pStage->texture.texgen == TG_DIFFUSE_CUBE ) {
  419. // As far as I can tell, this is never used
  420. idLib::Warning( "Using Diffuse Cube! Please contact Brian!" );
  421. } else if ( pStage->texture.texgen == TG_GLASSWARP ) {
  422. // As far as I can tell, this is never used
  423. idLib::Warning( "Using GlassWarp! Please contact Brian!" );
  424. }
  425. SetVertexParm( RENDERPARM_TEXGEN_0_ENABLED, useTexGenParm );
  426. }
  427. /*
  428. ================
  429. RB_FinishStageTexturing
  430. ================
  431. */
  432. static void RB_FinishStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf ) {
  433. if ( pStage->texture.cinematic ) {
  434. // unbind the extra bink textures
  435. GL_SelectTexture( 1 );
  436. globalImages->BindNull();
  437. GL_SelectTexture( 2 );
  438. globalImages->BindNull();
  439. GL_SelectTexture( 0 );
  440. }
  441. if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {
  442. // see if there is also a bump map specified
  443. const shaderStage_t *bumpStage = surf->material->GetBumpStage();
  444. if ( bumpStage != NULL ) {
  445. // per-pixel reflection mapping with bump mapping
  446. GL_SelectTexture( 1 );
  447. globalImages->BindNull();
  448. GL_SelectTexture( 0 );
  449. } else {
  450. // per-pixel reflection mapping without bump mapping
  451. }
  452. renderProgManager.Unbind();
  453. }
  454. }
  455. /*
  456. =========================================================================================
  457. DEPTH BUFFER RENDERING
  458. =========================================================================================
  459. */
  460. /*
  461. ==================
  462. RB_FillDepthBufferGeneric
  463. ==================
  464. */
  465. static void RB_FillDepthBufferGeneric( const drawSurf_t * const * drawSurfs, int numDrawSurfs ) {
  466. for ( int i = 0; i < numDrawSurfs; i++ ) {
  467. const drawSurf_t * drawSurf = drawSurfs[i];
  468. const idMaterial * shader = drawSurf->material;
  469. // translucent surfaces don't put anything in the depth buffer and don't
  470. // test against it, which makes them fail the mirror clip plane operation
  471. if ( shader->Coverage() == MC_TRANSLUCENT ) {
  472. continue;
  473. }
  474. // get the expressions for conditionals / color / texcoords
  475. const float * regs = drawSurf->shaderRegisters;
  476. // if all stages of a material have been conditioned off, don't do anything
  477. int stage = 0;
  478. for ( ; stage < shader->GetNumStages(); stage++ ) {
  479. const shaderStage_t * pStage = shader->GetStage( stage );
  480. // check the stage enable condition
  481. if ( regs[ pStage->conditionRegister ] != 0 ) {
  482. break;
  483. }
  484. }
  485. if ( stage == shader->GetNumStages() ) {
  486. continue;
  487. }
  488. // change the matrix if needed
  489. if ( drawSurf->space != backEnd.currentSpace ) {
  490. RB_SetMVP( drawSurf->space->mvp );
  491. backEnd.currentSpace = drawSurf->space;
  492. }
  493. uint64 surfGLState = 0;
  494. // set polygon offset if necessary
  495. if ( shader->TestMaterialFlag( MF_POLYGONOFFSET ) ) {
  496. surfGLState |= GLS_POLYGON_OFFSET;
  497. GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
  498. }
  499. // subviews will just down-modulate the color buffer
  500. float color[4];
  501. if ( shader->GetSort() == SS_SUBVIEW ) {
  502. surfGLState |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS;
  503. color[0] = 1.0f;
  504. color[1] = 1.0f;
  505. color[2] = 1.0f;
  506. color[3] = 1.0f;
  507. } else {
  508. // others just draw black
  509. color[0] = 0.0f;
  510. color[1] = 0.0f;
  511. color[2] = 0.0f;
  512. color[3] = 1.0f;
  513. }
  514. renderLog.OpenBlock( shader->GetName() );
  515. bool drawSolid = false;
  516. if ( shader->Coverage() == MC_OPAQUE ) {
  517. drawSolid = true;
  518. } else if ( shader->Coverage() == MC_PERFORATED ) {
  519. // we may have multiple alpha tested stages
  520. // if the only alpha tested stages are condition register omitted,
  521. // draw a normal opaque surface
  522. bool didDraw = false;
  523. // perforated surfaces may have multiple alpha tested stages
  524. for ( stage = 0; stage < shader->GetNumStages(); stage++ ) {
  525. const shaderStage_t *pStage = shader->GetStage(stage);
  526. if ( !pStage->hasAlphaTest ) {
  527. continue;
  528. }
  529. // check the stage enable condition
  530. if ( regs[ pStage->conditionRegister ] == 0 ) {
  531. continue;
  532. }
  533. // if we at least tried to draw an alpha tested stage,
  534. // we won't draw the opaque surface
  535. didDraw = true;
  536. // set the alpha modulate
  537. color[3] = regs[ pStage->color.registers[3] ];
  538. // skip the entire stage if alpha would be black
  539. if ( color[3] <= 0.0f ) {
  540. continue;
  541. }
  542. uint64 stageGLState = surfGLState;
  543. // set privatePolygonOffset if necessary
  544. if ( pStage->privatePolygonOffset ) {
  545. GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset );
  546. stageGLState |= GLS_POLYGON_OFFSET;
  547. }
  548. GL_Color( color );
  549. #ifdef USE_CORE_PROFILE
  550. GL_State( stageGLState );
  551. idVec4 alphaTestValue( regs[ pStage->alphaTestRegister ] );
  552. SetFragmentParm( RENDERPARM_ALPHA_TEST, alphaTestValue.ToFloatPtr() );
  553. #else
  554. GL_State( stageGLState | GLS_ALPHATEST_FUNC_GREATER | GLS_ALPHATEST_MAKE_REF( idMath::Ftob( 255.0f * regs[ pStage->alphaTestRegister ] ) ) );
  555. #endif
  556. if ( drawSurf->jointCache ) {
  557. renderProgManager.BindShader_TextureVertexColorSkinned();
  558. } else {
  559. renderProgManager.BindShader_TextureVertexColor();
  560. }
  561. RB_SetVertexColorParms( SVC_IGNORE );
  562. // bind the texture
  563. GL_SelectTexture( 0 );
  564. pStage->texture.image->Bind();
  565. // set texture matrix and texGens
  566. RB_PrepareStageTexturing( pStage, drawSurf );
  567. // must render with less-equal for Z-Cull to work properly
  568. assert( ( GL_GetCurrentState() & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_LESS );
  569. // draw it
  570. RB_DrawElementsWithCounters( drawSurf );
  571. // clean up
  572. RB_FinishStageTexturing( pStage, drawSurf );
  573. // unset privatePolygonOffset if necessary
  574. if ( pStage->privatePolygonOffset ) {
  575. GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
  576. }
  577. }
  578. if ( !didDraw ) {
  579. drawSolid = true;
  580. }
  581. }
  582. // draw the entire surface solid
  583. if ( drawSolid ) {
  584. if ( shader->GetSort() == SS_SUBVIEW ) {
  585. renderProgManager.BindShader_Color();
  586. GL_Color( color );
  587. GL_State( surfGLState );
  588. } else {
  589. if ( drawSurf->jointCache ) {
  590. renderProgManager.BindShader_DepthSkinned();
  591. } else {
  592. renderProgManager.BindShader_Depth();
  593. }
  594. GL_State( surfGLState | GLS_ALPHAMASK );
  595. }
  596. // must render with less-equal for Z-Cull to work properly
  597. assert( ( GL_GetCurrentState() & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_LESS );
  598. // draw it
  599. RB_DrawElementsWithCounters( drawSurf );
  600. }
  601. renderLog.CloseBlock();
  602. }
  603. #ifdef USE_CORE_PROFILE
  604. SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
  605. #endif
  606. }
  607. /*
  608. =====================
  609. RB_FillDepthBufferFast
  610. Optimized fast path code.
  611. If there are subview surfaces, they must be guarded in the depth buffer to allow
  612. the mirror / subview to show through underneath the current view rendering.
  613. Surfaces with perforated shaders need the full shader setup done, but should be
  614. drawn after the opaque surfaces.
  615. The bulk of the surfaces should be simple opaque geometry that can be drawn very rapidly.
  616. If there are no subview surfaces, we could clear to black and use fast-Z rendering
  617. on the 360.
  618. =====================
  619. */
  620. static void RB_FillDepthBufferFast( drawSurf_t **drawSurfs, int numDrawSurfs ) {
  621. if ( numDrawSurfs == 0 ) {
  622. return;
  623. }
  624. // if we are just doing 2D rendering, no need to fill the depth buffer
  625. if ( backEnd.viewDef->viewEntitys == NULL ) {
  626. return;
  627. }
  628. renderLog.OpenMainBlock( MRB_FILL_DEPTH_BUFFER );
  629. renderLog.OpenBlock( "RB_FillDepthBufferFast" );
  630. GL_StartDepthPass( backEnd.viewDef->scissor );
  631. // force MVP change on first surface
  632. backEnd.currentSpace = NULL;
  633. // draw all the subview surfaces, which will already be at the start of the sorted list,
  634. // with the general purpose path
  635. GL_State( GLS_DEFAULT );
  636. int surfNum;
  637. for ( surfNum = 0; surfNum < numDrawSurfs; surfNum++ ) {
  638. if ( drawSurfs[surfNum]->material->GetSort() != SS_SUBVIEW ) {
  639. break;
  640. }
  641. RB_FillDepthBufferGeneric( &drawSurfs[surfNum], 1 );
  642. }
  643. const drawSurf_t ** perforatedSurfaces = (const drawSurf_t ** )_alloca( numDrawSurfs * sizeof( drawSurf_t * ) );
  644. int numPerforatedSurfaces = 0;
  645. // draw all the opaque surfaces and build up a list of perforated surfaces that
  646. // we will defer drawing until all opaque surfaces are done
  647. GL_State( GLS_DEFAULT );
  648. // continue checking past the subview surfaces
  649. for ( ; surfNum < numDrawSurfs; surfNum++ ) {
  650. const drawSurf_t * surf = drawSurfs[ surfNum ];
  651. const idMaterial * shader = surf->material;
  652. // translucent surfaces don't put anything in the depth buffer
  653. if ( shader->Coverage() == MC_TRANSLUCENT ) {
  654. continue;
  655. }
  656. if ( shader->Coverage() == MC_PERFORATED ) {
  657. // save for later drawing
  658. perforatedSurfaces[ numPerforatedSurfaces ] = surf;
  659. numPerforatedSurfaces++;
  660. continue;
  661. }
  662. // set polygon offset?
  663. // set mvp matrix
  664. if ( surf->space != backEnd.currentSpace ) {
  665. RB_SetMVP( surf->space->mvp );
  666. backEnd.currentSpace = surf->space;
  667. }
  668. renderLog.OpenBlock( shader->GetName() );
  669. if ( surf->jointCache ) {
  670. renderProgManager.BindShader_DepthSkinned();
  671. } else {
  672. renderProgManager.BindShader_Depth();
  673. }
  674. // must render with less-equal for Z-Cull to work properly
  675. assert( ( GL_GetCurrentState() & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_LESS );
  676. // draw it solid
  677. RB_DrawElementsWithCounters( surf );
  678. renderLog.CloseBlock();
  679. }
  680. // draw all perforated surfaces with the general code path
  681. if ( numPerforatedSurfaces > 0 ) {
  682. RB_FillDepthBufferGeneric( perforatedSurfaces, numPerforatedSurfaces );
  683. }
  684. // Allow platform specific data to be collected after the depth pass.
  685. GL_FinishDepthPass();
  686. renderLog.CloseBlock();
  687. renderLog.CloseMainBlock();
  688. }
  689. /*
  690. =========================================================================================
  691. GENERAL INTERACTION RENDERING
  692. =========================================================================================
  693. */
  694. const int INTERACTION_TEXUNIT_BUMP = 0;
  695. const int INTERACTION_TEXUNIT_FALLOFF = 1;
  696. const int INTERACTION_TEXUNIT_PROJECTION = 2;
  697. const int INTERACTION_TEXUNIT_DIFFUSE = 3;
  698. const int INTERACTION_TEXUNIT_SPECULAR = 4;
  699. /*
  700. ==================
  701. RB_SetupInteractionStage
  702. ==================
  703. */
  704. static void RB_SetupInteractionStage( const shaderStage_t *surfaceStage, const float *surfaceRegs, const float lightColor[4],
  705. idVec4 matrix[2], float color[4] ) {
  706. if ( surfaceStage->texture.hasMatrix ) {
  707. matrix[0][0] = surfaceRegs[surfaceStage->texture.matrix[0][0]];
  708. matrix[0][1] = surfaceRegs[surfaceStage->texture.matrix[0][1]];
  709. matrix[0][2] = 0.0f;
  710. matrix[0][3] = surfaceRegs[surfaceStage->texture.matrix[0][2]];
  711. matrix[1][0] = surfaceRegs[surfaceStage->texture.matrix[1][0]];
  712. matrix[1][1] = surfaceRegs[surfaceStage->texture.matrix[1][1]];
  713. matrix[1][2] = 0.0f;
  714. matrix[1][3] = surfaceRegs[surfaceStage->texture.matrix[1][2]];
  715. // we attempt to keep scrolls from generating incredibly large texture values, but
  716. // center rotations and center scales can still generate offsets that need to be > 1
  717. if ( matrix[0][3] < -40.0f || matrix[0][3] > 40.0f ) {
  718. matrix[0][3] -= idMath::Ftoi( matrix[0][3] );
  719. }
  720. if ( matrix[1][3] < -40.0f || matrix[1][3] > 40.0f ) {
  721. matrix[1][3] -= idMath::Ftoi( matrix[1][3] );
  722. }
  723. } else {
  724. matrix[0][0] = 1.0f;
  725. matrix[0][1] = 0.0f;
  726. matrix[0][2] = 0.0f;
  727. matrix[0][3] = 0.0f;
  728. matrix[1][0] = 0.0f;
  729. matrix[1][1] = 1.0f;
  730. matrix[1][2] = 0.0f;
  731. matrix[1][3] = 0.0f;
  732. }
  733. if ( color != NULL ) {
  734. for ( int i = 0; i < 4; i++ ) {
  735. // clamp here, so cards with a greater range don't look different.
  736. // we could perform overbrighting like we do for lights, but
  737. // it doesn't currently look worth it.
  738. color[i] = idMath::ClampFloat( 0.0f, 1.0f, surfaceRegs[surfaceStage->color.registers[i]] ) * lightColor[i];
  739. }
  740. }
  741. }
  742. /*
  743. =================
  744. RB_DrawSingleInteraction
  745. =================
  746. */
  747. static void RB_DrawSingleInteraction( drawInteraction_t * din ) {
  748. if ( din->bumpImage == NULL ) {
  749. // stage wasn't actually an interaction
  750. return;
  751. }
  752. if ( din->diffuseImage == NULL || r_skipDiffuse.GetBool() ) {
  753. // this isn't a YCoCg black, but it doesn't matter, because
  754. // the diffuseColor will also be 0
  755. din->diffuseImage = globalImages->blackImage;
  756. }
  757. if ( din->specularImage == NULL || r_skipSpecular.GetBool() || din->ambientLight ) {
  758. din->specularImage = globalImages->blackImage;
  759. }
  760. if ( r_skipBump.GetBool() ) {
  761. din->bumpImage = globalImages->flatNormalMap;
  762. }
  763. // if we wouldn't draw anything, don't call the Draw function
  764. const bool diffuseIsBlack = ( din->diffuseImage == globalImages->blackImage )
  765. || ( ( din->diffuseColor[0] <= 0 ) && ( din->diffuseColor[1] <= 0 ) && ( din->diffuseColor[2] <= 0 ) );
  766. const bool specularIsBlack = ( din->specularImage == globalImages->blackImage )
  767. || ( ( din->specularColor[0] <= 0 ) && ( din->specularColor[1] <= 0 ) && ( din->specularColor[2] <= 0 ) );
  768. if ( diffuseIsBlack && specularIsBlack ) {
  769. return;
  770. }
  771. // bump matrix
  772. SetVertexParm( RENDERPARM_BUMPMATRIX_S, din->bumpMatrix[0].ToFloatPtr() );
  773. SetVertexParm( RENDERPARM_BUMPMATRIX_T, din->bumpMatrix[1].ToFloatPtr() );
  774. // diffuse matrix
  775. SetVertexParm( RENDERPARM_DIFFUSEMATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
  776. SetVertexParm( RENDERPARM_DIFFUSEMATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
  777. // specular matrix
  778. SetVertexParm( RENDERPARM_SPECULARMATRIX_S, din->specularMatrix[0].ToFloatPtr() );
  779. SetVertexParm( RENDERPARM_SPECULARMATRIX_T, din->specularMatrix[1].ToFloatPtr() );
  780. RB_SetVertexColorParms( din->vertexColor );
  781. SetFragmentParm( RENDERPARM_DIFFUSEMODIFIER, din->diffuseColor.ToFloatPtr() );
  782. SetFragmentParm( RENDERPARM_SPECULARMODIFIER, din->specularColor.ToFloatPtr() );
  783. // texture 0 will be the per-surface bump map
  784. GL_SelectTexture( INTERACTION_TEXUNIT_BUMP );
  785. din->bumpImage->Bind();
  786. // texture 3 is the per-surface diffuse map
  787. GL_SelectTexture( INTERACTION_TEXUNIT_DIFFUSE );
  788. din->diffuseImage->Bind();
  789. // texture 4 is the per-surface specular map
  790. GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR );
  791. din->specularImage->Bind();
  792. RB_DrawElementsWithCounters( din->surf );
  793. }
  794. /*
  795. =================
  796. RB_SetupForFastPathInteractions
  797. These are common for all fast path surfaces
  798. =================
  799. */
  800. static void RB_SetupForFastPathInteractions( const idVec4 & diffuseColor, const idVec4 & specularColor ) {
  801. const idVec4 sMatrix( 1, 0, 0, 0 );
  802. const idVec4 tMatrix( 0, 1, 0, 0 );
  803. // bump matrix
  804. SetVertexParm( RENDERPARM_BUMPMATRIX_S, sMatrix.ToFloatPtr() );
  805. SetVertexParm( RENDERPARM_BUMPMATRIX_T, tMatrix.ToFloatPtr() );
  806. // diffuse matrix
  807. SetVertexParm( RENDERPARM_DIFFUSEMATRIX_S, sMatrix.ToFloatPtr() );
  808. SetVertexParm( RENDERPARM_DIFFUSEMATRIX_T, tMatrix.ToFloatPtr() );
  809. // specular matrix
  810. SetVertexParm( RENDERPARM_SPECULARMATRIX_S, sMatrix.ToFloatPtr() );
  811. SetVertexParm( RENDERPARM_SPECULARMATRIX_T, tMatrix.ToFloatPtr() );
  812. RB_SetVertexColorParms( SVC_IGNORE );
  813. SetFragmentParm( RENDERPARM_DIFFUSEMODIFIER, diffuseColor.ToFloatPtr() );
  814. SetFragmentParm( RENDERPARM_SPECULARMODIFIER, specularColor.ToFloatPtr() );
  815. }
  816. /*
  817. =============
  818. RB_RenderInteractions
  819. With added sorting and trivial path work.
  820. =============
  821. */
  822. static void RB_RenderInteractions( const drawSurf_t *surfList, const viewLight_t * vLight, int depthFunc, bool performStencilTest, bool useLightDepthBounds ) {
  823. if ( surfList == NULL ) {
  824. return;
  825. }
  826. // change the scissor if needed, it will be constant across all the surfaces lit by the light
  827. if ( !backEnd.currentScissor.Equals( vLight->scissorRect ) && r_useScissor.GetBool() ) {
  828. GL_Scissor( backEnd.viewDef->viewport.x1 + vLight->scissorRect.x1,
  829. backEnd.viewDef->viewport.y1 + vLight->scissorRect.y1,
  830. vLight->scissorRect.x2 + 1 - vLight->scissorRect.x1,
  831. vLight->scissorRect.y2 + 1 - vLight->scissorRect.y1 );
  832. backEnd.currentScissor = vLight->scissorRect;
  833. }
  834. // perform setup here that will be constant for all interactions
  835. if ( performStencilTest ) {
  836. GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | depthFunc | GLS_STENCIL_FUNC_EQUAL | GLS_STENCIL_MAKE_REF( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK( STENCIL_SHADOW_MASK_VALUE ) );
  837. } else {
  838. GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | depthFunc | GLS_STENCIL_FUNC_ALWAYS );
  839. }
  840. // some rare lights have multiple animating stages, loop over them outside the surface list
  841. const idMaterial * lightShader = vLight->lightShader;
  842. const float * lightRegs = vLight->shaderRegisters;
  843. drawInteraction_t inter = {};
  844. inter.ambientLight = lightShader->IsAmbientLight();
  845. //---------------------------------
  846. // Split out the complex surfaces from the fast-path surfaces
  847. // so we can do the fast path ones all in a row.
  848. // The surfaces should already be sorted by space because they
  849. // are added single-threaded, and there is only a negligable amount
  850. // of benefit to trying to sort by materials.
  851. //---------------------------------
  852. static const int MAX_INTERACTIONS_PER_LIGHT = 1024;
  853. static const int MAX_COMPLEX_INTERACTIONS_PER_LIGHT = 128;
  854. idStaticList< const drawSurf_t *, MAX_INTERACTIONS_PER_LIGHT > allSurfaces;
  855. idStaticList< const drawSurf_t *, MAX_COMPLEX_INTERACTIONS_PER_LIGHT > complexSurfaces;
  856. for ( const drawSurf_t * walk = surfList; walk != NULL; walk = walk->nextOnLight ) {
  857. // make sure the triangle culling is done
  858. if ( walk->shadowVolumeState != SHADOWVOLUME_DONE ) {
  859. assert( walk->shadowVolumeState == SHADOWVOLUME_UNFINISHED || walk->shadowVolumeState == SHADOWVOLUME_DONE );
  860. uint64 start = Sys_Microseconds();
  861. while ( walk->shadowVolumeState == SHADOWVOLUME_UNFINISHED ) {
  862. Sys_Yield();
  863. }
  864. uint64 end = Sys_Microseconds();
  865. backEnd.pc.shadowMicroSec += end - start;
  866. }
  867. const idMaterial * surfaceShader = walk->material;
  868. if ( surfaceShader->GetFastPathBumpImage() ) {
  869. allSurfaces.Append( walk );
  870. } else {
  871. complexSurfaces.Append( walk );
  872. }
  873. }
  874. for ( int i = 0; i < complexSurfaces.Num(); i++ ) {
  875. allSurfaces.Append( complexSurfaces[i] );
  876. }
  877. bool lightDepthBoundsDisabled = false;
  878. for ( int lightStageNum = 0; lightStageNum < lightShader->GetNumStages(); lightStageNum++ ) {
  879. const shaderStage_t *lightStage = lightShader->GetStage( lightStageNum );
  880. // ignore stages that fail the condition
  881. if ( !lightRegs[ lightStage->conditionRegister ] ) {
  882. continue;
  883. }
  884. const float lightScale = r_lightScale.GetFloat();
  885. const idVec4 lightColor(
  886. lightScale * lightRegs[ lightStage->color.registers[0] ],
  887. lightScale * lightRegs[ lightStage->color.registers[1] ],
  888. lightScale * lightRegs[ lightStage->color.registers[2] ],
  889. lightRegs[ lightStage->color.registers[3] ] );
  890. // apply the world-global overbright and the 2x factor for specular
  891. const idVec4 diffuseColor = lightColor;
  892. const idVec4 specularColor = lightColor * 2.0f;
  893. float lightTextureMatrix[16];
  894. if ( lightStage->texture.hasMatrix ) {
  895. RB_GetShaderTextureMatrix( lightRegs, &lightStage->texture, lightTextureMatrix );
  896. }
  897. // texture 1 will be the light falloff texture
  898. GL_SelectTexture( INTERACTION_TEXUNIT_FALLOFF );
  899. vLight->falloffImage->Bind();
  900. // texture 2 will be the light projection texture
  901. GL_SelectTexture( INTERACTION_TEXUNIT_PROJECTION );
  902. lightStage->texture.image->Bind();
  903. // force the light textures to not use anisotropic filtering, which is wasted on them
  904. // all of the texture sampler parms should be constant for all interactions, only
  905. // the actual texture image bindings will change
  906. //----------------------------------
  907. // For all surfaces on this light list, generate an interaction for this light stage
  908. //----------------------------------
  909. // setup renderparms assuming we will be drawing trivial surfaces first
  910. RB_SetupForFastPathInteractions( diffuseColor, specularColor );
  911. // even if the space does not change between light stages, each light stage may need a different lightTextureMatrix baked in
  912. backEnd.currentSpace = NULL;
  913. for ( int sortedSurfNum = 0; sortedSurfNum < allSurfaces.Num(); sortedSurfNum++ ) {
  914. const drawSurf_t * const surf = allSurfaces[ sortedSurfNum ];
  915. // select the render prog
  916. if ( lightShader->IsAmbientLight() ) {
  917. if ( surf->jointCache ) {
  918. renderProgManager.BindShader_InteractionAmbientSkinned();
  919. } else {
  920. renderProgManager.BindShader_InteractionAmbient();
  921. }
  922. } else {
  923. if ( surf->jointCache ) {
  924. renderProgManager.BindShader_InteractionSkinned();
  925. } else {
  926. renderProgManager.BindShader_Interaction();
  927. }
  928. }
  929. const idMaterial * surfaceShader = surf->material;
  930. const float * surfaceRegs = surf->shaderRegisters;
  931. inter.surf = surf;
  932. // change the MVP matrix, view/light origin and light projection vectors if needed
  933. if ( surf->space != backEnd.currentSpace ) {
  934. backEnd.currentSpace = surf->space;
  935. // turn off the light depth bounds test if this model is rendered with a depth hack
  936. if ( useLightDepthBounds ) {
  937. if ( !surf->space->weaponDepthHack && surf->space->modelDepthHack == 0.0f ) {
  938. if ( lightDepthBoundsDisabled ) {
  939. GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
  940. lightDepthBoundsDisabled = false;
  941. }
  942. } else {
  943. if ( !lightDepthBoundsDisabled ) {
  944. GL_DepthBoundsTest( 0.0f, 0.0f );
  945. lightDepthBoundsDisabled = true;
  946. }
  947. }
  948. }
  949. // model-view-projection
  950. RB_SetMVP( surf->space->mvp );
  951. // tranform the light/view origin into model local space
  952. idVec4 localLightOrigin( 0.0f );
  953. idVec4 localViewOrigin( 1.0f );
  954. R_GlobalPointToLocal( surf->space->modelMatrix, vLight->globalLightOrigin, localLightOrigin.ToVec3() );
  955. R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.viewDef->renderView.vieworg, localViewOrigin.ToVec3() );
  956. // set the local light/view origin
  957. SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLightOrigin.ToFloatPtr() );
  958. SetVertexParm( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() );
  959. // transform the light project into model local space
  960. idPlane lightProjection[4];
  961. for ( int i = 0; i < 4; i++ ) {
  962. R_GlobalPlaneToLocal( surf->space->modelMatrix, vLight->lightProject[i], lightProjection[i] );
  963. }
  964. // optionally multiply the local light projection by the light texture matrix
  965. if ( lightStage->texture.hasMatrix ) {
  966. RB_BakeTextureMatrixIntoTexgen( lightProjection, lightTextureMatrix );
  967. }
  968. // set the light projection
  969. SetVertexParm( RENDERPARM_LIGHTPROJECTION_S, lightProjection[0].ToFloatPtr() );
  970. SetVertexParm( RENDERPARM_LIGHTPROJECTION_T, lightProjection[1].ToFloatPtr() );
  971. SetVertexParm( RENDERPARM_LIGHTPROJECTION_Q, lightProjection[2].ToFloatPtr() );
  972. SetVertexParm( RENDERPARM_LIGHTFALLOFF_S, lightProjection[3].ToFloatPtr() );
  973. }
  974. // check for the fast path
  975. if ( surfaceShader->GetFastPathBumpImage() && !r_skipInteractionFastPath.GetBool() ) {
  976. renderLog.OpenBlock( surf->material->GetName() );
  977. // texture 0 will be the per-surface bump map
  978. GL_SelectTexture( INTERACTION_TEXUNIT_BUMP );
  979. surfaceShader->GetFastPathBumpImage()->Bind();
  980. // texture 3 is the per-surface diffuse map
  981. GL_SelectTexture( INTERACTION_TEXUNIT_DIFFUSE );
  982. surfaceShader->GetFastPathDiffuseImage()->Bind();
  983. // texture 4 is the per-surface specular map
  984. GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR );
  985. surfaceShader->GetFastPathSpecularImage()->Bind();
  986. RB_DrawElementsWithCounters( surf );
  987. renderLog.CloseBlock();
  988. continue;
  989. }
  990. renderLog.OpenBlock( surf->material->GetName() );
  991. inter.bumpImage = NULL;
  992. inter.specularImage = NULL;
  993. inter.diffuseImage = NULL;
  994. inter.diffuseColor[0] = inter.diffuseColor[1] = inter.diffuseColor[2] = inter.diffuseColor[3] = 0;
  995. inter.specularColor[0] = inter.specularColor[1] = inter.specularColor[2] = inter.specularColor[3] = 0;
  996. // go through the individual surface stages
  997. //
  998. // This is somewhat arcane because of the old support for video cards that had to render
  999. // interactions in multiple passes.
  1000. //
  1001. // We also have the very rare case of some materials that have conditional interactions
  1002. // for the "hell writing" that can be shined on them.
  1003. for ( int surfaceStageNum = 0; surfaceStageNum < surfaceShader->GetNumStages(); surfaceStageNum++ ) {
  1004. const shaderStage_t *surfaceStage = surfaceShader->GetStage( surfaceStageNum );
  1005. switch( surfaceStage->lighting ) {
  1006. case SL_COVERAGE: {
  1007. // ignore any coverage stages since they should only be used for the depth fill pass
  1008. // for diffuse stages that use alpha test.
  1009. break;
  1010. }
  1011. case SL_AMBIENT: {
  1012. // ignore ambient stages while drawing interactions
  1013. break;
  1014. }
  1015. case SL_BUMP: {
  1016. // ignore stage that fails the condition
  1017. if ( !surfaceRegs[ surfaceStage->conditionRegister ] ) {
  1018. break;
  1019. }
  1020. // draw any previous interaction
  1021. if ( inter.bumpImage != NULL ) {
  1022. RB_DrawSingleInteraction( &inter );
  1023. }
  1024. inter.bumpImage = surfaceStage->texture.image;
  1025. inter.diffuseImage = NULL;
  1026. inter.specularImage = NULL;
  1027. RB_SetupInteractionStage( surfaceStage, surfaceRegs, NULL,
  1028. inter.bumpMatrix, NULL );
  1029. break;
  1030. }
  1031. case SL_DIFFUSE: {
  1032. // ignore stage that fails the condition
  1033. if ( !surfaceRegs[ surfaceStage->conditionRegister ] ) {
  1034. break;
  1035. }
  1036. // draw any previous interaction
  1037. if ( inter.diffuseImage != NULL ) {
  1038. RB_DrawSingleInteraction( &inter );
  1039. }
  1040. inter.diffuseImage = surfaceStage->texture.image;
  1041. inter.vertexColor = surfaceStage->vertexColor;
  1042. RB_SetupInteractionStage( surfaceStage, surfaceRegs, diffuseColor.ToFloatPtr(),
  1043. inter.diffuseMatrix, inter.diffuseColor.ToFloatPtr() );
  1044. break;
  1045. }
  1046. case SL_SPECULAR: {
  1047. // ignore stage that fails the condition
  1048. if ( !surfaceRegs[ surfaceStage->conditionRegister ] ) {
  1049. break;
  1050. }
  1051. // draw any previous interaction
  1052. if ( inter.specularImage != NULL ) {
  1053. RB_DrawSingleInteraction( &inter );
  1054. }
  1055. inter.specularImage = surfaceStage->texture.image;
  1056. inter.vertexColor = surfaceStage->vertexColor;
  1057. RB_SetupInteractionStage( surfaceStage, surfaceRegs, specularColor.ToFloatPtr(),
  1058. inter.specularMatrix, inter.specularColor.ToFloatPtr() );
  1059. break;
  1060. }
  1061. }
  1062. }
  1063. // draw the final interaction
  1064. RB_DrawSingleInteraction( &inter );
  1065. renderLog.CloseBlock();
  1066. }
  1067. }
  1068. if ( useLightDepthBounds && lightDepthBoundsDisabled ) {
  1069. GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
  1070. }
  1071. renderProgManager.Unbind();
  1072. }
  1073. /*
  1074. ==============================================================================================
  1075. STENCIL SHADOW RENDERING
  1076. ==============================================================================================
  1077. */
  1078. /*
  1079. =====================
  1080. RB_StencilShadowPass
  1081. The stencil buffer should have been set to 128 on any surfaces that might receive shadows.
  1082. =====================
  1083. */
  1084. static void RB_StencilShadowPass( const drawSurf_t *drawSurfs, const viewLight_t * vLight ) {
  1085. if ( r_skipShadows.GetBool() ) {
  1086. return;
  1087. }
  1088. if ( drawSurfs == NULL ) {
  1089. return;
  1090. }
  1091. RENDERLOG_PRINTF( "---------- RB_StencilShadowPass ----------\n" );
  1092. renderProgManager.BindShader_Shadow();
  1093. GL_SelectTexture( 0 );
  1094. globalImages->BindNull();
  1095. uint64 glState = 0;
  1096. // for visualizing the shadows
  1097. if ( r_showShadows.GetInteger() ) {
  1098. // set the debug shadow color
  1099. SetFragmentParm( RENDERPARM_COLOR, colorMagenta.ToFloatPtr() );
  1100. if ( r_showShadows.GetInteger() == 2 ) {
  1101. // draw filled in
  1102. glState = GLS_DEPTHMASK | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_LESS;
  1103. } else {
  1104. // draw as lines, filling the depth buffer
  1105. glState = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS;
  1106. }
  1107. } else {
  1108. // don't write to the color or depth buffer, just the stencil buffer
  1109. glState = GLS_DEPTHMASK | GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHFUNC_LESS;
  1110. }
  1111. GL_PolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() );
  1112. // the actual stencil func will be set in the draw code, but we need to make sure it isn't
  1113. // disabled here, and that the value will get reset for the interactions without looking
  1114. // like a no-change-required
  1115. GL_State( glState | GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_KEEP | GLS_STENCIL_OP_PASS_INCR |
  1116. GLS_STENCIL_MAKE_REF( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK( STENCIL_SHADOW_MASK_VALUE ) | GLS_POLYGON_OFFSET );
  1117. // Two Sided Stencil reduces two draw calls to one for slightly faster shadows
  1118. GL_Cull( CT_TWO_SIDED );
  1119. // process the chain of shadows with the current rendering state
  1120. backEnd.currentSpace = NULL;
  1121. for ( const drawSurf_t * drawSurf = drawSurfs; drawSurf != NULL; drawSurf = drawSurf->nextOnLight ) {
  1122. if ( drawSurf->scissorRect.IsEmpty() ) {
  1123. continue; // !@# FIXME: find out why this is sometimes being hit!
  1124. // temporarily jump over the scissor and draw so the gl error callback doesn't get hit
  1125. }
  1126. // make sure the shadow volume is done
  1127. if ( drawSurf->shadowVolumeState != SHADOWVOLUME_DONE ) {
  1128. assert( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED || drawSurf->shadowVolumeState == SHADOWVOLUME_DONE );
  1129. uint64 start = Sys_Microseconds();
  1130. while ( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED ) {
  1131. Sys_Yield();
  1132. }
  1133. uint64 end = Sys_Microseconds();
  1134. backEnd.pc.shadowMicroSec += end - start;
  1135. }
  1136. if ( drawSurf->numIndexes == 0 ) {
  1137. continue; // a job may have created an empty shadow volume
  1138. }
  1139. if ( !backEnd.currentScissor.Equals( drawSurf->scissorRect ) && r_useScissor.GetBool() ) {
  1140. // change the scissor
  1141. GL_Scissor( backEnd.viewDef->viewport.x1 + drawSurf->scissorRect.x1,
  1142. backEnd.viewDef->viewport.y1 + drawSurf->scissorRect.y1,
  1143. drawSurf->scissorRect.x2 + 1 - drawSurf->scissorRect.x1,
  1144. drawSurf->scissorRect.y2 + 1 - drawSurf->scissorRect.y1 );
  1145. backEnd.currentScissor = drawSurf->scissorRect;
  1146. }
  1147. if ( drawSurf->space != backEnd.currentSpace ) {
  1148. // change the matrix
  1149. RB_SetMVP( drawSurf->space->mvp );
  1150. // set the local light position to allow the vertex program to project the shadow volume end cap to infinity
  1151. idVec4 localLight( 0.0f );
  1152. R_GlobalPointToLocal( drawSurf->space->modelMatrix, vLight->globalLightOrigin, localLight.ToVec3() );
  1153. SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLight.ToFloatPtr() );
  1154. backEnd.currentSpace = drawSurf->space;
  1155. }
  1156. if ( r_showShadows.GetInteger() == 0 ) {
  1157. if ( drawSurf->jointCache ) {
  1158. renderProgManager.BindShader_ShadowSkinned();
  1159. } else {
  1160. renderProgManager.BindShader_Shadow();
  1161. }
  1162. } else {
  1163. if ( drawSurf->jointCache ) {
  1164. renderProgManager.BindShader_ShadowDebugSkinned();
  1165. } else {
  1166. renderProgManager.BindShader_ShadowDebug();
  1167. }
  1168. }
  1169. // set depth bounds per shadow
  1170. if ( r_useShadowDepthBounds.GetBool() ) {
  1171. GL_DepthBoundsTest( drawSurf->scissorRect.zmin, drawSurf->scissorRect.zmax );
  1172. }
  1173. // Determine whether or not the shadow volume needs to be rendered with Z-pass or
  1174. // Z-fail. It is worthwhile to spend significant resources to reduce the number of
  1175. // cases where shadow volumes need to be rendered with Z-fail because Z-fail
  1176. // rendering can be significantly slower even on today's hardware. For instance,
  1177. // on NVIDIA hardware Z-fail rendering causes the Z-Cull to be used in reverse:
  1178. // Z-near becomes Z-far (trivial accept becomes trivial reject). Using the Z-Cull
  1179. // in reverse is far less efficient because the Z-Cull only stores Z-near per 16x16
  1180. // pixels while the Z-far is stored per 4x2 pixels. (The Z-near coallesce buffer
  1181. // which has 4x4 granularity is only used when updating the depth which is not the
  1182. // case for shadow volumes.) Note that it is also important to NOT use a Z-Cull
  1183. // reconstruct because that would clear the Z-near of the Z-Cull which results in
  1184. // no trivial rejection for Z-fail stencil shadow rendering.
  1185. const bool renderZPass = ( drawSurf->renderZFail == 0 ) || r_forceZPassStencilShadows.GetBool();
  1186. if ( renderZPass ) {
  1187. // Z-pass
  1188. qglStencilOpSeparate( GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR );
  1189. qglStencilOpSeparate( GL_BACK, GL_KEEP, GL_KEEP, GL_DECR );
  1190. } else if ( r_useStencilShadowPreload.GetBool() ) {
  1191. // preload + Z-pass
  1192. qglStencilOpSeparate( GL_FRONT, GL_KEEP, GL_DECR, GL_DECR );
  1193. qglStencilOpSeparate( GL_BACK, GL_KEEP, GL_INCR, GL_INCR );
  1194. } else {
  1195. // Z-fail
  1196. }
  1197. // get vertex buffer
  1198. const vertCacheHandle_t vbHandle = drawSurf->shadowCache;
  1199. idVertexBuffer * vertexBuffer;
  1200. if ( vertexCache.CacheIsStatic( vbHandle ) ) {
  1201. vertexBuffer = &vertexCache.staticData.vertexBuffer;
  1202. } else {
  1203. const uint64 frameNum = (int)( vbHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  1204. if ( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) ) {
  1205. idLib::Warning( "RB_DrawElementsWithCounters, vertexBuffer == NULL" );
  1206. continue;
  1207. }
  1208. vertexBuffer = &vertexCache.frameData[vertexCache.drawListNum].vertexBuffer;
  1209. }
  1210. const int vertOffset = (int)( vbHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
  1211. // get index buffer
  1212. const vertCacheHandle_t ibHandle = drawSurf->indexCache;
  1213. idIndexBuffer * indexBuffer;
  1214. if ( vertexCache.CacheIsStatic( ibHandle ) ) {
  1215. indexBuffer = &vertexCache.staticData.indexBuffer;
  1216. } else {
  1217. const uint64 frameNum = (int)( ibHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  1218. if ( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) ) {
  1219. idLib::Warning( "RB_DrawElementsWithCounters, indexBuffer == NULL" );
  1220. continue;
  1221. }
  1222. indexBuffer = &vertexCache.frameData[vertexCache.drawListNum].indexBuffer;
  1223. }
  1224. const uint64 indexOffset = (int)( ibHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
  1225. RENDERLOG_PRINTF( "Binding Buffers: %p %p\n", vertexBuffer, indexBuffer );
  1226. if ( backEnd.glState.currentIndexBuffer != (GLuint)indexBuffer->GetAPIObject() || !r_useStateCaching.GetBool() ) {
  1227. qglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, (GLuint)indexBuffer->GetAPIObject() );
  1228. backEnd.glState.currentIndexBuffer = (GLuint)indexBuffer->GetAPIObject();
  1229. }
  1230. if ( drawSurf->jointCache ) {
  1231. assert( renderProgManager.ShaderUsesJoints() );
  1232. idJointBuffer jointBuffer;
  1233. if ( !vertexCache.GetJointBuffer( drawSurf->jointCache, &jointBuffer ) ) {
  1234. idLib::Warning( "RB_DrawElementsWithCounters, jointBuffer == NULL" );
  1235. continue;
  1236. }
  1237. assert( ( jointBuffer.GetOffset() & ( glConfig.uniformBufferOffsetAlignment - 1 ) ) == 0 );
  1238. const GLuint ubo = reinterpret_cast< GLuint >( jointBuffer.GetAPIObject() );
  1239. qglBindBufferRange( GL_UNIFORM_BUFFER, 0, ubo, jointBuffer.GetOffset(), jointBuffer.GetNumJoints() * sizeof( idJointMat ) );
  1240. if ( ( backEnd.glState.vertexLayout != LAYOUT_DRAW_SHADOW_VERT_SKINNED) || ( backEnd.glState.currentVertexBuffer != (GLuint)vertexBuffer->GetAPIObject() ) || !r_useStateCaching.GetBool() ) {
  1241. qglBindBufferARB( GL_ARRAY_BUFFER_ARB, (GLuint)vertexBuffer->GetAPIObject() );
  1242. backEnd.glState.currentVertexBuffer = (GLuint)vertexBuffer->GetAPIObject();
  1243. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_VERTEX );
  1244. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_NORMAL );
  1245. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_COLOR );
  1246. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_COLOR2 );
  1247. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_ST );
  1248. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_TANGENT );
  1249. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_VERTEX, 4, GL_FLOAT, GL_FALSE, sizeof( idShadowVertSkinned ), (void *)( SHADOWVERTSKINNED_XYZW_OFFSET ) );
  1250. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( idShadowVertSkinned ), (void *)( SHADOWVERTSKINNED_COLOR_OFFSET ) );
  1251. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_COLOR2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( idShadowVertSkinned ), (void *)( SHADOWVERTSKINNED_COLOR2_OFFSET ) );
  1252. backEnd.glState.vertexLayout = LAYOUT_DRAW_SHADOW_VERT_SKINNED;
  1253. }
  1254. } else {
  1255. if ( ( backEnd.glState.vertexLayout != LAYOUT_DRAW_SHADOW_VERT ) || ( backEnd.glState.currentVertexBuffer != (GLuint)vertexBuffer->GetAPIObject() ) || !r_useStateCaching.GetBool() ) {
  1256. qglBindBufferARB( GL_ARRAY_BUFFER_ARB, (GLuint)vertexBuffer->GetAPIObject() );
  1257. backEnd.glState.currentVertexBuffer = (GLuint)vertexBuffer->GetAPIObject();
  1258. qglEnableVertexAttribArrayARB( PC_ATTRIB_INDEX_VERTEX );
  1259. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_NORMAL );
  1260. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_COLOR );
  1261. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_COLOR2 );
  1262. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_ST );
  1263. qglDisableVertexAttribArrayARB( PC_ATTRIB_INDEX_TANGENT );
  1264. qglVertexAttribPointerARB( PC_ATTRIB_INDEX_VERTEX, 4, GL_FLOAT, GL_FALSE, sizeof( idShadowVert ), (void *)( SHADOWVERT_XYZW_OFFSET ) );
  1265. backEnd.glState.vertexLayout = LAYOUT_DRAW_SHADOW_VERT;
  1266. }
  1267. }
  1268. renderProgManager.CommitUniforms();
  1269. if ( drawSurf->jointCache ) {
  1270. qglDrawElementsBaseVertex( GL_TRIANGLES, r_singleTriangle.GetBool() ? 3 : drawSurf->numIndexes, GL_INDEX_TYPE, (triIndex_t *)indexOffset, vertOffset / sizeof( idShadowVertSkinned ) );
  1271. } else {
  1272. qglDrawElementsBaseVertex( GL_TRIANGLES, r_singleTriangle.GetBool() ? 3 : drawSurf->numIndexes, GL_INDEX_TYPE, (triIndex_t *)indexOffset, vertOffset / sizeof( idShadowVert ) );
  1273. }
  1274. if ( !renderZPass && r_useStencilShadowPreload.GetBool() ) {
  1275. // render again with Z-pass
  1276. qglStencilOpSeparate( GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR );
  1277. qglStencilOpSeparate( GL_BACK, GL_KEEP, GL_KEEP, GL_DECR );
  1278. if ( drawSurf->jointCache ) {
  1279. qglDrawElementsBaseVertex( GL_TRIANGLES, r_singleTriangle.GetBool() ? 3 : drawSurf->numIndexes, GL_INDEX_TYPE, (triIndex_t *)indexOffset, vertOffset / sizeof ( idShadowVertSkinned ) );
  1280. } else {
  1281. qglDrawElementsBaseVertex( GL_TRIANGLES, r_singleTriangle.GetBool() ? 3 : drawSurf->numIndexes, GL_INDEX_TYPE, (triIndex_t *)indexOffset, vertOffset / sizeof ( idShadowVert ) );
  1282. }
  1283. }
  1284. }
  1285. // cleanup the shadow specific rendering state
  1286. GL_Cull( CT_FRONT_SIDED );
  1287. // reset depth bounds
  1288. if ( r_useShadowDepthBounds.GetBool() ) {
  1289. if ( r_useLightDepthBounds.GetBool() ) {
  1290. GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
  1291. } else {
  1292. GL_DepthBoundsTest( 0.0f, 0.0f );
  1293. }
  1294. }
  1295. }
  1296. /*
  1297. ==================
  1298. RB_StencilSelectLight
  1299. Deform the zeroOneCubeModel to exactly cover the light volume. Render the deformed cube model to the stencil buffer in
  1300. such a way that only fragments that are directly visible and contained within the volume will be written creating a
  1301. mask to be used by the following stencil shadow and draw interaction passes.
  1302. ==================
  1303. */
  1304. static void RB_StencilSelectLight( const viewLight_t * vLight ) {
  1305. renderLog.OpenBlock( "Stencil Select" );
  1306. // enable the light scissor
  1307. if ( !backEnd.currentScissor.Equals( vLight->scissorRect ) && r_useScissor.GetBool() ) {
  1308. GL_Scissor( backEnd.viewDef->viewport.x1 + vLight->scissorRect.x1,
  1309. backEnd.viewDef->viewport.y1 + vLight->scissorRect.y1,
  1310. vLight->scissorRect.x2 + 1 - vLight->scissorRect.x1,
  1311. vLight->scissorRect.y2 + 1 - vLight->scissorRect.y1 );
  1312. backEnd.currentScissor = vLight->scissorRect;
  1313. }
  1314. // clear stencil buffer to 0 (not drawable)
  1315. uint64 glStateMinusStencil = GL_GetCurrentStateMinusStencil();
  1316. GL_State( glStateMinusStencil | GLS_STENCIL_FUNC_ALWAYS | GLS_STENCIL_MAKE_REF( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK( STENCIL_SHADOW_MASK_VALUE ) ); // make sure stencil mask passes for the clear
  1317. GL_Clear( false, false, true, 0, 0.0f, 0.0f, 0.0f, 0.0f ); // clear to 0 for stencil select
  1318. // set the depthbounds
  1319. GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
  1320. GL_State( GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_LESS | GLS_STENCIL_FUNC_ALWAYS | GLS_STENCIL_MAKE_REF( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK( STENCIL_SHADOW_MASK_VALUE ) );
  1321. GL_Cull( CT_TWO_SIDED );
  1322. renderProgManager.BindShader_Depth();
  1323. // set the matrix for deforming the 'zeroOneCubeModel' into the frustum to exactly cover the light volume
  1324. idRenderMatrix invProjectMVPMatrix;
  1325. idRenderMatrix::Multiply( backEnd.viewDef->worldSpace.mvp, vLight->inverseBaseLightProject, invProjectMVPMatrix );
  1326. RB_SetMVP( invProjectMVPMatrix );
  1327. // two-sided stencil test
  1328. qglStencilOpSeparate( GL_FRONT, GL_KEEP, GL_REPLACE, GL_ZERO );
  1329. qglStencilOpSeparate( GL_BACK, GL_KEEP, GL_ZERO, GL_REPLACE );
  1330. RB_DrawElementsWithCounters( &backEnd.zeroOneCubeSurface );
  1331. // reset stencil state
  1332. GL_Cull( CT_FRONT_SIDED );
  1333. renderProgManager.Unbind();
  1334. // unset the depthbounds
  1335. GL_DepthBoundsTest( 0.0f, 0.0f );
  1336. renderLog.CloseBlock();
  1337. }
  1338. /*
  1339. ==============================================================================================
  1340. DRAW INTERACTIONS
  1341. ==============================================================================================
  1342. */
  1343. /*
  1344. ==================
  1345. RB_DrawInteractions
  1346. ==================
  1347. */
  1348. static void RB_DrawInteractions() {
  1349. if ( r_skipInteractions.GetBool() ) {
  1350. return;
  1351. }
  1352. renderLog.OpenMainBlock( MRB_DRAW_INTERACTIONS );
  1353. renderLog.OpenBlock( "RB_DrawInteractions" );
  1354. GL_SelectTexture( 0 );
  1355. const bool useLightDepthBounds = r_useLightDepthBounds.GetBool();
  1356. //
  1357. // for each light, perform shadowing and adding
  1358. //
  1359. for ( const viewLight_t * vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next ) {
  1360. // do fogging later
  1361. if ( vLight->lightShader->IsFogLight() ) {
  1362. continue;
  1363. }
  1364. if ( vLight->lightShader->IsBlendLight() ) {
  1365. continue;
  1366. }
  1367. if ( vLight->localInteractions == NULL && vLight->globalInteractions == NULL && vLight->translucentInteractions == NULL ) {
  1368. continue;
  1369. }
  1370. const idMaterial * lightShader = vLight->lightShader;
  1371. renderLog.OpenBlock( lightShader->GetName() );
  1372. // set the depth bounds for the whole light
  1373. if ( useLightDepthBounds ) {
  1374. GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
  1375. }
  1376. // only need to clear the stencil buffer and perform stencil testing if there are shadows
  1377. const bool performStencilTest = ( vLight->globalShadows != NULL || vLight->localShadows != NULL );
  1378. // mirror flips the sense of the stencil select, and I don't want to risk accidentally breaking it
  1379. // in the normal case, so simply disable the stencil select in the mirror case
  1380. const bool useLightStencilSelect = ( r_useLightStencilSelect.GetBool() && backEnd.viewDef->isMirror == false );
  1381. if ( performStencilTest ) {
  1382. if ( useLightStencilSelect ) {
  1383. // write a stencil mask for the visible light bounds to hi-stencil
  1384. RB_StencilSelectLight( vLight );
  1385. } else {
  1386. // always clear whole S-Cull tiles
  1387. idScreenRect rect;
  1388. rect.x1 = ( vLight->scissorRect.x1 + 0 ) & ~15;
  1389. rect.y1 = ( vLight->scissorRect.y1 + 0 ) & ~15;
  1390. rect.x2 = ( vLight->scissorRect.x2 + 15 ) & ~15;
  1391. rect.y2 = ( vLight->scissorRect.y2 + 15 ) & ~15;
  1392. if ( !backEnd.currentScissor.Equals( rect ) && r_useScissor.GetBool() ) {
  1393. GL_Scissor( backEnd.viewDef->viewport.x1 + rect.x1,
  1394. backEnd.viewDef->viewport.y1 + rect.y1,
  1395. rect.x2 + 1 - rect.x1,
  1396. rect.y2 + 1 - rect.y1 );
  1397. backEnd.currentScissor = rect;
  1398. }
  1399. GL_State( GLS_DEFAULT ); // make sure stencil mask passes for the clear
  1400. GL_Clear( false, false, true, STENCIL_SHADOW_TEST_VALUE, 0.0f, 0.0f, 0.0f, 0.0f );
  1401. }
  1402. }
  1403. if ( vLight->globalShadows != NULL ) {
  1404. renderLog.OpenBlock( "Global Light Shadows" );
  1405. RB_StencilShadowPass( vLight->globalShadows, vLight );
  1406. renderLog.CloseBlock();
  1407. }
  1408. if ( vLight->localInteractions != NULL ) {
  1409. renderLog.OpenBlock( "Local Light Interactions" );
  1410. RB_RenderInteractions( vLight->localInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds );
  1411. renderLog.CloseBlock();
  1412. }
  1413. if ( vLight->localShadows != NULL ) {
  1414. renderLog.OpenBlock( "Local Light Shadows" );
  1415. RB_StencilShadowPass( vLight->localShadows, vLight );
  1416. renderLog.CloseBlock();
  1417. }
  1418. if ( vLight->globalInteractions != NULL ) {
  1419. renderLog.OpenBlock( "Global Light Interactions" );
  1420. RB_RenderInteractions( vLight->globalInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds );
  1421. renderLog.CloseBlock();
  1422. }
  1423. if ( vLight->translucentInteractions != NULL && !r_skipTranslucent.GetBool() ) {
  1424. renderLog.OpenBlock( "Translucent Interactions" );
  1425. // Disable the depth bounds test because translucent surfaces don't work with
  1426. // the depth bounds tests since they did not write depth during the depth pass.
  1427. if ( useLightDepthBounds ) {
  1428. GL_DepthBoundsTest( 0.0f, 0.0f );
  1429. }
  1430. // The depth buffer wasn't filled in for translucent surfaces, so they
  1431. // can never be constrained to perforated surfaces with the depthfunc equal.
  1432. // Translucent surfaces do not receive shadows. This is a case where a
  1433. // shadow buffer solution would work but stencil shadows do not because
  1434. // stencil shadows only affect surfaces that contribute to the view depth
  1435. // buffer and translucent surfaces do not contribute to the view depth buffer.
  1436. RB_RenderInteractions( vLight->translucentInteractions, vLight, GLS_DEPTHFUNC_LESS, false, false );
  1437. renderLog.CloseBlock();
  1438. }
  1439. renderLog.CloseBlock();
  1440. }
  1441. // disable stencil shadow test
  1442. GL_State( GLS_DEFAULT );
  1443. // unbind texture units
  1444. for ( int i = 0; i < 5; i++ ) {
  1445. GL_SelectTexture( i );
  1446. globalImages->BindNull();
  1447. }
  1448. GL_SelectTexture( 0 );
  1449. // reset depth bounds
  1450. if ( useLightDepthBounds ) {
  1451. GL_DepthBoundsTest( 0.0f, 0.0f );
  1452. }
  1453. renderLog.CloseBlock();
  1454. renderLog.CloseMainBlock();
  1455. }
  1456. /*
  1457. =============================================================================================
  1458. NON-INTERACTION SHADER PASSES
  1459. =============================================================================================
  1460. */
  1461. /*
  1462. =====================
  1463. RB_DrawShaderPasses
  1464. Draw non-light dependent passes
  1465. If we are rendering Guis, the drawSurf_t::sort value is a depth offset that can
  1466. be multiplied by guiEye for polarity and screenSeparation for scale.
  1467. =====================
  1468. */
  1469. static int RB_DrawShaderPasses( const drawSurf_t * const * const drawSurfs, const int numDrawSurfs,
  1470. const float guiStereoScreenOffset, const int stereoEye ) {
  1471. // only obey skipAmbient if we are rendering a view
  1472. if ( backEnd.viewDef->viewEntitys && r_skipAmbient.GetBool() ) {
  1473. return numDrawSurfs;
  1474. }
  1475. renderLog.OpenBlock( "RB_DrawShaderPasses" );
  1476. GL_SelectTexture( 1 );
  1477. globalImages->BindNull();
  1478. GL_SelectTexture( 0 );
  1479. backEnd.currentSpace = (const viewEntity_t *)1; // using NULL makes /analyze think surf->space needs to be checked...
  1480. float currentGuiStereoOffset = 0.0f;
  1481. int i = 0;
  1482. for ( ; i < numDrawSurfs; i++ ) {
  1483. const drawSurf_t * surf = drawSurfs[i];
  1484. const idMaterial * shader = surf->material;
  1485. if ( !shader->HasAmbient() ) {
  1486. continue;
  1487. }
  1488. if ( shader->IsPortalSky() ) {
  1489. continue;
  1490. }
  1491. // some deforms may disable themselves by setting numIndexes = 0
  1492. if ( surf->numIndexes == 0 ) {
  1493. continue;
  1494. }
  1495. if ( shader->SuppressInSubview() ) {
  1496. continue;
  1497. }
  1498. if ( backEnd.viewDef->isXraySubview && surf->space->entityDef ) {
  1499. if ( surf->space->entityDef->parms.xrayIndex != 2 ) {
  1500. continue;
  1501. }
  1502. }
  1503. // we need to draw the post process shaders after we have drawn the fog lights
  1504. if ( shader->GetSort() >= SS_POST_PROCESS && !backEnd.currentRenderCopied ) {
  1505. break;
  1506. }
  1507. // if we are rendering a 3D view and the surface's eye index doesn't match
  1508. // the current view's eye index then we skip the surface
  1509. // if the stereoEye value of a surface is 0 then we need to draw it for both eyes.
  1510. const int shaderStereoEye = shader->GetStereoEye();
  1511. const bool isEyeValid = stereoRender_swapEyes.GetBool() ? ( shaderStereoEye == stereoEye ) : ( shaderStereoEye != stereoEye );
  1512. if ( ( stereoEye != 0 ) && ( shaderStereoEye != 0 ) && ( isEyeValid ) ) {
  1513. continue;
  1514. }
  1515. renderLog.OpenBlock( shader->GetName() );
  1516. // determine the stereoDepth offset
  1517. // guiStereoScreenOffset will always be zero for 3D views, so the !=
  1518. // check will never force an update due to the current sort value.
  1519. const float thisGuiStereoOffset = guiStereoScreenOffset * surf->sort;
  1520. // change the matrix and other space related vars if needed
  1521. if ( surf->space != backEnd.currentSpace || thisGuiStereoOffset != currentGuiStereoOffset ) {
  1522. backEnd.currentSpace = surf->space;
  1523. currentGuiStereoOffset = thisGuiStereoOffset;
  1524. const viewEntity_t *space = backEnd.currentSpace;
  1525. if ( guiStereoScreenOffset != 0.0f ) {
  1526. RB_SetMVPWithStereoOffset( space->mvp, currentGuiStereoOffset );
  1527. } else {
  1528. RB_SetMVP( space->mvp );
  1529. }
  1530. // set eye position in local space
  1531. idVec4 localViewOrigin( 1.0f );
  1532. R_GlobalPointToLocal( space->modelMatrix, backEnd.viewDef->renderView.vieworg, localViewOrigin.ToVec3() );
  1533. SetVertexParm( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() );
  1534. // set model Matrix
  1535. float modelMatrixTranspose[16];
  1536. R_MatrixTranspose( space->modelMatrix, modelMatrixTranspose );
  1537. SetVertexParms( RENDERPARM_MODELMATRIX_X, modelMatrixTranspose, 4 );
  1538. // Set ModelView Matrix
  1539. float modelViewMatrixTranspose[16];
  1540. R_MatrixTranspose( space->modelViewMatrix, modelViewMatrixTranspose );
  1541. SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, modelViewMatrixTranspose, 4 );
  1542. }
  1543. // change the scissor if needed
  1544. if ( !backEnd.currentScissor.Equals( surf->scissorRect ) && r_useScissor.GetBool() ) {
  1545. GL_Scissor( backEnd.viewDef->viewport.x1 + surf->scissorRect.x1,
  1546. backEnd.viewDef->viewport.y1 + surf->scissorRect.y1,
  1547. surf->scissorRect.x2 + 1 - surf->scissorRect.x1,
  1548. surf->scissorRect.y2 + 1 - surf->scissorRect.y1 );
  1549. backEnd.currentScissor = surf->scissorRect;
  1550. }
  1551. // get the expressions for conditionals / color / texcoords
  1552. const float *regs = surf->shaderRegisters;
  1553. // set face culling appropriately
  1554. if ( surf->space->isGuiSurface ) {
  1555. GL_Cull( CT_TWO_SIDED );
  1556. } else {
  1557. GL_Cull( shader->GetCullType() );
  1558. }
  1559. uint64 surfGLState = surf->extraGLState;
  1560. // set polygon offset if necessary
  1561. if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
  1562. GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
  1563. surfGLState = GLS_POLYGON_OFFSET;
  1564. }
  1565. for ( int stage = 0; stage < shader->GetNumStages(); stage++ ) {
  1566. const shaderStage_t *pStage = shader->GetStage(stage);
  1567. // check the enable condition
  1568. if ( regs[ pStage->conditionRegister ] == 0 ) {
  1569. continue;
  1570. }
  1571. // skip the stages involved in lighting
  1572. if ( pStage->lighting != SL_AMBIENT ) {
  1573. continue;
  1574. }
  1575. uint64 stageGLState = surfGLState;
  1576. if ( ( surfGLState & GLS_OVERRIDE ) == 0 ) {
  1577. stageGLState |= pStage->drawStateBits;
  1578. }
  1579. // skip if the stage is ( GL_ZERO, GL_ONE ), which is used for some alpha masks
  1580. if ( ( stageGLState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) == ( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE ) ) {
  1581. continue;
  1582. }
  1583. // see if we are a new-style stage
  1584. newShaderStage_t *newStage = pStage->newStage;
  1585. if ( newStage != NULL ) {
  1586. //--------------------------
  1587. //
  1588. // new style stages
  1589. //
  1590. //--------------------------
  1591. if ( r_skipNewAmbient.GetBool() ) {
  1592. continue;
  1593. }
  1594. renderLog.OpenBlock( "New Shader Stage" );
  1595. GL_State( stageGLState );
  1596. renderProgManager.BindShader( newStage->glslProgram, newStage->glslProgram );
  1597. for ( int j = 0; j < newStage->numVertexParms; j++ ) {
  1598. float parm[4];
  1599. parm[0] = regs[ newStage->vertexParms[j][0] ];
  1600. parm[1] = regs[ newStage->vertexParms[j][1] ];
  1601. parm[2] = regs[ newStage->vertexParms[j][2] ];
  1602. parm[3] = regs[ newStage->vertexParms[j][3] ];
  1603. SetVertexParm( (renderParm_t)( RENDERPARM_USER + j ), parm );
  1604. }
  1605. // set rpEnableSkinning if the shader has optional support for skinning
  1606. if ( surf->jointCache && renderProgManager.ShaderHasOptionalSkinning() ) {
  1607. const idVec4 skinningParm( 1.0f );
  1608. SetVertexParm( RENDERPARM_ENABLE_SKINNING, skinningParm.ToFloatPtr() );
  1609. }
  1610. // bind texture units
  1611. for ( int j = 0; j < newStage->numFragmentProgramImages; j++ ) {
  1612. idImage * image = newStage->fragmentProgramImages[j];
  1613. if ( image != NULL ) {
  1614. GL_SelectTexture( j );
  1615. image->Bind();
  1616. }
  1617. }
  1618. // draw it
  1619. RB_DrawElementsWithCounters( surf );
  1620. // unbind texture units
  1621. for ( int j = 0; j < newStage->numFragmentProgramImages; j++ ) {
  1622. idImage * image = newStage->fragmentProgramImages[j];
  1623. if ( image != NULL ) {
  1624. GL_SelectTexture( j );
  1625. globalImages->BindNull();
  1626. }
  1627. }
  1628. // clear rpEnableSkinning if it was set
  1629. if ( surf->jointCache && renderProgManager.ShaderHasOptionalSkinning() ) {
  1630. const idVec4 skinningParm( 0.0f );
  1631. SetVertexParm( RENDERPARM_ENABLE_SKINNING, skinningParm.ToFloatPtr() );
  1632. }
  1633. GL_SelectTexture( 0 );
  1634. renderProgManager.Unbind();
  1635. renderLog.CloseBlock();
  1636. continue;
  1637. }
  1638. //--------------------------
  1639. //
  1640. // old style stages
  1641. //
  1642. //--------------------------
  1643. // set the color
  1644. float color[4];
  1645. color[0] = regs[ pStage->color.registers[0] ];
  1646. color[1] = regs[ pStage->color.registers[1] ];
  1647. color[2] = regs[ pStage->color.registers[2] ];
  1648. color[3] = regs[ pStage->color.registers[3] ];
  1649. // skip the entire stage if an add would be black
  1650. if ( ( stageGLState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) == ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE )
  1651. && color[0] <= 0 && color[1] <= 0 && color[2] <= 0 ) {
  1652. continue;
  1653. }
  1654. // skip the entire stage if a blend would be completely transparent
  1655. if ( ( stageGLState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) == ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA )
  1656. && color[3] <= 0 ) {
  1657. continue;
  1658. }
  1659. stageVertexColor_t svc = pStage->vertexColor;
  1660. renderLog.OpenBlock( "Old Shader Stage" );
  1661. GL_Color( color );
  1662. if ( surf->space->isGuiSurface ) {
  1663. // Force gui surfaces to always be SVC_MODULATE
  1664. svc = SVC_MODULATE;
  1665. // use special shaders for bink cinematics
  1666. if ( pStage->texture.cinematic ) {
  1667. if ( ( stageGLState & GLS_OVERRIDE ) != 0 ) {
  1668. // This is a hack... Only SWF Guis set GLS_OVERRIDE
  1669. // Old style guis do not, and we don't want them to use the new GUI renederProg
  1670. renderProgManager.BindShader_BinkGUI();
  1671. } else {
  1672. renderProgManager.BindShader_Bink();
  1673. }
  1674. } else {
  1675. if ( ( stageGLState & GLS_OVERRIDE ) != 0 ) {
  1676. // This is a hack... Only SWF Guis set GLS_OVERRIDE
  1677. // Old style guis do not, and we don't want them to use the new GUI renderProg
  1678. renderProgManager.BindShader_GUI();
  1679. } else {
  1680. if ( surf->jointCache ) {
  1681. renderProgManager.BindShader_TextureVertexColorSkinned();
  1682. } else {
  1683. renderProgManager.BindShader_TextureVertexColor();
  1684. }
  1685. }
  1686. }
  1687. } else if ( ( pStage->texture.texgen == TG_SCREEN ) || ( pStage->texture.texgen == TG_SCREEN2 ) ) {
  1688. renderProgManager.BindShader_TextureTexGenVertexColor();
  1689. } else if ( pStage->texture.cinematic ) {
  1690. renderProgManager.BindShader_Bink();
  1691. } else {
  1692. if ( surf->jointCache ) {
  1693. renderProgManager.BindShader_TextureVertexColorSkinned();
  1694. } else {
  1695. renderProgManager.BindShader_TextureVertexColor();
  1696. }
  1697. }
  1698. RB_SetVertexColorParms( svc );
  1699. // bind the texture
  1700. RB_BindVariableStageImage( &pStage->texture, regs );
  1701. // set privatePolygonOffset if necessary
  1702. if ( pStage->privatePolygonOffset ) {
  1703. GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset );
  1704. stageGLState |= GLS_POLYGON_OFFSET;
  1705. }
  1706. // set the state
  1707. GL_State( stageGLState );
  1708. RB_PrepareStageTexturing( pStage, surf );
  1709. // draw it
  1710. RB_DrawElementsWithCounters( surf );
  1711. RB_FinishStageTexturing( pStage, surf );
  1712. // unset privatePolygonOffset if necessary
  1713. if ( pStage->privatePolygonOffset ) {
  1714. GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
  1715. }
  1716. renderLog.CloseBlock();
  1717. }
  1718. renderLog.CloseBlock();
  1719. }
  1720. GL_Cull( CT_FRONT_SIDED );
  1721. GL_Color( 1.0f, 1.0f, 1.0f );
  1722. renderLog.CloseBlock();
  1723. return i;
  1724. }
  1725. /*
  1726. =============================================================================================
  1727. BLEND LIGHT PROJECTION
  1728. =============================================================================================
  1729. */
  1730. /*
  1731. =====================
  1732. RB_T_BlendLight
  1733. =====================
  1734. */
  1735. static void RB_T_BlendLight( const drawSurf_t *drawSurfs, const viewLight_t * vLight ) {
  1736. backEnd.currentSpace = NULL;
  1737. for ( const drawSurf_t * drawSurf = drawSurfs; drawSurf != NULL; drawSurf = drawSurf->nextOnLight ) {
  1738. if ( drawSurf->scissorRect.IsEmpty() ) {
  1739. continue; // !@# FIXME: find out why this is sometimes being hit!
  1740. // temporarily jump over the scissor and draw so the gl error callback doesn't get hit
  1741. }
  1742. if ( !backEnd.currentScissor.Equals( drawSurf->scissorRect ) && r_useScissor.GetBool() ) {
  1743. // change the scissor
  1744. GL_Scissor( backEnd.viewDef->viewport.x1 + drawSurf->scissorRect.x1,
  1745. backEnd.viewDef->viewport.y1 + drawSurf->scissorRect.y1,
  1746. drawSurf->scissorRect.x2 + 1 - drawSurf->scissorRect.x1,
  1747. drawSurf->scissorRect.y2 + 1 - drawSurf->scissorRect.y1 );
  1748. backEnd.currentScissor = drawSurf->scissorRect;
  1749. }
  1750. if ( drawSurf->space != backEnd.currentSpace ) {
  1751. // change the matrix
  1752. RB_SetMVP( drawSurf->space->mvp );
  1753. // change the light projection matrix
  1754. idPlane lightProjectInCurrentSpace[4];
  1755. for ( int i = 0; i < 4; i++ ) {
  1756. R_GlobalPlaneToLocal( drawSurf->space->modelMatrix, vLight->lightProject[i], lightProjectInCurrentSpace[i] );
  1757. }
  1758. SetVertexParm( RENDERPARM_TEXGEN_0_S, lightProjectInCurrentSpace[0].ToFloatPtr() );
  1759. SetVertexParm( RENDERPARM_TEXGEN_0_T, lightProjectInCurrentSpace[1].ToFloatPtr() );
  1760. SetVertexParm( RENDERPARM_TEXGEN_0_Q, lightProjectInCurrentSpace[2].ToFloatPtr() );
  1761. SetVertexParm( RENDERPARM_TEXGEN_1_S, lightProjectInCurrentSpace[3].ToFloatPtr() ); // falloff
  1762. backEnd.currentSpace = drawSurf->space;
  1763. }
  1764. RB_DrawElementsWithCounters( drawSurf );
  1765. }
  1766. }
  1767. /*
  1768. =====================
  1769. RB_BlendLight
  1770. Dual texture together the falloff and projection texture with a blend
  1771. mode to the framebuffer, instead of interacting with the surface texture
  1772. =====================
  1773. */
  1774. static void RB_BlendLight( const drawSurf_t *drawSurfs, const drawSurf_t *drawSurfs2, const viewLight_t * vLight ) {
  1775. if ( drawSurfs == NULL ) {
  1776. return;
  1777. }
  1778. if ( r_skipBlendLights.GetBool() ) {
  1779. return;
  1780. }
  1781. renderLog.OpenBlock( vLight->lightShader->GetName() );
  1782. const idMaterial * lightShader = vLight->lightShader;
  1783. const float * regs = vLight->shaderRegisters;
  1784. // texture 1 will get the falloff texture
  1785. GL_SelectTexture( 1 );
  1786. vLight->falloffImage->Bind();
  1787. // texture 0 will get the projected texture
  1788. GL_SelectTexture( 0 );
  1789. renderProgManager.BindShader_BlendLight();
  1790. for ( int i = 0; i < lightShader->GetNumStages(); i++ ) {
  1791. const shaderStage_t *stage = lightShader->GetStage(i);
  1792. if ( !regs[ stage->conditionRegister ] ) {
  1793. continue;
  1794. }
  1795. GL_State( GLS_DEPTHMASK | stage->drawStateBits | GLS_DEPTHFUNC_EQUAL );
  1796. GL_SelectTexture( 0 );
  1797. stage->texture.image->Bind();
  1798. if ( stage->texture.hasMatrix ) {
  1799. RB_LoadShaderTextureMatrix( regs, &stage->texture );
  1800. }
  1801. // get the modulate values from the light, including alpha, unlike normal lights
  1802. float lightColor[4];
  1803. lightColor[0] = regs[ stage->color.registers[0] ];
  1804. lightColor[1] = regs[ stage->color.registers[1] ];
  1805. lightColor[2] = regs[ stage->color.registers[2] ];
  1806. lightColor[3] = regs[ stage->color.registers[3] ];
  1807. GL_Color( lightColor );
  1808. RB_T_BlendLight( drawSurfs, vLight );
  1809. RB_T_BlendLight( drawSurfs2, vLight );
  1810. }
  1811. GL_SelectTexture( 1 );
  1812. globalImages->BindNull();
  1813. GL_SelectTexture( 0 );
  1814. renderProgManager.Unbind();
  1815. renderLog.CloseBlock();
  1816. }
  1817. /*
  1818. =========================================================================================================
  1819. FOG LIGHTS
  1820. =========================================================================================================
  1821. */
  1822. /*
  1823. =====================
  1824. RB_T_BasicFog
  1825. =====================
  1826. */
  1827. static void RB_T_BasicFog( const drawSurf_t *drawSurfs, const idPlane fogPlanes[4], const idRenderMatrix * inverseBaseLightProject ) {
  1828. backEnd.currentSpace = NULL;
  1829. for ( const drawSurf_t * drawSurf = drawSurfs; drawSurf != NULL; drawSurf = drawSurf->nextOnLight ) {
  1830. if ( drawSurf->scissorRect.IsEmpty() ) {
  1831. continue; // !@# FIXME: find out why this is sometimes being hit!
  1832. // temporarily jump over the scissor and draw so the gl error callback doesn't get hit
  1833. }
  1834. if ( !backEnd.currentScissor.Equals( drawSurf->scissorRect ) && r_useScissor.GetBool() ) {
  1835. // change the scissor
  1836. GL_Scissor( backEnd.viewDef->viewport.x1 + drawSurf->scissorRect.x1,
  1837. backEnd.viewDef->viewport.y1 + drawSurf->scissorRect.y1,
  1838. drawSurf->scissorRect.x2 + 1 - drawSurf->scissorRect.x1,
  1839. drawSurf->scissorRect.y2 + 1 - drawSurf->scissorRect.y1 );
  1840. backEnd.currentScissor = drawSurf->scissorRect;
  1841. }
  1842. if ( drawSurf->space != backEnd.currentSpace ) {
  1843. idPlane localFogPlanes[4];
  1844. if ( inverseBaseLightProject == NULL ) {
  1845. RB_SetMVP( drawSurf->space->mvp );
  1846. for ( int i = 0; i < 4; i++ ) {
  1847. R_GlobalPlaneToLocal( drawSurf->space->modelMatrix, fogPlanes[i], localFogPlanes[i] );
  1848. }
  1849. } else {
  1850. idRenderMatrix invProjectMVPMatrix;
  1851. idRenderMatrix::Multiply( backEnd.viewDef->worldSpace.mvp, *inverseBaseLightProject, invProjectMVPMatrix );
  1852. RB_SetMVP( invProjectMVPMatrix );
  1853. for ( int i = 0; i < 4; i++ ) {
  1854. inverseBaseLightProject->InverseTransformPlane( fogPlanes[i], localFogPlanes[i], false );
  1855. }
  1856. }
  1857. SetVertexParm( RENDERPARM_TEXGEN_0_S, localFogPlanes[0].ToFloatPtr() );
  1858. SetVertexParm( RENDERPARM_TEXGEN_0_T, localFogPlanes[1].ToFloatPtr() );
  1859. SetVertexParm( RENDERPARM_TEXGEN_1_T, localFogPlanes[2].ToFloatPtr() );
  1860. SetVertexParm( RENDERPARM_TEXGEN_1_S, localFogPlanes[3].ToFloatPtr() );
  1861. backEnd.currentSpace = ( inverseBaseLightProject == NULL ) ? drawSurf->space : NULL;
  1862. }
  1863. if ( drawSurf->jointCache ) {
  1864. renderProgManager.BindShader_FogSkinned();
  1865. } else {
  1866. renderProgManager.BindShader_Fog();
  1867. }
  1868. RB_DrawElementsWithCounters( drawSurf );
  1869. }
  1870. }
  1871. /*
  1872. ==================
  1873. RB_FogPass
  1874. ==================
  1875. */
  1876. static void RB_FogPass( const drawSurf_t * drawSurfs, const drawSurf_t * drawSurfs2, const viewLight_t * vLight ) {
  1877. renderLog.OpenBlock( vLight->lightShader->GetName() );
  1878. // find the current color and density of the fog
  1879. const idMaterial * lightShader = vLight->lightShader;
  1880. const float * regs = vLight->shaderRegisters;
  1881. // assume fog shaders have only a single stage
  1882. const shaderStage_t * stage = lightShader->GetStage( 0 );
  1883. float lightColor[4];
  1884. lightColor[0] = regs[ stage->color.registers[0] ];
  1885. lightColor[1] = regs[ stage->color.registers[1] ];
  1886. lightColor[2] = regs[ stage->color.registers[2] ];
  1887. lightColor[3] = regs[ stage->color.registers[3] ];
  1888. GL_Color( lightColor );
  1889. // calculate the falloff planes
  1890. float a;
  1891. // if they left the default value on, set a fog distance of 500
  1892. if ( lightColor[3] <= 1.0f ) {
  1893. a = -0.5f / DEFAULT_FOG_DISTANCE;
  1894. } else {
  1895. // otherwise, distance = alpha color
  1896. a = -0.5f / lightColor[3];
  1897. }
  1898. // texture 0 is the falloff image
  1899. GL_SelectTexture( 0 );
  1900. globalImages->fogImage->Bind();
  1901. // texture 1 is the entering plane fade correction
  1902. GL_SelectTexture( 1 );
  1903. globalImages->fogEnterImage->Bind();
  1904. // S is based on the view origin
  1905. const float s = vLight->fogPlane.Distance( backEnd.viewDef->renderView.vieworg );
  1906. const float FOG_SCALE = 0.001f;
  1907. idPlane fogPlanes[4];
  1908. // S-0
  1909. fogPlanes[0][0] = a * backEnd.viewDef->worldSpace.modelViewMatrix[0*4+2];
  1910. fogPlanes[0][1] = a * backEnd.viewDef->worldSpace.modelViewMatrix[1*4+2];
  1911. fogPlanes[0][2] = a * backEnd.viewDef->worldSpace.modelViewMatrix[2*4+2];
  1912. fogPlanes[0][3] = a * backEnd.viewDef->worldSpace.modelViewMatrix[3*4+2] + 0.5f;
  1913. // T-0
  1914. fogPlanes[1][0] = 0.0f;//a * backEnd.viewDef->worldSpace.modelViewMatrix[0*4+0];
  1915. fogPlanes[1][1] = 0.0f;//a * backEnd.viewDef->worldSpace.modelViewMatrix[1*4+0];
  1916. fogPlanes[1][2] = 0.0f;//a * backEnd.viewDef->worldSpace.modelViewMatrix[2*4+0];
  1917. fogPlanes[1][3] = 0.5f;//a * backEnd.viewDef->worldSpace.modelViewMatrix[3*4+0] + 0.5f;
  1918. // T-1 will get a texgen for the fade plane, which is always the "top" plane on unrotated lights
  1919. fogPlanes[2][0] = FOG_SCALE * vLight->fogPlane[0];
  1920. fogPlanes[2][1] = FOG_SCALE * vLight->fogPlane[1];
  1921. fogPlanes[2][2] = FOG_SCALE * vLight->fogPlane[2];
  1922. fogPlanes[2][3] = FOG_SCALE * vLight->fogPlane[3] + FOG_ENTER;
  1923. // S-1
  1924. fogPlanes[3][0] = 0.0f;
  1925. fogPlanes[3][1] = 0.0f;
  1926. fogPlanes[3][2] = 0.0f;
  1927. fogPlanes[3][3] = FOG_SCALE * s + FOG_ENTER;
  1928. // draw it
  1929. GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
  1930. RB_T_BasicFog( drawSurfs, fogPlanes, NULL );
  1931. RB_T_BasicFog( drawSurfs2, fogPlanes, NULL );
  1932. // the light frustum bounding planes aren't in the depth buffer, so use depthfunc_less instead
  1933. // of depthfunc_equal
  1934. GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_LESS );
  1935. GL_Cull( CT_BACK_SIDED );
  1936. backEnd.zeroOneCubeSurface.space = &backEnd.viewDef->worldSpace;
  1937. backEnd.zeroOneCubeSurface.scissorRect = backEnd.viewDef->scissor;
  1938. RB_T_BasicFog( &backEnd.zeroOneCubeSurface, fogPlanes, &vLight->inverseBaseLightProject );
  1939. GL_Cull( CT_FRONT_SIDED );
  1940. GL_SelectTexture( 1 );
  1941. globalImages->BindNull();
  1942. GL_SelectTexture( 0 );
  1943. renderProgManager.Unbind();
  1944. renderLog.CloseBlock();
  1945. }
  1946. /*
  1947. ==================
  1948. RB_FogAllLights
  1949. ==================
  1950. */
  1951. static void RB_FogAllLights() {
  1952. if ( r_skipFogLights.GetBool() || r_showOverDraw.GetInteger() != 0
  1953. || backEnd.viewDef->isXraySubview /* don't fog in xray mode*/ ) {
  1954. return;
  1955. }
  1956. renderLog.OpenMainBlock( MRB_FOG_ALL_LIGHTS );
  1957. renderLog.OpenBlock( "RB_FogAllLights" );
  1958. // force fog plane to recalculate
  1959. backEnd.currentSpace = NULL;
  1960. for ( viewLight_t * vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next ) {
  1961. if ( vLight->lightShader->IsFogLight() ) {
  1962. RB_FogPass( vLight->globalInteractions, vLight->localInteractions, vLight );
  1963. } else if ( vLight->lightShader->IsBlendLight() ) {
  1964. RB_BlendLight( vLight->globalInteractions, vLight->localInteractions, vLight );
  1965. }
  1966. }
  1967. renderLog.CloseBlock();
  1968. renderLog.CloseMainBlock();
  1969. }
  1970. /*
  1971. =========================================================================================================
  1972. BACKEND COMMANDS
  1973. =========================================================================================================
  1974. */
  1975. /*
  1976. ==================
  1977. RB_DrawViewInternal
  1978. ==================
  1979. */
  1980. void RB_DrawViewInternal( const viewDef_t * viewDef, const int stereoEye ) {
  1981. renderLog.OpenBlock( "RB_DrawViewInternal" );
  1982. //-------------------------------------------------
  1983. // guis can wind up referencing purged images that need to be loaded.
  1984. // this used to be in the gui emit code, but now that it can be running
  1985. // in a separate thread, it must not try to load images, so do it here.
  1986. //-------------------------------------------------
  1987. drawSurf_t **drawSurfs = (drawSurf_t **)&viewDef->drawSurfs[0];
  1988. const int numDrawSurfs = viewDef->numDrawSurfs;
  1989. for ( int i = 0; i < numDrawSurfs; i++ ) {
  1990. const drawSurf_t * ds = viewDef->drawSurfs[ i ];
  1991. if ( ds->material != NULL ) {
  1992. const_cast<idMaterial *>( ds->material )->EnsureNotPurged();
  1993. }
  1994. }
  1995. //-------------------------------------------------
  1996. // RB_BeginDrawingView
  1997. //
  1998. // Any mirrored or portaled views have already been drawn, so prepare
  1999. // to actually render the visible surfaces for this view
  2000. //
  2001. // clear the z buffer, set the projection matrix, etc
  2002. //-------------------------------------------------
  2003. // set the window clipping
  2004. GL_Viewport( viewDef->viewport.x1,
  2005. viewDef->viewport.y1,
  2006. viewDef->viewport.x2 + 1 - viewDef->viewport.x1,
  2007. viewDef->viewport.y2 + 1 - viewDef->viewport.y1 );
  2008. // the scissor may be smaller than the viewport for subviews
  2009. GL_Scissor( backEnd.viewDef->viewport.x1 + viewDef->scissor.x1,
  2010. backEnd.viewDef->viewport.y1 + viewDef->scissor.y1,
  2011. viewDef->scissor.x2 + 1 - viewDef->scissor.x1,
  2012. viewDef->scissor.y2 + 1 - viewDef->scissor.y1 );
  2013. backEnd.currentScissor = viewDef->scissor;
  2014. backEnd.glState.faceCulling = -1; // force face culling to set next time
  2015. // ensures that depth writes are enabled for the depth clear
  2016. GL_State( GLS_DEFAULT );
  2017. // Clear the depth buffer and clear the stencil to 128 for stencil shadows as well as gui masking
  2018. GL_Clear( false, true, true, STENCIL_SHADOW_TEST_VALUE, 0.0f, 0.0f, 0.0f, 0.0f );
  2019. // normal face culling
  2020. GL_Cull( CT_FRONT_SIDED );
  2021. #ifdef USE_CORE_PROFILE
  2022. // bind one global Vertex Array Object (VAO)
  2023. qglBindVertexArray( glConfig.global_vao );
  2024. #endif
  2025. //------------------------------------
  2026. // sets variables that can be used by all programs
  2027. //------------------------------------
  2028. {
  2029. //
  2030. // set eye position in global space
  2031. //
  2032. float parm[4];
  2033. parm[0] = backEnd.viewDef->renderView.vieworg[0];
  2034. parm[1] = backEnd.viewDef->renderView.vieworg[1];
  2035. parm[2] = backEnd.viewDef->renderView.vieworg[2];
  2036. parm[3] = 1.0f;
  2037. SetVertexParm( RENDERPARM_GLOBALEYEPOS, parm ); // rpGlobalEyePos
  2038. // sets overbright to make world brighter
  2039. // This value is baked into the specularScale and diffuseScale values so
  2040. // the interaction programs don't need to perform the extra multiply,
  2041. // but any other renderprogs that want to obey the brightness value
  2042. // can reference this.
  2043. float overbright = r_lightScale.GetFloat() * 0.5f;
  2044. parm[0] = overbright;
  2045. parm[1] = overbright;
  2046. parm[2] = overbright;
  2047. parm[3] = overbright;
  2048. SetFragmentParm( RENDERPARM_OVERBRIGHT, parm );
  2049. // Set Projection Matrix
  2050. float projMatrixTranspose[16];
  2051. R_MatrixTranspose( backEnd.viewDef->projectionMatrix, projMatrixTranspose );
  2052. SetVertexParms( RENDERPARM_PROJMATRIX_X, projMatrixTranspose, 4 );
  2053. }
  2054. //-------------------------------------------------
  2055. // fill the depth buffer and clear color buffer to black except on subviews
  2056. //-------------------------------------------------
  2057. RB_FillDepthBufferFast( drawSurfs, numDrawSurfs );
  2058. //-------------------------------------------------
  2059. // main light renderer
  2060. //-------------------------------------------------
  2061. RB_DrawInteractions();
  2062. //-------------------------------------------------
  2063. // now draw any non-light dependent shading passes
  2064. //-------------------------------------------------
  2065. int processed = 0;
  2066. if ( !r_skipShaderPasses.GetBool() ) {
  2067. renderLog.OpenMainBlock( MRB_DRAW_SHADER_PASSES );
  2068. float guiScreenOffset;
  2069. if ( viewDef->viewEntitys != NULL ) {
  2070. // guiScreenOffset will be 0 in non-gui views
  2071. guiScreenOffset = 0.0f;
  2072. } else {
  2073. guiScreenOffset = stereoEye * viewDef->renderView.stereoScreenSeparation;
  2074. }
  2075. processed = RB_DrawShaderPasses( drawSurfs, numDrawSurfs, guiScreenOffset, stereoEye );
  2076. renderLog.CloseMainBlock();
  2077. }
  2078. //-------------------------------------------------
  2079. // fog and blend lights, drawn after emissive surfaces
  2080. // so they are properly dimmed down
  2081. //-------------------------------------------------
  2082. RB_FogAllLights();
  2083. //-------------------------------------------------
  2084. // capture the depth for the motion blur before rendering any post process surfaces that may contribute to the depth
  2085. //-------------------------------------------------
  2086. if ( r_motionBlur.GetInteger() > 0 ) {
  2087. const idScreenRect & viewport = backEnd.viewDef->viewport;
  2088. globalImages->currentDepthImage->CopyDepthbuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
  2089. }
  2090. //-------------------------------------------------
  2091. // now draw any screen warping post-process effects using _currentRender
  2092. //-------------------------------------------------
  2093. if ( processed < numDrawSurfs && !r_skipPostProcess.GetBool() ) {
  2094. int x = backEnd.viewDef->viewport.x1;
  2095. int y = backEnd.viewDef->viewport.y1;
  2096. int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1;
  2097. int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1;
  2098. RENDERLOG_PRINTF( "Resolve to %i x %i buffer\n", w, h );
  2099. GL_SelectTexture( 0 );
  2100. // resolve the screen
  2101. globalImages->currentRenderImage->CopyFramebuffer( x, y, w, h );
  2102. backEnd.currentRenderCopied = true;
  2103. // RENDERPARM_SCREENCORRECTIONFACTOR amd RENDERPARM_WINDOWCOORD overlap
  2104. // diffuseScale and specularScale
  2105. // screen power of two correction factor (no longer relevant now)
  2106. float screenCorrectionParm[4];
  2107. screenCorrectionParm[0] = 1.0f;
  2108. screenCorrectionParm[1] = 1.0f;
  2109. screenCorrectionParm[2] = 0.0f;
  2110. screenCorrectionParm[3] = 1.0f;
  2111. SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
  2112. // window coord to 0.0 to 1.0 conversion
  2113. float windowCoordParm[4];
  2114. windowCoordParm[0] = 1.0f / w;
  2115. windowCoordParm[1] = 1.0f / h;
  2116. windowCoordParm[2] = 0.0f;
  2117. windowCoordParm[3] = 1.0f;
  2118. SetFragmentParm( RENDERPARM_WINDOWCOORD, windowCoordParm ); // rpWindowCoord
  2119. // render the remaining surfaces
  2120. renderLog.OpenMainBlock( MRB_DRAW_SHADER_PASSES_POST );
  2121. RB_DrawShaderPasses( drawSurfs + processed, numDrawSurfs - processed, 0.0f /* definitely not a gui */, stereoEye );
  2122. renderLog.CloseMainBlock();
  2123. }
  2124. //-------------------------------------------------
  2125. // render debug tools
  2126. //-------------------------------------------------
  2127. RB_RenderDebugTools( drawSurfs, numDrawSurfs );
  2128. renderLog.CloseBlock();
  2129. }
  2130. /*
  2131. ==================
  2132. RB_MotionBlur
  2133. Experimental feature
  2134. ==================
  2135. */
  2136. void RB_MotionBlur() {
  2137. if ( !backEnd.viewDef->viewEntitys ) {
  2138. // 3D views only
  2139. return;
  2140. }
  2141. if ( r_motionBlur.GetInteger() <= 0 ) {
  2142. return;
  2143. }
  2144. if ( backEnd.viewDef->isSubview ) {
  2145. return;
  2146. }
  2147. GL_CheckErrors();
  2148. // clear the alpha buffer and draw only the hands + weapon into it so
  2149. // we can avoid blurring them
  2150. qglClearColor( 0, 0, 0, 1 );
  2151. GL_State( GLS_COLORMASK | GLS_DEPTHMASK );
  2152. qglClear( GL_COLOR_BUFFER_BIT );
  2153. GL_Color( 0, 0, 0, 0 );
  2154. GL_SelectTexture( 0 );
  2155. globalImages->blackImage->Bind();
  2156. backEnd.currentSpace = NULL;
  2157. drawSurf_t **drawSurfs = (drawSurf_t **)&backEnd.viewDef->drawSurfs[0];
  2158. for ( int surfNum = 0; surfNum < backEnd.viewDef->numDrawSurfs; surfNum++ ) {
  2159. const drawSurf_t * surf = drawSurfs[ surfNum ];
  2160. if ( !surf->space->weaponDepthHack && !surf->space->skipMotionBlur && !surf->material->HasSubview() ) {
  2161. // Apply motion blur to this object
  2162. continue;
  2163. }
  2164. const idMaterial * shader = surf->material;
  2165. if ( shader->Coverage() == MC_TRANSLUCENT ) {
  2166. // muzzle flash, etc
  2167. continue;
  2168. }
  2169. // set mvp matrix
  2170. if ( surf->space != backEnd.currentSpace ) {
  2171. RB_SetMVP( surf->space->mvp );
  2172. backEnd.currentSpace = surf->space;
  2173. }
  2174. // this could just be a color, but we don't have a skinned color-only prog
  2175. if ( surf->jointCache ) {
  2176. renderProgManager.BindShader_TextureVertexColorSkinned();
  2177. } else {
  2178. renderProgManager.BindShader_TextureVertexColor();
  2179. }
  2180. // draw it solid
  2181. RB_DrawElementsWithCounters( surf );
  2182. }
  2183. GL_State( GLS_DEPTHFUNC_ALWAYS );
  2184. // copy off the color buffer and the depth buffer for the motion blur prog
  2185. // we use the viewport dimensions for copying the buffers in case resolution scaling is enabled.
  2186. const idScreenRect & viewport = backEnd.viewDef->viewport;
  2187. globalImages->currentRenderImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
  2188. // in stereo rendering, each eye needs to get a separate previous frame mvp
  2189. int mvpIndex = ( backEnd.viewDef->renderView.viewEyeBuffer == 1 ) ? 1 : 0;
  2190. // derive the matrix to go from current pixels to previous frame pixels
  2191. idRenderMatrix inverseMVP;
  2192. idRenderMatrix::Inverse( backEnd.viewDef->worldSpace.mvp, inverseMVP );
  2193. idRenderMatrix motionMatrix;
  2194. idRenderMatrix::Multiply( backEnd.prevMVP[mvpIndex], inverseMVP, motionMatrix );
  2195. backEnd.prevMVP[mvpIndex] = backEnd.viewDef->worldSpace.mvp;
  2196. RB_SetMVP( motionMatrix );
  2197. GL_State( GLS_DEPTHFUNC_ALWAYS );
  2198. GL_Cull( CT_TWO_SIDED );
  2199. renderProgManager.BindShader_MotionBlur();
  2200. // let the fragment program know how many samples we are going to use
  2201. idVec4 samples( (float)( 1 << r_motionBlur.GetInteger() ) );
  2202. SetFragmentParm( RENDERPARM_OVERBRIGHT, samples.ToFloatPtr() );
  2203. GL_SelectTexture( 0 );
  2204. globalImages->currentRenderImage->Bind();
  2205. GL_SelectTexture( 1 );
  2206. globalImages->currentDepthImage->Bind();
  2207. RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
  2208. GL_CheckErrors();
  2209. }
  2210. /*
  2211. ==================
  2212. RB_DrawView
  2213. StereoEye will always be 0 in mono modes, or -1 / 1 in stereo modes.
  2214. If the view is a GUI view that is repeated for both eyes, the viewDef.stereoEye value
  2215. is 0, so the stereoEye parameter is not always the same as that.
  2216. ==================
  2217. */
  2218. void RB_DrawView( const void *data, const int stereoEye ) {
  2219. const drawSurfsCommand_t * cmd = (const drawSurfsCommand_t *)data;
  2220. backEnd.viewDef = cmd->viewDef;
  2221. // we will need to do a new copyTexSubImage of the screen
  2222. // when a SS_POST_PROCESS material is used
  2223. backEnd.currentRenderCopied = false;
  2224. // if there aren't any drawsurfs, do nothing
  2225. if ( !backEnd.viewDef->numDrawSurfs ) {
  2226. return;
  2227. }
  2228. // skip render bypasses everything that has models, assuming
  2229. // them to be 3D views, but leaves 2D rendering visible
  2230. if ( r_skipRender.GetBool() && backEnd.viewDef->viewEntitys ) {
  2231. return;
  2232. }
  2233. // skip render context sets the wgl context to NULL,
  2234. // which should factor out the API cost, under the assumption
  2235. // that all gl calls just return if the context isn't valid
  2236. if ( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys ) {
  2237. GLimp_DeactivateContext();
  2238. }
  2239. backEnd.pc.c_surfaces += backEnd.viewDef->numDrawSurfs;
  2240. RB_ShowOverdraw();
  2241. // render the scene
  2242. RB_DrawViewInternal( cmd->viewDef, stereoEye );
  2243. RB_MotionBlur();
  2244. // restore the context for 2D drawing if we were stubbing it out
  2245. if ( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys ) {
  2246. GLimp_ActivateContext();
  2247. GL_SetDefaultState();
  2248. }
  2249. // optionally draw a box colored based on the eye number
  2250. if ( r_drawEyeColor.GetBool() ) {
  2251. const idScreenRect & r = backEnd.viewDef->viewport;
  2252. GL_Scissor( ( r.x1 + r.x2 ) / 2, ( r.y1 + r.y2 ) / 2, 32, 32 );
  2253. switch ( stereoEye ) {
  2254. case -1:
  2255. GL_Clear( true, false, false, 0, 1.0f, 0.0f, 0.0f, 1.0f );
  2256. break;
  2257. case 1:
  2258. GL_Clear( true, false, false, 0, 0.0f, 1.0f, 0.0f, 1.0f );
  2259. break;
  2260. default:
  2261. GL_Clear( true, false, false, 0, 0.5f, 0.5f, 0.5f, 1.0f );
  2262. break;
  2263. }
  2264. }
  2265. }
  2266. /*
  2267. ==================
  2268. RB_CopyRender
  2269. Copy part of the current framebuffer to an image
  2270. ==================
  2271. */
  2272. void RB_CopyRender( const void *data ) {
  2273. const copyRenderCommand_t * cmd = (const copyRenderCommand_t *)data;
  2274. if ( r_skipCopyTexture.GetBool() ) {
  2275. return;
  2276. }
  2277. RENDERLOG_PRINTF( "***************** RB_CopyRender *****************\n" );
  2278. if ( cmd->image ) {
  2279. cmd->image->CopyFramebuffer( cmd->x, cmd->y, cmd->imageWidth, cmd->imageHeight );
  2280. }
  2281. if ( cmd->clearColorAfterCopy ) {
  2282. GL_Clear( true, false, false, STENCIL_SHADOW_TEST_VALUE, 0, 0, 0, 0 );
  2283. }
  2284. }
  2285. /*
  2286. ==================
  2287. RB_PostProcess
  2288. ==================
  2289. */
  2290. extern idCVar rs_enable;
  2291. void RB_PostProcess( const void * data ) {
  2292. // only do the post process step if resolution scaling is enabled. Prevents the unnecessary copying of the framebuffer and
  2293. // corresponding full screen quad pass.
  2294. if ( rs_enable.GetInteger() == 0 ) {
  2295. return;
  2296. }
  2297. // resolve the scaled rendering to a temporary texture
  2298. postProcessCommand_t * cmd = (postProcessCommand_t *)data;
  2299. const idScreenRect & viewport = cmd->viewDef->viewport;
  2300. globalImages->currentRenderImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
  2301. GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
  2302. GL_Cull( CT_TWO_SIDED );
  2303. int screenWidth = renderSystem->GetWidth();
  2304. int screenHeight = renderSystem->GetHeight();
  2305. // set the window clipping
  2306. GL_Viewport( 0, 0, screenWidth, screenHeight );
  2307. GL_Scissor( 0, 0, screenWidth, screenHeight );
  2308. GL_SelectTexture( 0 );
  2309. globalImages->currentRenderImage->Bind();
  2310. renderProgManager.BindShader_PostProcess();
  2311. // Draw
  2312. RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
  2313. renderLog.CloseBlock();
  2314. }