您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

851 行
22 KiB

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