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