Lighting.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
  3. * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
  4. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/Debug.h>
  9. #include <LibGL/GLContext.h>
  10. namespace GL {
  11. template<typename T>
  12. void GLContext::get_light_param(GLenum light, GLenum pname, T* params)
  13. {
  14. auto const& light_state = m_light_states[light - GL_LIGHT0];
  15. switch (pname) {
  16. case GL_AMBIENT:
  17. params[0] = light_state.ambient_intensity.x();
  18. params[1] = light_state.ambient_intensity.y();
  19. params[2] = light_state.ambient_intensity.z();
  20. params[3] = light_state.ambient_intensity.w();
  21. break;
  22. case GL_DIFFUSE:
  23. params[0] = light_state.diffuse_intensity.x();
  24. params[1] = light_state.diffuse_intensity.y();
  25. params[2] = light_state.diffuse_intensity.z();
  26. params[3] = light_state.diffuse_intensity.w();
  27. break;
  28. case GL_SPECULAR:
  29. params[0] = light_state.specular_intensity.x();
  30. params[1] = light_state.specular_intensity.y();
  31. params[2] = light_state.specular_intensity.z();
  32. params[3] = light_state.specular_intensity.w();
  33. break;
  34. case GL_SPOT_DIRECTION:
  35. params[0] = light_state.spotlight_direction.x();
  36. params[1] = light_state.spotlight_direction.y();
  37. params[2] = light_state.spotlight_direction.z();
  38. break;
  39. case GL_SPOT_EXPONENT:
  40. *params = light_state.spotlight_exponent;
  41. break;
  42. case GL_SPOT_CUTOFF:
  43. *params = light_state.spotlight_cutoff_angle;
  44. break;
  45. case GL_CONSTANT_ATTENUATION:
  46. *params = light_state.constant_attenuation;
  47. break;
  48. case GL_LINEAR_ATTENUATION:
  49. *params = light_state.linear_attenuation;
  50. break;
  51. case GL_QUADRATIC_ATTENUATION:
  52. *params = light_state.quadratic_attenuation;
  53. break;
  54. }
  55. }
  56. template<typename T>
  57. void GLContext::get_material_param(Face face, GLenum pname, T* params)
  58. {
  59. auto const& material = m_material_states[face];
  60. switch (pname) {
  61. case GL_AMBIENT:
  62. params[0] = static_cast<T>(material.ambient.x());
  63. params[1] = static_cast<T>(material.ambient.y());
  64. params[2] = static_cast<T>(material.ambient.z());
  65. params[3] = static_cast<T>(material.ambient.w());
  66. break;
  67. case GL_DIFFUSE:
  68. params[0] = static_cast<T>(material.diffuse.x());
  69. params[1] = static_cast<T>(material.diffuse.y());
  70. params[2] = static_cast<T>(material.diffuse.z());
  71. params[3] = static_cast<T>(material.diffuse.w());
  72. break;
  73. case GL_SPECULAR:
  74. params[0] = static_cast<T>(material.specular.x());
  75. params[1] = static_cast<T>(material.specular.y());
  76. params[2] = static_cast<T>(material.specular.z());
  77. params[3] = static_cast<T>(material.specular.w());
  78. break;
  79. case GL_EMISSION:
  80. params[0] = static_cast<T>(material.emissive.x());
  81. params[1] = static_cast<T>(material.emissive.y());
  82. params[2] = static_cast<T>(material.emissive.z());
  83. params[3] = static_cast<T>(material.emissive.w());
  84. break;
  85. case GL_SHININESS:
  86. *params = material.shininess;
  87. break;
  88. }
  89. }
  90. void GLContext::gl_color_material(GLenum face, GLenum mode)
  91. {
  92. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_color_material, face, mode);
  93. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  94. RETURN_WITH_ERROR_IF(face != GL_FRONT
  95. && face != GL_BACK
  96. && face != GL_FRONT_AND_BACK,
  97. GL_INVALID_ENUM);
  98. RETURN_WITH_ERROR_IF(mode != GL_EMISSION
  99. && mode != GL_AMBIENT
  100. && mode != GL_DIFFUSE
  101. && mode != GL_SPECULAR
  102. && mode != GL_AMBIENT_AND_DIFFUSE,
  103. GL_INVALID_ENUM);
  104. m_color_material_face = face;
  105. m_color_material_mode = mode;
  106. m_light_state_is_dirty = true;
  107. }
  108. void GLContext::gl_get_light(GLenum light, GLenum pname, void* params, GLenum type)
  109. {
  110. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_get_light, light, pname, params, type);
  111. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  112. RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light > GL_LIGHT0 + m_device_info.num_lights, GL_INVALID_ENUM);
  113. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_SPOT_DIRECTION || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_CUTOFF || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION), GL_INVALID_ENUM);
  114. if (type == GL_FLOAT)
  115. get_light_param<GLfloat>(light, pname, static_cast<GLfloat*>(params));
  116. else if (type == GL_INT)
  117. get_light_param<GLint>(light, pname, static_cast<GLint*>(params));
  118. else
  119. VERIFY_NOT_REACHED();
  120. }
  121. void GLContext::gl_get_material(GLenum face, GLenum pname, void* params, GLenum type)
  122. {
  123. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_get_material, face, pname, params, type);
  124. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  125. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION), GL_INVALID_ENUM);
  126. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK), GL_INVALID_ENUM);
  127. Face material_face = Front;
  128. switch (face) {
  129. case GL_FRONT:
  130. material_face = Front;
  131. break;
  132. case GL_BACK:
  133. material_face = Back;
  134. break;
  135. }
  136. if (type == GL_FLOAT)
  137. get_material_param<GLfloat>(material_face, pname, static_cast<GLfloat*>(params));
  138. else if (type == GL_INT)
  139. get_material_param<GLint>(material_face, pname, static_cast<GLint*>(params));
  140. else
  141. VERIFY_NOT_REACHED();
  142. }
  143. void GLContext::gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  144. {
  145. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_light_model, pname, x, y, z, w);
  146. RETURN_WITH_ERROR_IF(pname != GL_LIGHT_MODEL_AMBIENT
  147. && pname != GL_LIGHT_MODEL_COLOR_CONTROL
  148. && pname != GL_LIGHT_MODEL_LOCAL_VIEWER
  149. && pname != GL_LIGHT_MODEL_TWO_SIDE,
  150. GL_INVALID_ENUM);
  151. auto lighting_params = m_rasterizer->light_model();
  152. switch (pname) {
  153. case GL_LIGHT_MODEL_AMBIENT:
  154. lighting_params.scene_ambient_color = { x, y, z, w };
  155. break;
  156. case GL_LIGHT_MODEL_COLOR_CONTROL: {
  157. GLenum color_control = static_cast<GLenum>(x);
  158. RETURN_WITH_ERROR_IF(color_control != GL_SINGLE_COLOR && color_control != GL_SEPARATE_SPECULAR_COLOR, GL_INVALID_ENUM);
  159. lighting_params.color_control = (color_control == GL_SINGLE_COLOR) ? GPU::ColorControl::SingleColor : GPU::ColorControl::SeparateSpecularColor;
  160. break;
  161. }
  162. case GL_LIGHT_MODEL_LOCAL_VIEWER:
  163. // 0 means the viewer is at infinity
  164. // 1 means they're in local (eye) space
  165. lighting_params.viewer_at_infinity = (x != 1.0f);
  166. break;
  167. case GL_LIGHT_MODEL_TWO_SIDE:
  168. VERIFY(y == 0.0f && z == 0.0f && w == 0.0f);
  169. lighting_params.two_sided_lighting = x;
  170. break;
  171. default:
  172. VERIFY_NOT_REACHED();
  173. }
  174. m_rasterizer->set_light_model_params(lighting_params);
  175. }
  176. void GLContext::gl_lightf(GLenum light, GLenum pname, GLfloat param)
  177. {
  178. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightf, light, pname, param);
  179. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  180. RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_device_info.num_lights), GL_INVALID_ENUM);
  181. RETURN_WITH_ERROR_IF(!(pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname != GL_SPOT_EXPONENT || pname != GL_SPOT_CUTOFF), GL_INVALID_ENUM);
  182. RETURN_WITH_ERROR_IF(param < 0.f, GL_INVALID_VALUE);
  183. auto& light_state = m_light_states.at(light - GL_LIGHT0);
  184. switch (pname) {
  185. case GL_CONSTANT_ATTENUATION:
  186. light_state.constant_attenuation = param;
  187. break;
  188. case GL_LINEAR_ATTENUATION:
  189. light_state.linear_attenuation = param;
  190. break;
  191. case GL_QUADRATIC_ATTENUATION:
  192. light_state.quadratic_attenuation = param;
  193. break;
  194. case GL_SPOT_EXPONENT:
  195. RETURN_WITH_ERROR_IF(param > 128.f, GL_INVALID_VALUE);
  196. light_state.spotlight_exponent = param;
  197. break;
  198. case GL_SPOT_CUTOFF:
  199. RETURN_WITH_ERROR_IF(param > 90.f && param != 180.f, GL_INVALID_VALUE);
  200. light_state.spotlight_cutoff_angle = param;
  201. break;
  202. default:
  203. VERIFY_NOT_REACHED();
  204. }
  205. m_light_state_is_dirty = true;
  206. }
  207. void GLContext::gl_lightfv(GLenum light, GLenum pname, GLfloat const* params)
  208. {
  209. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightfv, light, pname, params);
  210. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  211. RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_device_info.num_lights), GL_INVALID_ENUM);
  212. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_POSITION || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname == GL_SPOT_CUTOFF || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_DIRECTION), GL_INVALID_ENUM);
  213. auto& light_state = m_light_states.at(light - GL_LIGHT0);
  214. switch (pname) {
  215. case GL_AMBIENT:
  216. light_state.ambient_intensity = { params[0], params[1], params[2], params[3] };
  217. break;
  218. case GL_DIFFUSE:
  219. light_state.diffuse_intensity = { params[0], params[1], params[2], params[3] };
  220. break;
  221. case GL_SPECULAR:
  222. light_state.specular_intensity = { params[0], params[1], params[2], params[3] };
  223. break;
  224. case GL_POSITION:
  225. light_state.position = { params[0], params[1], params[2], params[3] };
  226. light_state.position = model_view_matrix() * light_state.position;
  227. break;
  228. case GL_CONSTANT_ATTENUATION:
  229. RETURN_WITH_ERROR_IF(params[0] < 0.f, GL_INVALID_VALUE);
  230. light_state.constant_attenuation = params[0];
  231. break;
  232. case GL_LINEAR_ATTENUATION:
  233. RETURN_WITH_ERROR_IF(params[0] < 0.f, GL_INVALID_VALUE);
  234. light_state.linear_attenuation = params[0];
  235. break;
  236. case GL_QUADRATIC_ATTENUATION:
  237. RETURN_WITH_ERROR_IF(params[0] < 0.f, GL_INVALID_VALUE);
  238. light_state.quadratic_attenuation = params[0];
  239. break;
  240. case GL_SPOT_EXPONENT: {
  241. auto exponent = params[0];
  242. RETURN_WITH_ERROR_IF(exponent < 0.f || exponent > 128.f, GL_INVALID_VALUE);
  243. light_state.spotlight_exponent = exponent;
  244. break;
  245. }
  246. case GL_SPOT_CUTOFF: {
  247. auto cutoff = params[0];
  248. RETURN_WITH_ERROR_IF((cutoff < 0.f || cutoff > 90.f) && cutoff != 180.f, GL_INVALID_VALUE);
  249. light_state.spotlight_cutoff_angle = cutoff;
  250. break;
  251. }
  252. case GL_SPOT_DIRECTION: {
  253. FloatVector4 direction_vector = { params[0], params[1], params[2], 0.f };
  254. direction_vector = model_view_matrix() * direction_vector;
  255. light_state.spotlight_direction = direction_vector.xyz();
  256. break;
  257. }
  258. default:
  259. VERIFY_NOT_REACHED();
  260. }
  261. m_light_state_is_dirty = true;
  262. }
  263. void GLContext::gl_lightiv(GLenum light, GLenum pname, GLint const* params)
  264. {
  265. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightiv, light, pname, params);
  266. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  267. RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_device_info.num_lights), GL_INVALID_ENUM);
  268. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_POSITION || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname == GL_SPOT_CUTOFF || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_DIRECTION), GL_INVALID_ENUM);
  269. auto& light_state = m_light_states[light - GL_LIGHT0];
  270. auto const to_float_vector = [](GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
  271. return FloatVector4(x, y, z, w);
  272. };
  273. switch (pname) {
  274. case GL_AMBIENT:
  275. light_state.ambient_intensity = to_float_vector(params[0], params[1], params[2], params[3]);
  276. break;
  277. case GL_DIFFUSE:
  278. light_state.diffuse_intensity = to_float_vector(params[0], params[1], params[2], params[3]);
  279. break;
  280. case GL_SPECULAR:
  281. light_state.specular_intensity = to_float_vector(params[0], params[1], params[2], params[3]);
  282. break;
  283. case GL_POSITION:
  284. light_state.position = to_float_vector(params[0], params[1], params[2], params[3]);
  285. light_state.position = model_view_matrix() * light_state.position;
  286. break;
  287. case GL_CONSTANT_ATTENUATION:
  288. RETURN_WITH_ERROR_IF(params[0] < 0, GL_INVALID_VALUE);
  289. light_state.constant_attenuation = static_cast<float>(params[0]);
  290. break;
  291. case GL_LINEAR_ATTENUATION:
  292. RETURN_WITH_ERROR_IF(params[0] < 0, GL_INVALID_VALUE);
  293. light_state.linear_attenuation = static_cast<float>(params[0]);
  294. break;
  295. case GL_QUADRATIC_ATTENUATION:
  296. RETURN_WITH_ERROR_IF(params[0] < 0, GL_INVALID_VALUE);
  297. light_state.quadratic_attenuation = static_cast<float>(params[0]);
  298. break;
  299. case GL_SPOT_EXPONENT: {
  300. auto exponent = static_cast<float>(params[0]);
  301. RETURN_WITH_ERROR_IF(exponent < 0.f || exponent > 128.f, GL_INVALID_VALUE);
  302. light_state.spotlight_exponent = exponent;
  303. break;
  304. }
  305. case GL_SPOT_CUTOFF: {
  306. auto cutoff = static_cast<float>(params[0]);
  307. RETURN_WITH_ERROR_IF((cutoff < 0.f || cutoff > 90.f) && cutoff != 180.f, GL_INVALID_VALUE);
  308. light_state.spotlight_cutoff_angle = cutoff;
  309. break;
  310. }
  311. case GL_SPOT_DIRECTION: {
  312. auto direction_vector = to_float_vector(params[0], params[1], params[2], 0.0f);
  313. direction_vector = model_view_matrix() * direction_vector;
  314. light_state.spotlight_direction = direction_vector.xyz();
  315. break;
  316. }
  317. default:
  318. VERIFY_NOT_REACHED();
  319. }
  320. m_light_state_is_dirty = true;
  321. }
  322. void GLContext::gl_materialf(GLenum face, GLenum pname, GLfloat param)
  323. {
  324. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialf, face, pname, param);
  325. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  326. RETURN_WITH_ERROR_IF(pname != GL_SHININESS, GL_INVALID_ENUM);
  327. RETURN_WITH_ERROR_IF(param > 128.0f, GL_INVALID_VALUE);
  328. switch (face) {
  329. case GL_FRONT:
  330. m_material_states[Face::Front].shininess = param;
  331. break;
  332. case GL_BACK:
  333. m_material_states[Face::Back].shininess = param;
  334. break;
  335. case GL_FRONT_AND_BACK:
  336. m_material_states[Face::Front].shininess = param;
  337. m_material_states[Face::Back].shininess = param;
  338. break;
  339. default:
  340. VERIFY_NOT_REACHED();
  341. }
  342. m_light_state_is_dirty = true;
  343. }
  344. void GLContext::gl_materialfv(GLenum face, GLenum pname, GLfloat const* params)
  345. {
  346. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialfv, face, pname, params);
  347. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  348. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION || pname == GL_SHININESS || pname == GL_AMBIENT_AND_DIFFUSE), GL_INVALID_ENUM);
  349. RETURN_WITH_ERROR_IF((pname == GL_SHININESS && *params > 128.0f), GL_INVALID_VALUE);
  350. auto update_material = [](GPU::Material& material, GLenum pname, GLfloat const* params) {
  351. switch (pname) {
  352. case GL_AMBIENT:
  353. material.ambient = { params[0], params[1], params[2], params[3] };
  354. break;
  355. case GL_DIFFUSE:
  356. material.diffuse = { params[0], params[1], params[2], params[3] };
  357. break;
  358. case GL_SPECULAR:
  359. material.specular = { params[0], params[1], params[2], params[3] };
  360. break;
  361. case GL_EMISSION:
  362. material.emissive = { params[0], params[1], params[2], params[3] };
  363. break;
  364. case GL_SHININESS:
  365. material.shininess = params[0];
  366. break;
  367. case GL_AMBIENT_AND_DIFFUSE:
  368. material.ambient = { params[0], params[1], params[2], params[3] };
  369. material.diffuse = { params[0], params[1], params[2], params[3] };
  370. break;
  371. }
  372. };
  373. switch (face) {
  374. case GL_FRONT:
  375. update_material(m_material_states[Face::Front], pname, params);
  376. break;
  377. case GL_BACK:
  378. update_material(m_material_states[Face::Back], pname, params);
  379. break;
  380. case GL_FRONT_AND_BACK:
  381. update_material(m_material_states[Face::Front], pname, params);
  382. update_material(m_material_states[Face::Back], pname, params);
  383. break;
  384. }
  385. m_light_state_is_dirty = true;
  386. }
  387. void GLContext::gl_materialiv(GLenum face, GLenum pname, GLint const* params)
  388. {
  389. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialiv, face, pname, params);
  390. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  391. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION || pname == GL_SHININESS || pname == GL_AMBIENT_AND_DIFFUSE), GL_INVALID_ENUM);
  392. RETURN_WITH_ERROR_IF((pname == GL_SHININESS && *params > 128), GL_INVALID_VALUE);
  393. auto update_material = [](GPU::Material& material, GLenum pname, GLint const* params) {
  394. switch (pname) {
  395. case GL_AMBIENT:
  396. material.ambient = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) };
  397. break;
  398. case GL_DIFFUSE:
  399. material.diffuse = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) };
  400. break;
  401. case GL_SPECULAR:
  402. material.specular = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) };
  403. break;
  404. case GL_EMISSION:
  405. material.emissive = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) };
  406. break;
  407. case GL_SHININESS:
  408. material.shininess = static_cast<float>(params[0]);
  409. break;
  410. case GL_AMBIENT_AND_DIFFUSE:
  411. material.ambient = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) };
  412. material.diffuse = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) };
  413. break;
  414. }
  415. };
  416. switch (face) {
  417. case GL_FRONT:
  418. update_material(m_material_states[Face::Front], pname, params);
  419. break;
  420. case GL_BACK:
  421. update_material(m_material_states[Face::Back], pname, params);
  422. break;
  423. case GL_FRONT_AND_BACK:
  424. update_material(m_material_states[Face::Front], pname, params);
  425. update_material(m_material_states[Face::Back], pname, params);
  426. break;
  427. }
  428. m_light_state_is_dirty = true;
  429. }
  430. void GLContext::gl_shade_model(GLenum mode)
  431. {
  432. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_shade_model, mode);
  433. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  434. RETURN_WITH_ERROR_IF(mode != GL_FLAT && mode != GL_SMOOTH, GL_INVALID_ENUM);
  435. auto options = m_rasterizer->options();
  436. options.shade_smooth = (mode == GL_SMOOTH);
  437. m_rasterizer->set_options(options);
  438. }
  439. void GLContext::sync_light_state()
  440. {
  441. if (!m_light_state_is_dirty)
  442. return;
  443. m_light_state_is_dirty = false;
  444. auto options = m_rasterizer->options();
  445. options.color_material_enabled = m_color_material_enabled;
  446. switch (m_color_material_face) {
  447. case GL_BACK:
  448. options.color_material_face = GPU::ColorMaterialFace::Back;
  449. break;
  450. case GL_FRONT:
  451. options.color_material_face = GPU::ColorMaterialFace::Front;
  452. break;
  453. case GL_FRONT_AND_BACK:
  454. options.color_material_face = GPU::ColorMaterialFace::FrontAndBack;
  455. break;
  456. default:
  457. VERIFY_NOT_REACHED();
  458. }
  459. switch (m_color_material_mode) {
  460. case GL_AMBIENT:
  461. options.color_material_mode = GPU::ColorMaterialMode::Ambient;
  462. break;
  463. case GL_AMBIENT_AND_DIFFUSE:
  464. options.color_material_mode = GPU::ColorMaterialMode::AmbientAndDiffuse;
  465. break;
  466. case GL_DIFFUSE:
  467. options.color_material_mode = GPU::ColorMaterialMode::Diffuse;
  468. break;
  469. case GL_EMISSION:
  470. options.color_material_mode = GPU::ColorMaterialMode::Emissive;
  471. break;
  472. case GL_SPECULAR:
  473. options.color_material_mode = GPU::ColorMaterialMode::Specular;
  474. break;
  475. default:
  476. VERIFY_NOT_REACHED();
  477. }
  478. m_rasterizer->set_options(options);
  479. for (auto light_id = 0u; light_id < m_device_info.num_lights; light_id++) {
  480. auto const& current_light_state = m_light_states.at(light_id);
  481. m_rasterizer->set_light_state(light_id, current_light_state);
  482. }
  483. m_rasterizer->set_material_state(GPU::Face::Front, m_material_states[Face::Front]);
  484. m_rasterizer->set_material_state(GPU::Face::Back, m_material_states[Face::Back]);
  485. }
  486. }