25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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