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

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