Draw.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. #include "Render.h"
  2. #include "Capsule/Capsule.h"
  3. #include "MaxLights.h"
  4. #include "Shaders/Shader.h"
  5. #include "Shaders/ShaderVar.h"
  6. __forceinline bool NeedDrawRotateGizmoLine (const Vector& vCenter, const Vector &v1, const Vector &v2, const Vector& vCamDir)
  7. {
  8. //return true;
  9. Vector dir1 = v1 - vCenter;
  10. Vector dir2 = v1 - vCenter;
  11. if ((vCamDir | dir1) > 0) return false;
  12. if ((vCamDir | dir2) > 0) return false;
  13. return true;
  14. }
  15. __forceinline bool LightIsUsed (const Vector & camPos, ILight* light, const GMXOBB &boundBox, const Plane* Frustum, Color & recalculatedColor)
  16. {
  17. //получаем позицию источника в пространстве коробки....
  18. const Vector& vLightPos = light->GetPos();
  19. float fRadius = light->GetRadius();
  20. float fLodMinDist = light->getLOD_minDist_Squared();
  21. float fLodMaxDist = light->getLOD_maxDist_Squared();
  22. float fLodLen = light->getLOD_len_Squared();
  23. recalculatedColor = light->GetColor();
  24. Vector dist = vLightPos - camPos;
  25. float fDistToLightSquared = dist | dist;
  26. //TODO: тут float compare на 260 тыщ тактов...
  27. if (fDistToLightSquared > fLodMinDist)
  28. {
  29. if (fDistToLightSquared > fLodMaxDist)
  30. {
  31. return false;
  32. }
  33. float fColorScaleK = 1.0f - ((fDistToLightSquared - fLodMinDist) * fLodLen);
  34. recalculatedColor = recalculatedColor * fColorScaleK;
  35. }
  36. for(long p = 0; p < 5; p++)
  37. {
  38. if(((vLightPos | Frustum[p].n) - Frustum[p].d) < -fRadius)
  39. {
  40. return false;
  41. }
  42. }
  43. Vector vLightPosInBoxCoord = boundBox.GetTransform().MulVertexByInverse(vLightPos);
  44. const Vector& extents = boundBox.GetExtents();
  45. if (vLightPosInBoxCoord.x >= 0)
  46. {
  47. //по оси X вышли за пределы источника
  48. if ((vLightPosInBoxCoord.x - extents.x) > fRadius) return false;
  49. } else
  50. {
  51. //по оси X вышли за пределы источника
  52. if ((vLightPosInBoxCoord.x + extents.x) < -fRadius) return false;
  53. }
  54. if (vLightPosInBoxCoord.y >= 0)
  55. {
  56. //по оси Y вышли за пределы источника
  57. if ((vLightPosInBoxCoord.y - extents.y) > fRadius) return false;
  58. } else
  59. {
  60. //по оси Y вышли за пределы источника
  61. if ((vLightPosInBoxCoord.y + extents.y) < -fRadius) return false;
  62. }
  63. if (vLightPosInBoxCoord.z >= 0)
  64. {
  65. //по оси Z вышли за пределы источника
  66. if ((vLightPosInBoxCoord.z - extents.z) > fRadius) return false;
  67. } else
  68. {
  69. //по оси Z вышли за пределы источника
  70. if ((vLightPosInBoxCoord.z + extents.z) < -fRadius) return false;
  71. }
  72. return true;
  73. }
  74. void NGRender::SetLightVariables (ShaderId shaderId, ILight** lightsArray, dword dwArraySize)
  75. {
  76. SHADER* shader = (SHADER*)(shaderId);
  77. if (lightsArray == NULL || dwArraySize == 0)
  78. {
  79. //Надо направленный источник, на все остальное насрать
  80. #if defined (_XBOX) && defined(_PRECOMPILED_COMMAND_BUFFER_BAKER)
  81. m_ShaderManager.getVarDatabase()->ApplyLightingVariables30(stdLightVariables, 0);
  82. #else
  83. shader->ApplyLightingVariables30(stdLightVariables, 0);
  84. #endif
  85. return;
  86. }
  87. if( dwArraySize > MAX_LIGHTS_IN_30_MODEL)
  88. {
  89. dwArraySize = MAX_LIGHTS_IN_30_MODEL;
  90. }
  91. dword n = 0;
  92. for (; n < dwArraySize; n++)
  93. {
  94. ILight* light = lightsArray[n];
  95. const Vector4& col = light->GetRenderColor().v4;
  96. float FarRadius = light->GetRadius();
  97. stdLightVariables.pointLights.vPointLightPos[n] = light->GetPos();
  98. stdLightVariables.pointLights.vPointLightColor[n] = col;
  99. stdLightVariables.pointLights.vPointLightColorSpecular[n] = col;
  100. Vector & specular = stdLightVariables.pointLights.vPointLightColorSpecular[n].v;
  101. if ((specular | specular) > 1.0f)
  102. {
  103. specular.Normalize();
  104. }
  105. stdLightVariables.pointLights.vPointLightColorSpecular[n].v *= SPECULAR_STRENGHT;
  106. /*x: OneDivPointLightNearPow, y:PointLightNear, z:PointLightFar, w:PointLightAffectedShadow*/
  107. stdLightVariables.pointLights.vPointLightsParams[n] = Vector4(1.0f / (FarRadius * FarRadius), 0.0f, FarRadius, light->getAffectedByShadowK());
  108. }
  109. for (; n < MAX_LIGHTS_IN_30_MODEL; n++)
  110. {
  111. stdLightVariables.pointLights.vPointLightPos[n] = 0.0f;
  112. stdLightVariables.pointLights.vPointLightColor[n] = 0.0f;
  113. stdLightVariables.pointLights.vPointLightColorSpecular[n] = 0.0f;
  114. /*x: OneDivPointLightNearPow, y:PointLightNear, z:PointLightFar, w:PointLightAffectedShadow*/
  115. stdLightVariables.pointLights.vPointLightsParams[n] = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
  116. }
  117. #if defined (_XBOX) && defined(_PRECOMPILED_COMMAND_BUFFER_BAKER)
  118. m_ShaderManager.getVarDatabase()->ApplyLightingVariables30(stdLightVariables, dwArraySize);
  119. #else
  120. shader->ApplyLightingVariables30(stdLightVariables, dwArraySize);
  121. #endif
  122. }
  123. void NGRender::DebugIntersectLights (const GMXOBB &boundBox, array<ILight*> & affectedLights)
  124. {
  125. AssertCoreThread;
  126. const Plane* Frustum = GetFrustumFast();
  127. dword VisibleLightCount = 0;
  128. int LastUsedLightIndex = -1;
  129. affectedLights.DelAll();
  130. Color newColor;
  131. ILight* lightPtr = NULL;
  132. //Проверяем источники
  133. for (dword i=0; i < activeLights.Size(); i++)
  134. {
  135. lightPtr = activeLights[i];
  136. newColor = lightPtr->GetColor();
  137. if (!LightIsUsed(vCameraPosition_WorldSpace.v, lightPtr, boundBox, Frustum, newColor))
  138. {
  139. continue;
  140. }
  141. dword dwOldValue = lightPtr->debugGetValue();
  142. lightPtr->debugSetValue(dwOldValue+1);
  143. affectedLights.Add(lightPtr);
  144. lightPtr->SetRenderColor(newColor);
  145. LastUsedLightIndex = i;
  146. VisibleLightCount++;
  147. }
  148. }
  149. bool NGRender::DrawIndexedPrimitiveLighted(const ShaderLightingId & id, RENDERPRIMITIVETYPE Type, dword MinVertexIndex, dword NumVertices, dword StartIndex, dword PrimitiveCount, const GMXOBB &boundBox)
  150. {
  151. AssertCoreThread;
  152. #ifndef _XBOX
  153. #ifdef KEY_U_DISABLE_RENDER
  154. if (!bDisableHacks)
  155. {
  156. if (api->DebugKeyState('U'))
  157. {
  158. return true;
  159. }
  160. }
  161. #endif
  162. if (bUseMipFillColor)
  163. {
  164. return DrawIndexedPrimitiveSingleThread(id.off, Type, MinVertexIndex, NumVertices, StartIndex, PrimitiveCount);
  165. }
  166. #endif
  167. const Plane* Frustum = GetFrustumFast();
  168. dword VisibleLightCount = 0;
  169. int LastUsedLightIndex = -1;
  170. passLights.DelAll();
  171. Color newColor;
  172. ILight* lightPtr = NULL;
  173. //Проверяем источники
  174. for (dword i=0; i < activeLights.Size(); i++)
  175. {
  176. lightPtr = activeLights[i];
  177. newColor = lightPtr->GetColor();
  178. if (!LightIsUsed(vCameraPosition_WorldSpace.v, lightPtr, boundBox, Frustum, newColor))
  179. {
  180. continue;
  181. }
  182. passLights.Add(lightPtr);
  183. lightPtr->SetRenderColor(newColor);
  184. LastUsedLightIndex = i;
  185. VisibleLightCount++;
  186. }
  187. if (passLights.Size() > MAX_LIGHTS_IN_30_MODEL)
  188. {
  189. //Слишком много источников на батч
  190. return DrawIndexedPrimitiveSingleThread(id.off, Type, MinVertexIndex, NumVertices, StartIndex, PrimitiveCount);
  191. }
  192. if (id.on == NULL)
  193. {
  194. return false;
  195. }
  196. stats.LightCountVisible = coremax (stats.LightCountVisible, VisibleLightCount);
  197. if (passLights.Size() > 0)
  198. {
  199. // directional и < MAX_LIGHTS_PER_PASS point
  200. SetLightVariables(id.on, &passLights[0], VisibleLightCount);
  201. dword dwID = pixBeginEvent(_FL_, "%d lights", VisibleLightCount);
  202. bool bRes = DrawIndexedPrimitiveSingleThread(id.on, Type, MinVertexIndex, NumVertices, StartIndex, PrimitiveCount);
  203. pixEndEvent(_FL_, dwID);
  204. passLights.DelAll();
  205. return bRes;
  206. }
  207. SetLightVariables(id.on, NULL, 0);
  208. return DrawIndexedPrimitiveSingleThread(id.on, Type, MinVertexIndex, NumVertices, StartIndex, PrimitiveCount);
  209. }
  210. bool NGRender::DrawPrimitiveLighted(const ShaderLightingId & id, RENDERPRIMITIVETYPE Type, dword StartVertex, dword PrimitiveCount, const GMXOBB & boundBox)
  211. {
  212. AssertCoreThread;
  213. #ifndef _XBOX
  214. #ifdef KEY_U_DISABLE_RENDER
  215. if (!bDisableHacks)
  216. {
  217. if (api->DebugKeyState('U'))
  218. {
  219. return true;
  220. }
  221. }
  222. #endif
  223. if (bUseMipFillColor)
  224. {
  225. return DrawPrimitive(id.off, Type, StartVertex, PrimitiveCount);
  226. }
  227. #endif
  228. const Plane* Frustum = GetFrustumFast();
  229. dword VisibleLightCount = 0;
  230. int LastUsedLightIndex = -1;
  231. passLights.DelAll();
  232. Color newColor;
  233. ILight* lightPtr = NULL;
  234. //Проверяем источники
  235. for (dword i=0; i < activeLights.Size(); i++)
  236. {
  237. lightPtr = activeLights[i];
  238. newColor = lightPtr->GetColor();
  239. if (!LightIsUsed(vCameraPosition_WorldSpace.v, lightPtr, boundBox, Frustum, newColor))
  240. {
  241. continue;
  242. }
  243. passLights.Add(lightPtr);
  244. lightPtr->SetRenderColor(newColor);
  245. LastUsedLightIndex = i;
  246. VisibleLightCount++;
  247. }
  248. if (passLights.Size() > MAX_LIGHTS_IN_30_MODEL)
  249. {
  250. //Слишком много источников на батч
  251. return DrawPrimitive(id.off, Type, StartVertex, PrimitiveCount);
  252. }
  253. if (id.on == NULL)
  254. {
  255. return false;
  256. }
  257. stats.LightCountVisible = coremax (stats.LightCountVisible, VisibleLightCount);
  258. if (passLights.Size() > 0)
  259. {
  260. // directional и < MAX_LIGHTS_PER_PASS point
  261. SetLightVariables(id.on, &passLights[0], VisibleLightCount);
  262. bool bRes = DrawPrimitive(id.on, Type, StartVertex, PrimitiveCount);
  263. passLights.DelAll();
  264. return bRes;
  265. }
  266. SetLightVariables(id.on, NULL, 0);
  267. return DrawPrimitive(id.on, Type, StartVertex, PrimitiveCount);
  268. }
  269. bool NGRender::DrawLine(const Vector & v1, dword dwColor1, const Vector & v2, dword dwColor2, bool bWorldMatrix, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  270. {
  271. AssertCoreThread;
  272. if (IsRenderDisabled()) return false;
  273. RS_LINE line[2];
  274. line[0].vPos = v1;
  275. line[0].dwColor = dwColor1;
  276. line[1].vPos = v2;
  277. line[1].dwColor = dwColor2;
  278. Matrix mWorldSave;
  279. if (!bWorldMatrix)
  280. {
  281. mWorldSave = GetWorld();
  282. SetWorld(mIdentity);
  283. }
  284. bool bSuccess = DrawLines(line, 1, pTechniqueName, NULL, 0);
  285. if (!bWorldMatrix)
  286. SetWorld(mWorldSave);
  287. return bSuccess;
  288. }
  289. bool NGRender::DrawBufferedLine(const Vector & v1, dword dwColor1, const Vector & v2, dword dwColor2, bool bWorldMatrix, const char* szTechnique)
  290. {
  291. AssertCoreThread;
  292. RS_LINE * p1 = &aBufferedLines[aBufferedLines.Add()];
  293. RS_LINE * p2 = &aBufferedLines[aBufferedLines.Add()];
  294. if (bWorldMatrix)
  295. {
  296. p1->vPos = v1 * GetWorld();
  297. p2->vPos = v2 * GetWorld();
  298. }
  299. else
  300. {
  301. p1->vPos = v1;
  302. p2->vPos = v2;
  303. }
  304. p1->dwColor = dwColor1;
  305. p2->dwColor = dwColor2;
  306. if (aBufferedLines() >= 2048) FlushBufferedLines(bWorldMatrix, szTechnique);
  307. return true;
  308. }
  309. bool NGRender::FlushBufferedLines(bool bIdentityMatrix, const char* szTechnqiue)
  310. {
  311. AssertCoreThread;
  312. if (aBufferedLines())
  313. {
  314. Matrix mWorldSave = GetWorld();
  315. if (bIdentityMatrix) SetWorld(mIdentity);
  316. DrawLines(&aBufferedLines[0], aBufferedLines() / 2, szTechnqiue);
  317. if (bIdentityMatrix) SetWorld(mWorldSave);
  318. }
  319. aBufferedLines.DelAll();
  320. return true;
  321. }
  322. bool NGRender::DrawLines(RS_LINE * pRSL, dword dwLinesNum, const char * pTechniqueName, void * pObsoletteMustBeNULL, dword dwStride)
  323. {
  324. AssertCoreThread;
  325. ShaderId id;
  326. GetShaderId(pTechniqueName, id);
  327. if (IsRenderDisabled()) return false;
  328. if (!pRSL || !dwLinesNum) return false;
  329. if (!dwStride) dwStride = sizeof(RS_LINE);
  330. bool bSuccess = DrawPrimitiveUP(id, PT_LINELIST, dwLinesNum, pRSL, dwStride);
  331. return bSuccess;
  332. }
  333. bool NGRender::DrawSolidBox(const Vector & vMin, const Vector & vMax, const Matrix & mMatrix, dword dwColor, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  334. {
  335. AssertCoreThread;
  336. Vector vScale = vMax - vMin;
  337. Vector vCenter = vMin + (vMax - vMin) / 2.0f;
  338. SHADER* shader = m_ShaderManager.FindShaderByName(pTechniqueName);
  339. if (!shader)
  340. {
  341. api->Trace("Can't draw box, shader '%s' not found", pTechniqueName);
  342. return false;
  343. }
  344. Matrix mSavedWorld = GetWorld();
  345. SetWorld(mMatrix);
  346. SHADERVAR* sv_vLightDir = (SHADERVAR*)GetTechniqueGlobalVariable("vLightDir", _FL_);
  347. if (sv_vLightDir)
  348. {
  349. Vector vLightDir = -Vector(GetView().m[0][2], GetView().m[1][2], GetView().m[2][2]);
  350. const Matrix& mWorldInv = mtxWorldInv;
  351. vLightDir = mWorldInv.MulNormal(vLightDir);
  352. vLightDir.Normalize();
  353. sv_vLightDir->SetVector(vLightDir);
  354. sv_vLightDir = NULL;
  355. }
  356. SHADERVAR* sv_vCenter = (SHADERVAR*)GetTechniqueGlobalVariable("vCenter", _FL_);
  357. if (sv_vCenter)
  358. {
  359. sv_vCenter->SetVector(vCenter);
  360. sv_vCenter = NULL;
  361. }
  362. SHADERVAR* sv_vScale = (SHADERVAR*)GetTechniqueGlobalVariable("vScale", _FL_);
  363. if (sv_vScale)
  364. {
  365. sv_vScale->SetVector(vScale);
  366. sv_vScale = NULL;
  367. }
  368. SHADERVAR* sv_vColor = (SHADERVAR*)GetTechniqueGlobalVariable("vColor", _FL_);
  369. if (sv_vColor)
  370. {
  371. sv_vColor->SetVector4(Color(dwColor).v4);
  372. sv_vColor = NULL;
  373. }
  374. SetStreamSource(0, pVSolidBox);
  375. SetIndices(pISolidBox, 0);
  376. ShaderId id;
  377. GetShaderId(pTechniqueName, id);
  378. DrawIndexedPrimitive(id, PT_TRIANGLELIST, 0, pVSolidBox->GetLength() / sizeof(SolidBoxVertex), 0, pISolidBox->GetLength() / (sizeof(short) * 3));
  379. SetWorld(mSavedWorld);
  380. return true;
  381. }
  382. bool NGRender::DrawBox(const Vector & vMin, const Vector & vMax, const Matrix & mMatrix, dword dwColor, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  383. {
  384. AssertCoreThread;
  385. RS_LINE RSL[12 * 2];
  386. Vector v0 = vMin;
  387. Vector v1 = Vector(vMax.x, vMin.y, vMin.z);
  388. Vector v2 = Vector(vMax.x, vMin.y, vMax.z);
  389. Vector v3 = Vector(vMin.x, vMin.y, vMax.z);
  390. Vector v4 = Vector(vMin.x, vMax.y, vMin.z);
  391. Vector v5 = Vector(vMax.x, vMax.y, vMin.z);
  392. Vector v6 = Vector(vMax.x, vMax.y, vMax.z);
  393. Vector v7 = Vector(vMin.x, vMax.y, vMax.z);
  394. long i = 0;
  395. // down
  396. RSL[i++].vPos = v0; RSL[i++].vPos = v1;
  397. RSL[i++].vPos = v1; RSL[i++].vPos = v2;
  398. RSL[i++].vPos = v2; RSL[i++].vPos = v3;
  399. RSL[i++].vPos = v3; RSL[i++].vPos = v0;
  400. // up
  401. RSL[i++].vPos = v4; RSL[i++].vPos = v5;
  402. RSL[i++].vPos = v5; RSL[i++].vPos = v6;
  403. RSL[i++].vPos = v6; RSL[i++].vPos = v7;
  404. RSL[i++].vPos = v7; RSL[i++].vPos = v4;
  405. // edges
  406. RSL[i++].vPos = v0; RSL[i++].vPos = v4;
  407. RSL[i++].vPos = v1; RSL[i++].vPos = v5;
  408. RSL[i++].vPos = v2; RSL[i++].vPos = v6;
  409. RSL[i++].vPos = v3; RSL[i++].vPos = v7;
  410. for (i=0; i<12 * 2; i++) RSL[i].dwColor = dwColor;
  411. Matrix mWorldSave = GetWorld();
  412. SetWorld(mMatrix);
  413. bool bSuccess = DrawLines(RSL, 12, pTechniqueName, NULL);
  414. SetWorld(mWorldSave);
  415. return bSuccess;
  416. }
  417. bool NGRender::DrawRects(IBaseTexture* pTexture, RS_RECT * pRects, dword dwRectsNum, const char * pTechniqueName, void * pObsoletteMustBeNULL, dword dwStride, dword dwSubTexX, dword dwSubTexY)
  418. {
  419. AssertCoreThread;
  420. if (!pRects || dwRectsNum == 0) return false;
  421. if (IsRenderDisabled()) return false;
  422. SHADER* shader = m_ShaderManager.FindShaderByName(pTechniqueName);
  423. if (!shader)
  424. {
  425. api->Trace("Can't draw rects, shader '%s' not found", pTechniqueName);
  426. return false;
  427. }
  428. IVariable* var = GetTechniqueGlobalVariable("RectTexture", _FL_);
  429. if (var)
  430. {
  431. if (pTexture)
  432. var->SetTexture(pTexture);
  433. else
  434. var->ResetTexture();
  435. var = NULL;
  436. }
  437. Matrix mView = GetView();
  438. bool bUseSubTextures = (dwSubTexX > 1 || dwSubTexY > 1);
  439. for (dword i=0; i<(dwRectsNum + MAX_RECTS_NUM - 1) / MAX_RECTS_NUM; i++)
  440. {
  441. dword dwNum = ((i + 1) * MAX_RECTS_NUM > dwRectsNum) ? dwNum = dwRectsNum - (dwRectsNum / MAX_RECTS_NUM) * MAX_RECTS_NUM : MAX_RECTS_NUM;
  442. #ifndef _XBOX
  443. DWORD dwFlags = D3DLOCK_DISCARD;
  444. #else
  445. DWORD dwFlags = 0;
  446. #endif
  447. RECT_VERTEX * pRectsVerts = (RECT_VERTEX*)pRectsVBuffer->Lock(0, 0, dwFlags);
  448. for (dword j=0; j<dwNum; j++)
  449. {
  450. dword dwIdx = i * MAX_RECTS_NUM + j;
  451. RECT_VERTEX * pV = &pRectsVerts[j * 4];
  452. RS_RECT * pR = (RS_RECT*)&(((char*)pRects)[dwStride * dwIdx]);
  453. float fCos = cosf(pR->fAngle);
  454. float fSin = sinf(pR->fAngle);
  455. float fSizeX = pR->fSizeX;
  456. float fSizeY = pR->fSizeY;
  457. Vector vPos = mView * pR->vPos;
  458. float dx, dy, sx, sy;
  459. if (bUseSubTextures)
  460. {
  461. dx = 1.0f / float(dwSubTexX);
  462. dy = 1.0f / float(dwSubTexY);
  463. sx = dx * (pR->dwSubTexture - dwSubTexX * (pR->dwSubTexture / dwSubTexX));
  464. sy = dy * (pR->dwSubTexture / dwSubTexY);
  465. }
  466. else
  467. {
  468. sx = sy = 0.0f;
  469. dx = dy = 1.0f;
  470. }
  471. pV[0].vPos = Vector(-fSizeX, -fSizeY, 0.0f).RotateXY(fCos, fSin) + vPos;
  472. pV[0].dwColor = pR->dwColor;
  473. pV[0].tu = 0.0f * dx + sx;
  474. pV[0].tv = 1.0f * dy + sy;
  475. pV[1].vPos = Vector(-fSizeX, fSizeY, 0.0f).RotateXY(fCos, fSin) + vPos;
  476. pV[1].dwColor = pR->dwColor;
  477. pV[1].tu = 0.0f * dx + sx;
  478. pV[1].tv = 0.0f * dy + sy;
  479. pV[2].vPos = Vector(fSizeX, fSizeY, 0.0f).RotateXY(fCos, fSin) + vPos;
  480. pV[2].dwColor = pR->dwColor;
  481. pV[2].tu = 1.0f * dx + sx;
  482. pV[2].tv = 0.0f * dy + sy;
  483. pV[3].vPos = Vector(fSizeX, -fSizeY, 0.0f).RotateXY(fCos, fSin) + vPos;
  484. pV[3].dwColor = pR->dwColor;
  485. pV[3].tu = 1.0f * dx + sx;
  486. pV[3].tv = 1.0f * dy + sy;
  487. }
  488. pRectsVBuffer->Unlock();
  489. SetStreamSource(0, pRectsVBuffer);
  490. SetIndices(pRectsIBuffer, 0);
  491. Matrix mOldView = GetView();
  492. Matrix mOldWorld = GetWorld();
  493. SetWorld(Matrix());
  494. SetView(Matrix());
  495. ShaderId id;
  496. GetShaderId(pTechniqueName, id);
  497. DrawIndexedPrimitive(id, PT_TRIANGLELIST, 0, dwNum * 4, 0, dwNum * 2);
  498. SetWorld(mOldWorld);
  499. SetView(mOldView);
  500. }
  501. return true;
  502. }
  503. bool NGRender::DrawSprites(IBaseTexture* pTexture, RS_SPRITE * pSprites, dword dwSpritesNum, const char * pTechniqueName, void * pObsoletteMustBeNULL, dword dwStride)
  504. {
  505. AssertCoreThread;
  506. if (!pSprites || dwSpritesNum == 0)
  507. {
  508. return false;
  509. }
  510. if (IsRenderDisabled())
  511. {
  512. return false;
  513. }
  514. SHADER* shader = m_ShaderManager.FindShaderByName(pTechniqueName);
  515. if (!shader)
  516. {
  517. api->Trace("Can't draw sprites, shader '%s' not found", pTechniqueName);
  518. return false;
  519. }
  520. IVariable* var = GetTechniqueGlobalVariable("Texture", _FL_);
  521. if (var)
  522. {
  523. if (pTexture == NULL)
  524. {
  525. var->ResetTexture();
  526. } else
  527. {
  528. var->SetTexture(pTexture);
  529. }
  530. var = NULL;
  531. }
  532. for (dword i=0; i<(dwSpritesNum + MAX_RECTS_NUM - 1) / MAX_RECTS_NUM; i++)
  533. {
  534. dword dwNum = ((i + 1) * MAX_RECTS_NUM > dwSpritesNum) ? dwNum = dwSpritesNum - (dwSpritesNum / MAX_RECTS_NUM) * MAX_RECTS_NUM : MAX_RECTS_NUM;
  535. #ifndef _XBOX
  536. DWORD dwFlags = LOCK_DISCARD;
  537. #else
  538. DWORD dwFlags = 0;
  539. #endif
  540. RS_SPRITE * pSpritesVerts = (RS_SPRITE*)pSpritesVBuffer->Lock(0, 0, dwFlags);
  541. for (dword j=0; j<dwNum; j++)
  542. {
  543. dword dwIdx = i * MAX_RECTS_NUM + j;
  544. RS_SPRITE * pV = &pSpritesVerts[j * 4];
  545. RS_SPRITE * pS = (RS_SPRITE*)&(((char*)pSprites)[dwStride * dwIdx]);
  546. pV[0] = pS[0]; pV[1] = pS[1]; pV[2] = pS[2]; pV[3] = pS[3];
  547. }
  548. pSpritesVBuffer->Unlock();
  549. SetStreamSource(0, pSpritesVBuffer);
  550. SetIndices(pRectsIBuffer, 0);
  551. ShaderId id;
  552. GetShaderId(pTechniqueName, id);
  553. DrawIndexedPrimitive(id, PT_TRIANGLELIST, 0, dwNum * 4, 0, dwNum * 2);
  554. SetStreamSource(0, null);
  555. }
  556. return true;
  557. }
  558. bool NGRender::DrawNormals(IVBuffer * pVBuffer, dword dwStartVertex, dword dwNumVertices, dword dwColor1, dword dwColor2, float fScale, dword dwStride, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  559. {
  560. AssertCoreThread;
  561. if (!pVBuffer) return false;
  562. if (!dwStride) dwStride = pVBuffer->GetStride();
  563. if (!dwStride) return false;
  564. char * pBuffer = (char*)pVBuffer->Lock();
  565. if (!pBuffer) return false;
  566. RS_LINE * pLines = NEW RS_LINE[dwNumVertices * 2];
  567. for (dword i=0; i<dwNumVertices; i++)
  568. {
  569. Vector * pVector = (Vector*)(pBuffer + dwStartVertex * dwStride);
  570. Vector * pNormal = (Vector*)(pBuffer + dwStartVertex * dwStride + sizeof(Vector));
  571. pLines[i * 2 + 0].vPos = *pVector;
  572. pLines[i * 2 + 0].dwColor = dwColor1;
  573. pLines[i * 2 + 1].vPos = (*pVector) + fScale * (*pNormal);
  574. pLines[i * 2 + 1].dwColor = dwColor2;
  575. pBuffer += dwStride;
  576. }
  577. pVBuffer->Unlock();
  578. bool bSuccess = DrawLines(pLines, dwNumVertices, pTechniqueName, NULL);
  579. DELETE(pLines);
  580. return bSuccess;
  581. }
  582. bool NGRender::DrawSphere(const Vector & vPos, float fRadius, dword dwColor, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  583. {
  584. AssertCoreThread;
  585. if (IsRenderDisabled()) return false;
  586. Matrix mPos;
  587. mPos.BuildPosition(vPos);
  588. mPos.m[0][0] = fRadius;
  589. mPos.m[1][1] = fRadius;
  590. mPos.m[2][2] = fRadius;
  591. return DrawSphere(mPos, dwColor, pTechniqueName, NULL);
  592. }
  593. bool NGRender::DrawSphere(const Matrix & mPos, dword dwColor, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  594. {
  595. AssertCoreThread;
  596. if (IsRenderDisabled()) return false;
  597. Vector vRadius = mPos.GetScale();
  598. float fRadius = coremax(vRadius.x, vRadius.y);
  599. fRadius = coremax(fRadius, vRadius.z);
  600. const Plane * frustum = GetFrustum();
  601. for(long i = 0; i < 4; i++)
  602. {
  603. if(frustum[i].Dist(mPos.pos) < -fRadius) return true;
  604. }
  605. Matrix mWorldSave = GetWorld();
  606. SetWorld(mPos);
  607. SHADER* sphereShader = m_ShaderManager.FindShaderByName(pTechniqueName);
  608. if (!sphereShader)
  609. {
  610. api->Trace("Can't draw sphere, shader '%s' not found", pTechniqueName);
  611. return false;
  612. }
  613. IVariable* var = GetTechniqueGlobalVariable("SphereColor", _FL_);
  614. if (var)
  615. {
  616. var->SetVector4(Color(dwColor).v4);
  617. var = NULL;
  618. }
  619. ShaderId id;
  620. GetShaderId(pTechniqueName, id);
  621. SetStreamSource(0, pVSphereBuffer);
  622. DrawPrimitive(id, PT_TRIANGLELIST, 0, dwNumSphereTrgs);
  623. SetWorld(mWorldSave);
  624. return true;
  625. }
  626. void NGRender::MakeDrawVector(RS_LINE * pLines, dword dwNumSubLines, const Matrix & mMatrix, Vector vUp, Vector v1, Vector v2, float fScale, dword dwColor)
  627. {
  628. AssertCoreThread;
  629. dword i;
  630. for (i=0; i<dwNumSubLines * 2 + 2; i++) pLines[i].dwColor = dwColor;
  631. pLines[0].vPos = v1;
  632. pLines[1].vPos = v1 + (fScale * v2);
  633. float fRadius = 0.03f * fScale;
  634. float fDist = 0.85f * fScale * sqrtf(~v2);
  635. for (i=0; i<dwNumSubLines; i++)
  636. {
  637. float fAng = PIm2 * float(i) / float(dwNumSubLines);
  638. float x = fRadius * sinf(fAng);
  639. float z = fRadius * cosf(fAng);
  640. Vector vRes;
  641. if (fabsf(vUp.x) < 1e-5f) vRes = Vector(fDist, x, z);
  642. if (fabsf(vUp.y) < 1e-5f) vRes = Vector(x, fDist, z);
  643. if (fabsf(vUp.z) < 1e-5f) vRes = Vector(x, z, fDist);
  644. vRes = vRes * mMatrix;
  645. pLines[2 + i * 2 + 0].vPos = vRes;
  646. pLines[2 + i * 2 + 1].vPos = pLines[1].vPos;
  647. }
  648. }
  649. bool NGRender::DrawMatrix(const Matrix & mMatrix, float fScale, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  650. {
  651. AssertCoreThread;
  652. if (IsRenderDisabled()) return false;
  653. RS_LINE lines[3 * 51 * 2];
  654. MakeDrawVector(&lines[0], 50, mMatrix, Vector(0.0f, 1.0f, 1.0f), mMatrix.pos, mMatrix.vx, fScale, 0xFF00FF00);
  655. MakeDrawVector(&lines[102], 50, mMatrix, Vector(1.0f, 0.0f, 1.0f), mMatrix.pos, mMatrix.vy, fScale, 0xFFFF0000);
  656. MakeDrawVector(&lines[204], 50, mMatrix, Vector(1.0f, 1.0f, 0.0f), mMatrix.pos, mMatrix.vz, fScale, 0xFF0000FF);
  657. Matrix mWorldSave = GetWorld(); SetWorld(mIdentity);
  658. bool bSuccess = DrawLines(lines, 3 * 51, pTechniqueName, NULL);
  659. SetWorld(mWorldSave);
  660. return bSuccess;
  661. }
  662. bool NGRender::DrawVector(const Vector & v1, const Vector & v2, dword dwColor, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  663. {
  664. AssertCoreThread;
  665. if (IsRenderDisabled()) return false;
  666. RS_LINE lines[51 * 2];
  667. Matrix mView;
  668. float fScale = sqrtf(~(v2 - v1));
  669. if (!mView.BuildView(v1, v2, Vector(0.0f, 1.0f, 0.0f)))
  670. if (!mView.BuildView(v1, v2, Vector(1.0f, 0.0f, 0.0f))) return false;
  671. mView.Inverse();
  672. MakeDrawVector(&lines[0], 50, mView, Vector(1.0f, 1.0f, 0.0f), mView.pos, mView.vz, fScale, dwColor);
  673. Matrix mWorldSave = GetWorld(); SetWorld(mIdentity);
  674. bool bSuccess = DrawLines(lines, 51, pTechniqueName, NULL);
  675. SetWorld(mWorldSave);
  676. return bSuccess;
  677. }
  678. bool NGRender::DrawPolygon(const Vector * pVectors, dword dwNumPoints, const Color & color, const Matrix& matrix, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  679. {
  680. AssertCoreThread;
  681. if (IsRenderDisabled()) return false;
  682. if (!pVectors || dwNumPoints < 3) return false;
  683. aPolygons.Empty();
  684. for (dword i=0; i<dwNumPoints; i++)
  685. {
  686. POLYGON_VERTEX * pV = &aPolygons[aPolygons.Add()];
  687. pV->dwColor = color;
  688. pV->vPos = pVectors[i];
  689. }
  690. SetWorld(matrix);
  691. ShaderId id;
  692. GetShaderId(pTechniqueName, id);
  693. return DrawPrimitiveUP(id, PT_TRIANGLEFAN, dwNumPoints - 2, &aPolygons[0], sizeof(POLYGON_VERTEX));
  694. }
  695. void NGRender::DrawXZCircle (const Vector& center, float fRadius, dword dwColor, const char* szTechnique)
  696. {
  697. AssertCoreThread;
  698. if (IsRenderDisabled()) return;
  699. Matrix prevWorld = GetWorld();
  700. SetWorld(mIdentity);
  701. float fDelta = 0.2f;
  702. RS_LINE line[2];
  703. Vector vStart;
  704. Vector vEnd;
  705. Vector vStartPoint;
  706. vStartPoint = Vector(cosf(0)*fRadius, 0.0f, sinf(0)*fRadius);
  707. vStartPoint += center;
  708. for (float Angle = fDelta; Angle <= (PI*2); Angle += fDelta)
  709. {
  710. Vector vPoint = Vector(cosf(Angle)*fRadius, 0.0f, sinf(Angle)*fRadius);
  711. vPoint += center;
  712. vStart = vStartPoint;
  713. vEnd = vPoint;
  714. line[0].vPos = vStart;
  715. line[0].dwColor = dwColor;
  716. line[1].vPos = vEnd;
  717. line[1].dwColor = dwColor;
  718. DrawLines(line, 1, szTechnique);
  719. //pRS->DrawVector(vStart, vEnd, dwColor);
  720. vStartPoint = vPoint;
  721. }
  722. vStart = vStartPoint;
  723. vEnd = Vector(cosf(0)*fRadius, 0.0f, sinf(0)*fRadius);
  724. vEnd += center;
  725. line[0].vPos = vStart;
  726. line[0].dwColor = dwColor;
  727. line[1].vPos = vEnd;
  728. line[1].dwColor = dwColor;
  729. DrawLines(line, 1, szTechnique);
  730. SetWorld(prevWorld);
  731. }
  732. void NGRender::DrawSphereGizmo (const Vector& pos, float fRadius, dword dwColor1, dword dwColor2, const char* szTechnique)
  733. {
  734. AssertCoreThread;
  735. if (IsRenderDisabled()) return;
  736. //Matrix mTransform;
  737. //GetMatrix(mTransform);
  738. Matrix mCurView = GetView();
  739. mCurView.Inverse();
  740. Vector vCamDir = mCurView.vz;
  741. Matrix wrld = Matrix();
  742. float fDelta = 0.2f;
  743. Vector vStart;
  744. Vector vEnd;
  745. Vector mFrom = pos;
  746. Vector vStartPoint = Vector(sinf(0)*fRadius, cosf(0)*fRadius, 0.0f);
  747. for (float Angle = fDelta; Angle <= (PI*2); Angle += fDelta)
  748. {
  749. Vector vPoint = Vector(sinf(Angle)*fRadius, cosf(Angle)*fRadius, 0.0f);
  750. vStart = vStartPoint*wrld;
  751. vEnd = vPoint*wrld;
  752. vStart += mFrom;
  753. vEnd += mFrom;
  754. if (NeedDrawRotateGizmoLine(pos, vStart, vEnd, vCamDir))
  755. {
  756. DrawBufferedLine(vStart, dwColor1, vEnd, dwColor1, false, szTechnique);
  757. }
  758. vStartPoint = vPoint;
  759. }
  760. vStart = vStartPoint*wrld;
  761. vEnd = Vector(sinf(0)*fRadius, cosf(0)*fRadius, 0.0f)*wrld;
  762. vStart += mFrom;
  763. vEnd += mFrom;
  764. if (NeedDrawRotateGizmoLine(pos, vStart, vEnd, vCamDir))
  765. {
  766. DrawBufferedLine(vStart, dwColor1, vEnd, dwColor1, false, szTechnique);
  767. }
  768. vStartPoint = Vector(0.0f, cosf(0)*fRadius, sinf(0)*fRadius);
  769. for (float Angle = fDelta; Angle <= (PI*2); Angle += fDelta)
  770. {
  771. Vector vPoint = Vector(0.0f, cosf(Angle)*fRadius, sinf(Angle)*fRadius);
  772. vStart = vStartPoint*wrld;
  773. vEnd = vPoint*wrld;
  774. vStart += mFrom;
  775. vEnd += mFrom;
  776. if (NeedDrawRotateGizmoLine(pos, vStart, vEnd, vCamDir))
  777. {
  778. DrawBufferedLine(vStart, dwColor1, vEnd, dwColor1, false, szTechnique);
  779. }
  780. vStartPoint = vPoint;
  781. }
  782. vStart = vStartPoint*wrld;
  783. vEnd = Vector(0.0f, cosf(0)*fRadius, sinf(0)*fRadius)*wrld;
  784. vStart += mFrom;
  785. vEnd += mFrom;
  786. if (NeedDrawRotateGizmoLine(pos, vStart, vEnd, vCamDir))
  787. {
  788. DrawBufferedLine(vStart, dwColor1, vEnd, dwColor1, false, szTechnique);
  789. }
  790. vStartPoint = Vector(cosf(0)*fRadius, 0.0f, sinf(0)*fRadius);
  791. for (float Angle = fDelta; Angle <= (PI*2); Angle += fDelta)
  792. {
  793. Vector vPoint = Vector(cosf(Angle)*fRadius, 0.0f, sinf(Angle)*fRadius);
  794. vStart = vStartPoint*wrld;
  795. vEnd = vPoint*wrld;
  796. vStart += mFrom;
  797. vEnd += mFrom;
  798. if (NeedDrawRotateGizmoLine(pos, vStart, vEnd, vCamDir))
  799. {
  800. DrawBufferedLine(vStart, dwColor1, vEnd, dwColor1, false, szTechnique);
  801. }
  802. vStartPoint = vPoint;
  803. }
  804. vStart = vStartPoint*wrld;
  805. vEnd = Vector(cosf(0)*fRadius, 0.0f, sinf(0)*fRadius)*wrld;
  806. vStart += mFrom;
  807. vEnd += mFrom;
  808. if (NeedDrawRotateGizmoLine(pos, vStart, vEnd, vCamDir))
  809. {
  810. DrawBufferedLine(vStart, dwColor1, vEnd, dwColor1, false, szTechnique);
  811. }
  812. Matrix mView = GetView();
  813. mView.pos = 0.0f;
  814. mView.Inverse();
  815. vStartPoint = Vector(sinf(0)*fRadius, cosf(0)*fRadius, 0.0f);
  816. for (float Angle = fDelta; Angle <= (PI*2); Angle += fDelta)
  817. {
  818. Vector vPoint = Vector(sinf(Angle)*fRadius, cosf(Angle)*fRadius, 0.0f);
  819. vStart = vStartPoint*mView;
  820. vEnd = vPoint*mView;
  821. vStart += mFrom;
  822. vEnd += mFrom;
  823. DrawBufferedLine(vStart, dwColor2, vEnd, dwColor2, false, szTechnique);
  824. vStartPoint = vPoint;
  825. }
  826. vStart = vStartPoint*mView;
  827. vEnd = Vector(sinf(0)*fRadius, cosf(0)*fRadius, 0.0f)*mView;
  828. vStart += mFrom;
  829. vEnd += mFrom;
  830. DrawBufferedLine(vStart, dwColor2, vEnd, dwColor2, false, szTechnique);
  831. FlushBufferedLines(true, szTechnique);
  832. }
  833. bool NGRender::DrawCapsule(float fRadius, float fHeight, dword dwColor, const Matrix &WorldMat, const char * pTechniqueName, void * pObsoletteMustBeNULL)
  834. {
  835. AssertCoreThread;
  836. if (!capsuleRender) return false;
  837. capsuleRender->Draw( fRadius, fHeight, dwColor, WorldMat, pTechniqueName);
  838. return true;
  839. }