842 lines
21 KiB

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