Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

827 rindas
21 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #include <lol/engine-internal.h>
  11. #include <cstdlib>
  12. #if defined _XBOX
  13. # include <xtl.h>
  14. # undef near /* Fuck Microsoft */
  15. # undef far /* Fuck Microsoft again */
  16. #elif defined _WIN32
  17. # if defined USE_D3D9
  18. # include <d3d9.h>
  19. # endif
  20. # define WIN32_LEAN_AND_MEAN
  21. # include <windows.h>
  22. # undef near /* Fuck Microsoft */
  23. # undef far /* Fuck Microsoft again */
  24. #endif
  25. #include "lolgl.h"
  26. /* FIXME: find a way to pass g_hwnd from the windowing system */
  27. #if defined USE_D3D9
  28. extern HWND g_hwnd;
  29. #elif defined _XBOX
  30. HWND g_hwnd = 0;
  31. #endif
  32. namespace lol
  33. {
  34. /*
  35. * The global g_renderer object, initialised by Video::Init
  36. */
  37. Renderer *g_renderer = nullptr;
  38. /*
  39. * Private RendererData class
  40. */
  41. class RendererData
  42. {
  43. friend class Renderer;
  44. private:
  45. ibox2 m_viewport;
  46. vec4 m_clear_color;
  47. float m_clear_depth;
  48. AlphaFunc m_alpha_func;
  49. float m_alpha_value;
  50. BlendEquation m_blend_rgb, m_blend_alpha;
  51. BlendFunc m_blend_src, m_blend_dst;
  52. DepthFunc m_depth_func;
  53. DepthMask m_depth_mask;
  54. CullMode m_cull_mode;
  55. PolygonMode m_polygon_mode;
  56. private:
  57. #if defined USE_D3D9
  58. IDirect3D9 *m_d3d_ctx;
  59. IDirect3DDevice9 *m_d3d_dev;
  60. #elif defined _XBOX
  61. Direct3D *m_d3d_ctx;
  62. D3DDevice *m_d3d_dev;
  63. #endif
  64. };
  65. /*
  66. * Public Renderer class
  67. */
  68. Renderer::Renderer(ivec2 size)
  69. : m_data(new RendererData())
  70. {
  71. #if defined USE_D3D9 || defined _XBOX
  72. /* Create Direct3D context */
  73. m_data->m_d3d_ctx = Direct3DCreate9(D3D_SDK_VERSION);
  74. if (!m_data->m_d3d_ctx)
  75. {
  76. Log::Error("cannot initialise D3D\n");
  77. exit(EXIT_FAILURE);
  78. }
  79. /* Create Direct3D device */
  80. # if defined _XBOX
  81. XVIDEO_MODE VideoMode;
  82. XGetVideoMode(&VideoMode);
  83. size = lol::min(size, ivec2(VideoMode.dwDisplayWidth,
  84. VideoMode.dwDisplayHeight));
  85. # endif
  86. D3DPRESENT_PARAMETERS d3dpp;
  87. memset(&d3dpp, 0, sizeof(d3dpp));
  88. d3dpp.BackBufferWidth = size.x;
  89. d3dpp.BackBufferHeight = size.y;
  90. d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
  91. d3dpp.BackBufferCount = 1;
  92. d3dpp.hDeviceWindow = g_hwnd;
  93. # if USE_SDL || USE_OLD_SDL
  94. d3dpp.Windowed = TRUE;
  95. # endif
  96. d3dpp.EnableAutoDepthStencil = TRUE;
  97. d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
  98. d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  99. d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  100. HRESULT hr = m_data->m_d3d_ctx->CreateDevice(0, D3DDEVTYPE_HAL, g_hwnd,
  101. D3DCREATE_HARDWARE_VERTEXPROCESSING,
  102. &d3dpp, &m_data->m_d3d_dev);
  103. if (FAILED(hr))
  104. {
  105. Log::Error("cannot create D3D device\n");
  106. exit(EXIT_FAILURE);
  107. }
  108. #else
  109. # if defined USE_GLEW && !defined __APPLE__
  110. /* Initialise GLEW if necessary */
  111. GLenum glerr = glewInit();
  112. if (glerr != GLEW_OK)
  113. {
  114. Log::Error("cannot initialise GLEW: %s\n", glewGetErrorString(glerr));
  115. exit(EXIT_FAILURE);
  116. }
  117. # endif
  118. #endif
  119. /* Initialise rendering states */
  120. m_data->m_viewport = ibox2(0, 0, 0, 0);
  121. SetViewport(ibox2(ivec2::zero, size));
  122. m_data->m_clear_color = vec4(-1.f);
  123. SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f));
  124. m_data->m_clear_depth = -1.f;
  125. SetClearDepth(1.f);
  126. m_data->m_alpha_func = AlphaFunc::Never;
  127. m_data->m_alpha_value = -1.0f;
  128. SetAlphaFunc(AlphaFunc::Disabled, 0.0f);
  129. m_data->m_blend_rgb = BlendEquation::Subtract;
  130. m_data->m_blend_alpha = BlendEquation::Subtract;
  131. SetBlendEquation(BlendEquation::Add, BlendEquation::Add);
  132. m_data->m_blend_src = BlendFunc::Disabled;
  133. m_data->m_blend_dst = BlendFunc::Disabled;
  134. SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
  135. m_data->m_depth_func = DepthFunc::Disabled;
  136. SetDepthFunc(DepthFunc::LessOrEqual);
  137. m_data->m_depth_mask = DepthMask::Disabled;
  138. SetDepthMask(DepthMask::Enabled);
  139. m_data->m_cull_mode = CullMode::Disabled;
  140. SetCullMode(CullMode::Clockwise);
  141. m_data->m_polygon_mode = PolygonMode::Point;
  142. SetPolygonMode(PolygonMode::Fill);
  143. /* Add some rendering states that we don't export to the user */
  144. #if defined USE_D3D9 || defined _XBOX
  145. /* TODO */
  146. #else
  147. # if defined HAVE_GL_2X && !defined __APPLE__
  148. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  149. # endif
  150. #endif
  151. }
  152. Renderer::~Renderer()
  153. {
  154. delete m_data;
  155. }
  156. void *Renderer::GetDevice()
  157. {
  158. #if defined USE_D3D9 || defined _XBOX
  159. return m_data->m_d3d_dev;
  160. #else
  161. return nullptr;
  162. #endif
  163. }
  164. /*
  165. * Buffer clearing
  166. */
  167. void Renderer::Clear(ClearMask mask)
  168. {
  169. #if defined USE_D3D9 || defined _XBOX
  170. int m = 0;
  171. if (mask & ClearMask::Color)
  172. m |= D3DCLEAR_TARGET;
  173. if (mask & ClearMask::Depth)
  174. m |= D3DCLEAR_ZBUFFER;
  175. if (mask & ClearMask::Stencil)
  176. m |= D3DCLEAR_STENCIL;
  177. vec3 tmp = 255.999f * GetClearColor().rgb;
  178. D3DCOLOR clear_color = D3DCOLOR_XRGB((int)tmp.r, (int)tmp.g, (int)tmp.b);
  179. if (FAILED(m_data->m_d3d_dev->Clear(0, nullptr, m, clear_color,
  180. GetClearDepth(), 0)))
  181. Abort();
  182. #else
  183. GLbitfield m = 0;
  184. if (mask & ClearMask::Color)
  185. m |= GL_COLOR_BUFFER_BIT;
  186. if (mask & ClearMask::Depth)
  187. m |= GL_DEPTH_BUFFER_BIT;
  188. if (mask & ClearMask::Stencil)
  189. m |= GL_STENCIL_BUFFER_BIT;
  190. glClear(m);
  191. #endif
  192. }
  193. /*
  194. * Viewport dimensions
  195. */
  196. void Renderer::SetViewport(ibox2 viewport)
  197. {
  198. if (m_data->m_viewport == viewport)
  199. return;
  200. #if defined USE_D3D9 || defined _XBOX
  201. D3DVIEWPORT9 vp = { viewport.A.x, viewport.A.y,
  202. viewport.B.x, viewport.B.y,
  203. 0.0f, 1.0f };
  204. m_data->m_d3d_dev->SetViewport(&vp);
  205. #else
  206. glViewport(viewport.A.x, viewport.A.y, viewport.B.x, viewport.B.y);
  207. #endif
  208. m_data->m_viewport = viewport;
  209. }
  210. ibox2 Renderer::GetViewport() const
  211. {
  212. return m_data->m_viewport;
  213. }
  214. float Renderer::GetXYRatio() const
  215. {
  216. ibox2 a = GetViewport();
  217. ibox2 b(a.A, a.B);
  218. ivec2 s = b.B - b.A;
  219. return (float)s.x / s.y;
  220. }
  221. float Renderer::GetYXRatio() const
  222. {
  223. ibox2 a = GetViewport();
  224. ibox2 b(a.A, a.B);
  225. ivec2 s = b.B - b.A;
  226. return (float)s.y / s.x;
  227. }
  228. /*
  229. * Clear color
  230. */
  231. void Renderer::SetClearColor(vec4 color)
  232. {
  233. if (m_data->m_clear_color == color)
  234. return;
  235. #if defined USE_D3D9 || defined _XBOX
  236. /* Nothing to do */
  237. #else
  238. glClearColor(color.r, color.g, color.b, color.a);
  239. #endif
  240. m_data->m_clear_color = color;
  241. }
  242. vec4 Renderer::GetClearColor() const
  243. {
  244. return m_data->m_clear_color;
  245. }
  246. /*
  247. * Clear depth
  248. */
  249. void Renderer::SetClearDepth(float depth)
  250. {
  251. if (m_data->m_clear_depth == depth)
  252. return;
  253. #if defined USE_D3D9 || defined _XBOX
  254. /* Nothing to do */
  255. #elif defined HAVE_GLES_2X
  256. glClearDepthf(depth);
  257. #else
  258. glClearDepth(depth);
  259. #endif
  260. m_data->m_clear_depth = depth;
  261. }
  262. float Renderer::GetClearDepth() const
  263. {
  264. return m_data->m_clear_depth;
  265. }
  266. /*
  267. * Alpha testing
  268. */
  269. void Renderer::SetAlphaFunc(AlphaFunc func, float alpha)
  270. {
  271. if (m_data->m_alpha_func == func && m_data->m_alpha_value == alpha)
  272. return;
  273. #if defined USE_D3D9 || defined _XBOX
  274. switch (func)
  275. {
  276. case AlphaFunc::Disabled:
  277. break; /* Nothing to do */
  278. case AlphaFunc::Never:
  279. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NEVER);
  280. break;
  281. case AlphaFunc::Less:
  282. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);
  283. break;
  284. case AlphaFunc::Equal:
  285. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_EQUAL);
  286. break;
  287. case AlphaFunc::LessOrEqual:
  288. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESSEQUAL);
  289. break;
  290. case AlphaFunc::Greater:
  291. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
  292. break;
  293. case AlphaFunc::NotEqual:
  294. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
  295. break;
  296. case AlphaFunc::GreaterOrEqual:
  297. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
  298. break;
  299. case AlphaFunc::Always:
  300. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
  301. break;
  302. }
  303. if (func == AlphaFunc::Disabled)
  304. {
  305. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  306. }
  307. else
  308. {
  309. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
  310. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAREF,
  311. (DWORD)(alpha * 255.999f));
  312. }
  313. #elif defined GL_VERSION_1_1
  314. switch (func)
  315. {
  316. case AlphaFunc::Disabled:
  317. break; /* Nothing to do */
  318. case AlphaFunc::Never:
  319. glAlphaFunc(GL_NEVER, alpha); break;
  320. case AlphaFunc::Less:
  321. glAlphaFunc(GL_LESS, alpha); break;
  322. case AlphaFunc::Equal:
  323. glAlphaFunc(GL_EQUAL, alpha); break;
  324. case AlphaFunc::LessOrEqual:
  325. glAlphaFunc(GL_LEQUAL, alpha); break;
  326. case AlphaFunc::Greater:
  327. glAlphaFunc(GL_GREATER, alpha); break;
  328. case AlphaFunc::NotEqual:
  329. glAlphaFunc(GL_NOTEQUAL, alpha); break;
  330. case AlphaFunc::GreaterOrEqual:
  331. glAlphaFunc(GL_GEQUAL, alpha); break;
  332. case AlphaFunc::Always:
  333. glAlphaFunc(GL_ALWAYS, alpha); break;
  334. }
  335. if (func == AlphaFunc::Disabled)
  336. glDisable(GL_ALPHA_TEST);
  337. else
  338. glEnable(GL_ALPHA_TEST);
  339. #else
  340. /* XXX: alpha test not available in GL ES and deprecated anyway. */
  341. #endif
  342. m_data->m_alpha_func = func;
  343. m_data->m_alpha_value = alpha;
  344. }
  345. AlphaFunc Renderer::GetAlphaFunc() const
  346. {
  347. return m_data->m_alpha_func;
  348. }
  349. float Renderer::GetAlphaValue() const
  350. {
  351. return m_data->m_alpha_value;
  352. }
  353. /*
  354. * Blend equation
  355. */
  356. void Renderer::SetBlendEquation(BlendEquation rgb, BlendEquation alpha)
  357. {
  358. if (m_data->m_blend_rgb == rgb && m_data->m_blend_alpha == alpha)
  359. return;
  360. #if defined USE_D3D9 || defined _XBOX
  361. D3DBLEND s1[2] = { D3DBLENDOP_ADD, D3DBLENDOP_ADD };
  362. BlendEquation s2[2] = { rgb, alpha };
  363. for (int i = 0; i < 2; ++i)
  364. {
  365. switch (s2[i])
  366. {
  367. case BlendEquation::Add:
  368. s1[i] = D3DBLENDOP_ADD; break;
  369. case BlendEquation::Subtract:
  370. s1[i] = D3DBLENDOP_SUBTRACT; break;
  371. case BlendEquation::ReverseSubtract:
  372. s1[i] = D3DBLENDOP_REVSUBTRACT; break;
  373. case BlendEquation::Min:
  374. s1[i] = D3DBLENDOP_MIN; break;
  375. case BlendEquation::Max:
  376. s1[i] = D3DBLENDOP_MAX; break;
  377. }
  378. }
  379. m_data->m_d3d_dev->SetRenderState(D3DRS_BLENDOP, s1[0]);
  380. m_data->m_d3d_dev->SetRenderState(D3DRS_BLENDOPALPHA, s1[1]);
  381. #else
  382. GLenum s1[2] = { GL_FUNC_ADD, GL_FUNC_ADD };
  383. BlendEquation s2[2] = { rgb, alpha };
  384. for (int i = 0; i < 2; ++i)
  385. {
  386. switch (s2[i])
  387. {
  388. case BlendEquation::Add:
  389. s1[i] = GL_FUNC_ADD; break;
  390. case BlendEquation::Subtract:
  391. s1[i] = GL_FUNC_SUBTRACT; break;
  392. case BlendEquation::ReverseSubtract:
  393. s1[i] = GL_FUNC_REVERSE_SUBTRACT; break;
  394. #if defined GL_MIN && defined GL_MAX
  395. case BlendEquation::Min:
  396. s1[i] = GL_MIN; break;
  397. case BlendEquation::Max:
  398. s1[i] = GL_MAX; break;
  399. #else
  400. case BlendEquation::Min:
  401. s1[i] = GL_MIN_EXT; break;
  402. case BlendEquation::Max:
  403. s1[i] = GL_MAX_EXT; break;
  404. #endif
  405. }
  406. }
  407. glBlendEquationSeparate(s1[0], s1[1]);
  408. #endif
  409. m_data->m_blend_rgb = rgb;
  410. m_data->m_blend_alpha = alpha;
  411. }
  412. BlendEquation Renderer::GetBlendEquationRgb() const
  413. {
  414. return m_data->m_blend_rgb;
  415. }
  416. BlendEquation Renderer::GetBlendEquationAlpha() const
  417. {
  418. return m_data->m_blend_alpha;
  419. }
  420. /*
  421. * Blend function
  422. */
  423. void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst)
  424. {
  425. if (m_data->m_blend_src == src && m_data->m_blend_dst == dst)
  426. return;
  427. #if defined USE_D3D9 || defined _XBOX
  428. D3DBLEND s1[2] = { D3DBLEND_ONE, D3DBLEND_ZERO };
  429. BlendFunc s2[2] = { src, dst };
  430. for (int i = 0; i < 2; ++i)
  431. {
  432. switch (s2[i])
  433. {
  434. case BlendFunc::Disabled:
  435. break; /* Nothing to do */
  436. case BlendFunc::Zero:
  437. s1[i] = D3DBLEND_ZERO; break;
  438. case BlendFunc::One:
  439. s1[i] = D3DBLEND_ONE; break;
  440. case BlendFunc::SrcColor:
  441. s1[i] = D3DBLEND_SRCCOLOR; break;
  442. case BlendFunc::OneMinusSrcColor:
  443. s1[i] = D3DBLEND_INVSRCCOLOR; break;
  444. case BlendFunc::DstColor:
  445. s1[i] = D3DBLEND_DESTCOLOR; break;
  446. case BlendFunc::OneMinusDstColor:
  447. s1[i] = D3DBLEND_INVDESTCOLOR; break;
  448. case BlendFunc::SrcAlpha:
  449. s1[i] = D3DBLEND_SRCALPHA; break;
  450. case BlendFunc::OneMinusSrcAlpha:
  451. s1[i] = D3DBLEND_INVSRCALPHA; break;
  452. case BlendFunc::DstAlpha:
  453. s1[i] = D3DBLEND_DESTALPHA; break;
  454. case BlendFunc::OneMinusDstAlpha:
  455. s1[i] = D3DBLEND_INVDESTALPHA; break;
  456. /* FiXME: these can be supported using D3DPBLENDCAPS_BLENDFACTOR */
  457. case BlendFunc::ConstantColor:
  458. ASSERT(0, "BlendFunc::ConstantColor not supported");
  459. break;
  460. case BlendFunc::OneMinusConstantColor:
  461. ASSERT(0, "BlendFunc::OneMinusConstantColor not supported");
  462. break;
  463. case BlendFunc::ConstantAlpha:
  464. ASSERT(0, "BlendFunc::ConstantAlpha not supported");
  465. break;
  466. case BlendFunc::OneMinusConstantAlpha:
  467. ASSERT(0, "BlendFunc::OneMinusConstantAlpha not supported");
  468. break;
  469. }
  470. }
  471. if (src == BlendFunc::Disabled)
  472. {
  473. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
  474. }
  475. else
  476. {
  477. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  478. m_data->m_d3d_dev->SetRenderState(D3DRS_SRCBLEND, s1[0]);
  479. m_data->m_d3d_dev->SetRenderState(D3DRS_DESTBLEND, s1[1]);
  480. }
  481. #else
  482. GLenum s1[2] = { GL_ONE, GL_ZERO };
  483. BlendFunc s2[2] = { src, dst };
  484. for (int i = 0; i < 2; ++i)
  485. {
  486. switch (s2[i])
  487. {
  488. case BlendFunc::Disabled:
  489. break; /* Nothing to do */
  490. case BlendFunc::Zero:
  491. s1[i] = GL_ZERO; break;
  492. case BlendFunc::One:
  493. s1[i] = GL_ONE; break;
  494. case BlendFunc::SrcColor:
  495. s1[i] = GL_SRC_COLOR; break;
  496. case BlendFunc::OneMinusSrcColor:
  497. s1[i] = GL_ONE_MINUS_SRC_COLOR; break;
  498. case BlendFunc::DstColor:
  499. s1[i] = GL_DST_COLOR; break;
  500. case BlendFunc::OneMinusDstColor:
  501. s1[i] = GL_ONE_MINUS_DST_COLOR; break;
  502. case BlendFunc::SrcAlpha:
  503. s1[i] = GL_SRC_ALPHA; break;
  504. case BlendFunc::OneMinusSrcAlpha:
  505. s1[i] = GL_ONE_MINUS_SRC_ALPHA; break;
  506. case BlendFunc::DstAlpha:
  507. s1[i] = GL_DST_ALPHA; break;
  508. case BlendFunc::OneMinusDstAlpha:
  509. s1[i] = GL_ONE_MINUS_DST_ALPHA; break;
  510. case BlendFunc::ConstantColor:
  511. s1[i] = GL_CONSTANT_COLOR; break;
  512. case BlendFunc::OneMinusConstantColor:
  513. s1[i] = GL_ONE_MINUS_CONSTANT_COLOR; break;
  514. case BlendFunc::ConstantAlpha:
  515. s1[i] = GL_CONSTANT_ALPHA; break;
  516. case BlendFunc::OneMinusConstantAlpha:
  517. s1[i] = GL_ONE_MINUS_CONSTANT_ALPHA; break;
  518. }
  519. }
  520. if (src == BlendFunc::Disabled)
  521. {
  522. glDisable(GL_BLEND);
  523. }
  524. else
  525. {
  526. glEnable(GL_BLEND);
  527. glBlendFunc(s1[0], s1[1]);
  528. }
  529. #endif
  530. m_data->m_blend_src = src;
  531. m_data->m_blend_dst = dst;
  532. }
  533. BlendFunc Renderer::GetBlendFuncSrc() const
  534. {
  535. return m_data->m_blend_src;
  536. }
  537. BlendFunc Renderer::GetBlendFuncDst() const
  538. {
  539. return m_data->m_blend_dst;
  540. }
  541. /*
  542. * Depth test
  543. */
  544. void Renderer::SetDepthFunc(DepthFunc func)
  545. {
  546. if (m_data->m_depth_func == func)
  547. return;
  548. #if defined USE_D3D9 || defined _XBOX
  549. switch (func)
  550. {
  551. case DepthFunc::Disabled:
  552. break; /* Nothing to do */
  553. case DepthFunc::Never:
  554. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_NEVER);
  555. break;
  556. case DepthFunc::Less:
  557. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
  558. break;
  559. case DepthFunc::Equal:
  560. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
  561. break;
  562. case DepthFunc::LessOrEqual:
  563. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  564. break;
  565. case DepthFunc::Greater:
  566. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER);
  567. break;
  568. case DepthFunc::NotEqual:
  569. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL);
  570. break;
  571. case DepthFunc::GreaterOrEqual:
  572. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
  573. break;
  574. case DepthFunc::Always:
  575. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  576. break;
  577. }
  578. if (func == DepthFunc::Disabled)
  579. m_data->m_d3d_dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
  580. else
  581. m_data->m_d3d_dev->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
  582. #else
  583. switch (func)
  584. {
  585. case DepthFunc::Disabled:
  586. break; /* Nothing to do */
  587. case DepthFunc::Never:
  588. glDepthFunc(GL_NEVER); break;
  589. case DepthFunc::Less:
  590. glDepthFunc(GL_LESS); break;
  591. case DepthFunc::Equal:
  592. glDepthFunc(GL_EQUAL); break;
  593. case DepthFunc::LessOrEqual:
  594. glDepthFunc(GL_LEQUAL); break;
  595. case DepthFunc::Greater:
  596. glDepthFunc(GL_GREATER); break;
  597. case DepthFunc::NotEqual:
  598. glDepthFunc(GL_NOTEQUAL); break;
  599. case DepthFunc::GreaterOrEqual:
  600. glDepthFunc(GL_GEQUAL); break;
  601. case DepthFunc::Always:
  602. glDepthFunc(GL_ALWAYS); break;
  603. }
  604. if (func == DepthFunc::Disabled)
  605. glDisable(GL_DEPTH_TEST);
  606. else
  607. glEnable(GL_DEPTH_TEST);
  608. #endif
  609. m_data->m_depth_func = func;
  610. }
  611. DepthFunc Renderer::GetDepthFunc() const
  612. {
  613. return m_data->m_depth_func;
  614. }
  615. /*
  616. * Depth mask
  617. */
  618. void Renderer::SetDepthMask(DepthMask mask)
  619. {
  620. if (m_data->m_depth_mask == mask)
  621. return;
  622. #if defined USE_D3D9 || defined _XBOX
  623. if (mask == DepthMask::Disabled)
  624. m_data->m_d3d_dev->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
  625. else
  626. m_data->m_d3d_dev->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE);
  627. #else
  628. if (mask == DepthMask::Disabled)
  629. glDepthMask(GL_FALSE);
  630. else
  631. glDepthMask(GL_TRUE);
  632. #endif
  633. m_data->m_depth_mask = mask;
  634. }
  635. DepthMask Renderer::GetDepthMask() const
  636. {
  637. return m_data->m_depth_mask;
  638. }
  639. /*
  640. * Face culling
  641. */
  642. void Renderer::SetCullMode(CullMode mode)
  643. {
  644. if (m_data->m_cull_mode == mode)
  645. return;
  646. #if defined USE_D3D9 || defined _XBOX
  647. switch (mode)
  648. {
  649. case CullMode::Disabled:
  650. m_data->m_d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  651. break;
  652. case CullMode::Clockwise:
  653. m_data->m_d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
  654. break;
  655. case CullMode::CounterClockwise:
  656. m_data->m_d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  657. break;
  658. }
  659. #else
  660. switch (mode)
  661. {
  662. case CullMode::Disabled:
  663. glDisable(GL_CULL_FACE);
  664. break;
  665. case CullMode::Clockwise:
  666. glEnable(GL_CULL_FACE);
  667. glCullFace(GL_FRONT);
  668. glFrontFace(GL_CW);
  669. break;
  670. case CullMode::CounterClockwise:
  671. glEnable(GL_CULL_FACE);
  672. glCullFace(GL_FRONT);
  673. glFrontFace(GL_CCW);
  674. break;
  675. }
  676. #endif
  677. m_data->m_cull_mode = mode;
  678. }
  679. CullMode Renderer::GetCullMode() const
  680. {
  681. return m_data->m_cull_mode;
  682. }
  683. /*
  684. * Polygon rendering mode
  685. */
  686. void Renderer::SetPolygonMode(PolygonMode mode)
  687. {
  688. if (m_data->m_polygon_mode == mode)
  689. return;
  690. #if defined USE_D3D9 || defined _XBOX
  691. switch (mode)
  692. {
  693. case PolygonMode::Point:
  694. m_data->m_d3d_dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT);
  695. break;
  696. case PolygonMode::Line:
  697. m_data->m_d3d_dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
  698. break;
  699. case PolygonMode::Fill:
  700. m_data->m_d3d_dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  701. break;
  702. }
  703. #elif defined __CELLOS_LV2__ || defined GL_VERSION_1_1
  704. switch (mode)
  705. {
  706. case PolygonMode::Point:
  707. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  708. break;
  709. case PolygonMode::Line:
  710. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  711. break;
  712. case PolygonMode::Fill:
  713. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  714. break;
  715. }
  716. #endif
  717. m_data->m_polygon_mode = mode;
  718. }
  719. PolygonMode Renderer::GetPolygonMode() const
  720. {
  721. return m_data->m_polygon_mode;
  722. }
  723. } /* namespace lol */