test_glsl_shader.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. from panda3d import core
  2. import os
  3. import struct
  4. import pytest
  5. from _pytest.outcomes import Failed
  6. SHADERS_DIR = core.Filename.from_os_specific(os.path.dirname(__file__))
  7. # This is the template for the compute shader that is used by run_glsl_test.
  8. # It defines an assert() macro that writes failures to a buffer, indexed by
  9. # line number.
  10. # The reset() function serves to prevent the _triggered variable from being
  11. # optimized out in the case that the assertions are being optimized out.
  12. GLSL_COMPUTE_TEMPLATE = """#version {version}
  13. {extensions}
  14. layout(local_size_x = 1, local_size_y = 1) in;
  15. {preamble}
  16. layout(r8ui) uniform writeonly uimageBuffer _triggered;
  17. void _reset() {{
  18. imageStore(_triggered, 0, uvec4(0, 0, 0, 0));
  19. memoryBarrier();
  20. }}
  21. void _assert(bool cond, int line) {{
  22. if (!cond) {{
  23. imageStore(_triggered, line, uvec4(1));
  24. }}
  25. }}
  26. #define assert(cond) _assert(cond, __LINE__)
  27. void main() {{
  28. _reset();
  29. {body}
  30. }}
  31. """
  32. def run_glsl_test(gsg, body, preamble="", inputs={}, version=150, exts=set(), state=None):
  33. """ Runs a GLSL test on the given GSG. The given body is executed in the
  34. main function and should call assert(). The preamble should contain all
  35. of the shader inputs. """
  36. if not gsg.supports_compute_shaders or not gsg.supports_glsl:
  37. pytest.skip("compute shaders not supported")
  38. if not gsg.supports_buffer_texture:
  39. pytest.skip("buffer textures not supported")
  40. exts = exts | {'GL_ARB_compute_shader', 'GL_ARB_shader_image_load_store'}
  41. missing_exts = sorted(ext for ext in exts if not gsg.has_extension(ext))
  42. if missing_exts:
  43. pytest.skip("missing extensions: " + ' '.join(missing_exts))
  44. extensions = ''
  45. for ext in exts:
  46. extensions += '#extension {ext} : require\n'.format(ext=ext)
  47. __tracebackhide__ = True
  48. preamble = preamble.strip()
  49. body = body.rstrip().lstrip('\n')
  50. code = GLSL_COMPUTE_TEMPLATE.format(version=version, extensions=extensions, preamble=preamble, body=body)
  51. line_offset = code[:code.find(body)].count('\n') + 1
  52. shader = core.Shader.make_compute(core.Shader.SL_GLSL, code)
  53. assert shader, code
  54. # Create a buffer to hold the results of the assertion. We use one byte
  55. # per line of shader code, so we can show which lines triggered.
  56. result = core.Texture("")
  57. result.set_clear_color((0, 0, 0, 0))
  58. result.setup_buffer_texture(code.count('\n'), core.Texture.T_unsigned_byte,
  59. core.Texture.F_r8i, core.GeomEnums.UH_static)
  60. # Build up the shader inputs
  61. attrib = core.ShaderAttrib.make(shader)
  62. for name, value in inputs.items():
  63. attrib = attrib.set_shader_input(name, value)
  64. attrib = attrib.set_shader_input('_triggered', result)
  65. if not state:
  66. state = core.RenderState.make(attrib)
  67. else:
  68. state = state.set_attrib(attrib)
  69. # Run the compute shader.
  70. engine = core.GraphicsEngine.get_global_ptr()
  71. try:
  72. engine.dispatch_compute((1, 1, 1), state, gsg)
  73. except AssertionError as exc:
  74. assert False, "Error executing compute shader:\n" + code
  75. # Download the texture to check whether the assertion triggered.
  76. assert engine.extract_texture_data(result, gsg)
  77. triggered = result.get_ram_image()
  78. if any(triggered):
  79. count = len(triggered) - triggered.count(0)
  80. lines = body.split('\n')
  81. formatted = ''
  82. for i, line in enumerate(lines):
  83. if triggered[i + line_offset]:
  84. formatted += '=> ' + line + '\n'
  85. else:
  86. formatted += ' ' + line + '\n'
  87. pytest.fail("{0} GLSL assertions triggered:\n{1}".format(count, formatted))
  88. def run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=False):
  89. """Compile supplied GLSL shader paths and check for errors"""
  90. shader = core.Shader.load(core.Shader.SL_GLSL, vert_path, frag_path)
  91. assert shader is not None
  92. if not gsg.supports_glsl:
  93. expect_fail = True
  94. shader.prepare_now(gsg.prepared_objects, gsg)
  95. assert shader.is_prepared(gsg.prepared_objects)
  96. if expect_fail:
  97. assert shader.get_error_flag()
  98. else:
  99. assert not shader.get_error_flag()
  100. def test_glsl_test(gsg):
  101. "Test to make sure that the GLSL tests work correctly."
  102. run_glsl_test(gsg, "assert(true);")
  103. def test_glsl_test_fail(gsg):
  104. "Same as above, but making sure that the failure case works correctly."
  105. with pytest.raises(Failed):
  106. run_glsl_test(gsg, "assert(false);")
  107. def test_glsl_sampler(gsg):
  108. tex1 = core.Texture("")
  109. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8)
  110. tex1.set_clear_color((0, 2 / 255.0, 1, 1))
  111. tex2 = core.Texture("")
  112. tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32)
  113. tex2.set_clear_color((1.0, 2.0, -3.14, 0.0))
  114. tex3 = core.Texture("")
  115. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_float, core.Texture.F_r32)
  116. tex3.set_clear_color((0.5, 0.0, 0.0, 1.0))
  117. preamble = """
  118. uniform sampler1D tex1;
  119. uniform sampler2D tex2;
  120. uniform sampler3D tex3;
  121. """
  122. code = """
  123. assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1));
  124. assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0));
  125. assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == vec4(0.5, 0.0, 0.0, 1.0));
  126. """
  127. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  128. def test_glsl_isampler(gsg):
  129. from struct import pack
  130. tex1 = core.Texture("")
  131. tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i)
  132. tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3))
  133. tex2 = core.Texture("")
  134. tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i)
  135. tex2.set_ram_image(pack('h', 4))
  136. tex3 = core.Texture("")
  137. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i)
  138. tex3.set_ram_image(pack('i', 5))
  139. preamble = """
  140. uniform isampler1D tex1;
  141. uniform isampler2D tex2;
  142. uniform isampler3D tex3;
  143. """
  144. code = """
  145. assert(texelFetch(tex1, 0, 0) == ivec4(0, 1, 2, 3));
  146. assert(texelFetch(tex2, ivec2(0, 0), 0) == ivec4(4, 0, 0, 1));
  147. assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == ivec4(5, 0, 0, 1));
  148. """
  149. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  150. def test_glsl_usampler(gsg):
  151. from struct import pack
  152. tex1 = core.Texture("")
  153. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i)
  154. tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3))
  155. tex2 = core.Texture("")
  156. tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i)
  157. tex2.set_ram_image(pack('H', 4))
  158. tex3 = core.Texture("")
  159. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i)
  160. tex3.set_ram_image(pack('I', 5))
  161. preamble = """
  162. uniform usampler1D tex1;
  163. uniform usampler2D tex2;
  164. uniform usampler3D tex3;
  165. """
  166. code = """
  167. assert(texelFetch(tex1, 0, 0) == uvec4(0, 1, 2, 3));
  168. assert(texelFetch(tex2, ivec2(0, 0), 0) == uvec4(4, 0, 0, 1));
  169. assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == uvec4(5, 0, 0, 1));
  170. """
  171. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  172. def test_glsl_image(gsg):
  173. tex1 = core.Texture("")
  174. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8)
  175. tex1.set_clear_color((0, 2 / 255.0, 1, 1))
  176. tex2 = core.Texture("")
  177. tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32)
  178. tex2.set_clear_color((1.0, 2.0, -3.14, 0.0))
  179. preamble = """
  180. layout(rgba8) uniform image1D tex1;
  181. layout(rgba32f) uniform image2D tex2;
  182. """
  183. code = """
  184. assert(imageLoad(tex1, 0) == vec4(0, 2 / 255.0, 1, 1));
  185. assert(imageLoad(tex2, ivec2(0, 0)) == vec4(1.0, 2.0, -3.14, 0.0));
  186. """
  187. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
  188. def test_glsl_iimage(gsg):
  189. from struct import pack
  190. tex1 = core.Texture("")
  191. tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i)
  192. tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3))
  193. tex2 = core.Texture("")
  194. tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i)
  195. tex2.set_ram_image(pack('h', 4))
  196. tex3 = core.Texture("")
  197. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i)
  198. tex3.set_ram_image(pack('i', 5))
  199. preamble = """
  200. layout(rgba8i) uniform iimage1D tex1;
  201. layout(r16i) uniform iimage2D tex2;
  202. layout(r32i) uniform iimage3D tex3;
  203. """
  204. code = """
  205. assert(imageLoad(tex1, 0) == ivec4(0, 1, 2, 3));
  206. assert(imageLoad(tex2, ivec2(0, 0)) == ivec4(4, 0, 0, 1));
  207. assert(imageLoad(tex3, ivec3(0, 0, 0)) == ivec4(5, 0, 0, 1));
  208. """
  209. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  210. def test_glsl_uimage(gsg):
  211. from struct import pack
  212. tex1 = core.Texture("")
  213. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i)
  214. tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3))
  215. tex2 = core.Texture("")
  216. tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i)
  217. tex2.set_ram_image(pack('H', 4))
  218. tex3 = core.Texture("")
  219. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i)
  220. tex3.set_ram_image(pack('I', 5))
  221. preamble = """
  222. layout(rgba8ui) uniform uimage1D tex1;
  223. layout(r16ui) uniform uimage2D tex2;
  224. layout(r32ui) uniform uimage3D tex3;
  225. """
  226. code = """
  227. assert(imageLoad(tex1, 0) == uvec4(0, 1, 2, 3));
  228. assert(imageLoad(tex2, ivec2(0, 0)) == uvec4(4, 0, 0, 1));
  229. assert(imageLoad(tex3, ivec3(0, 0, 0)) == uvec4(5, 0, 0, 1));
  230. """
  231. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  232. def test_glsl_ssbo(gsg):
  233. from struct import pack, unpack
  234. num1 = pack('<i', 1234567)
  235. num2 = pack('<i', -1234567)
  236. buffer1 = core.ShaderBuffer("buffer1", num1, core.GeomEnums.UH_static)
  237. buffer2 = core.ShaderBuffer("buffer2", num2, core.GeomEnums.UH_static)
  238. preamble = """
  239. layout(std430, binding=0) buffer buffer1 {
  240. int value1;
  241. };
  242. layout(std430, binding=1) buffer buffer2 {
  243. int value2;
  244. };
  245. """
  246. code = """
  247. assert(value1 == 1234567);
  248. assert(value2 == -1234567);
  249. value1 = 98765;
  250. value2 = 5343525;
  251. """
  252. run_glsl_test(gsg, code, preamble, {'buffer1': buffer1, 'buffer2': buffer2},
  253. exts={'GL_ARB_shader_storage_buffer_object',
  254. 'GL_ARB_uniform_buffer_object',
  255. 'GL_ARB_shading_language_420pack'})
  256. data1 = gsg.get_engine().extract_shader_buffer_data(buffer1, gsg)
  257. assert unpack('<i', data1[:4]) == (98765, )
  258. data2 = gsg.get_engine().extract_shader_buffer_data(buffer2, gsg)
  259. assert unpack('<i', data2[:4]) == (5343525, )
  260. def test_glsl_int(gsg):
  261. inputs = dict(
  262. zero=0,
  263. intmax=0x7fffffff,
  264. intmin=-0x7fffffff,
  265. )
  266. preamble = """
  267. uniform int zero;
  268. uniform int intmax;
  269. uniform int intmin;
  270. """
  271. code = """
  272. assert(zero == 0);
  273. assert(intmax == 0x7fffffff);
  274. assert(intmin == -0x7fffffff);
  275. """
  276. run_glsl_test(gsg, code, preamble, inputs)
  277. def test_glsl_uint(gsg):
  278. #TODO: fix passing uints greater than intmax
  279. inputs = dict(
  280. zero=0,
  281. intmax=0x7fffffff,
  282. )
  283. preamble = """
  284. uniform uint zero;
  285. uniform uint intmax;
  286. """
  287. code = """
  288. assert(zero == 0u);
  289. assert(intmax == 0x7fffffffu);
  290. """
  291. run_glsl_test(gsg, code, preamble, inputs)
  292. def test_glsl_bool(gsg):
  293. flags = dict(
  294. flag1=False,
  295. flag2=0,
  296. flag3=0.0,
  297. flag4=True,
  298. flag5=1,
  299. flag6=3,
  300. )
  301. preamble = """
  302. uniform bool flag1;
  303. uniform bool flag2;
  304. uniform bool flag3;
  305. uniform bool flag4;
  306. uniform bool flag5;
  307. uniform bool flag6;
  308. """
  309. code = """
  310. assert(!flag1);
  311. assert(!flag2);
  312. assert(!flag3);
  313. assert(flag4);
  314. assert(flag5);
  315. assert(flag6);
  316. """
  317. run_glsl_test(gsg, code, preamble, flags)
  318. def test_glsl_mat3(gsg):
  319. param1 = core.LMatrix4(core.LMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9))
  320. param2 = core.NodePath("param2")
  321. param2.set_mat(core.LMatrix3(10, 11, 12, 13, 14, 15, 16, 17, 18))
  322. preamble = """
  323. uniform mat3 param1;
  324. uniform mat3 param2;
  325. """
  326. code = """
  327. assert(param1[0] == vec3(1, 2, 3));
  328. assert(param1[1] == vec3(4, 5, 6));
  329. assert(param1[2] == vec3(7, 8, 9));
  330. assert(param2[0] == vec3(10, 11, 12));
  331. assert(param2[1] == vec3(13, 14, 15));
  332. assert(param2[2] == vec3(16, 17, 18));
  333. """
  334. run_glsl_test(gsg, code, preamble, {'param1': param1, 'param2': param2})
  335. def test_glsl_mat4(gsg):
  336. param1 = core.LMatrix4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
  337. param2 = core.NodePath("param2")
  338. param2.set_mat(core.LMatrix4(
  339. 17, 18, 19, 20,
  340. 21, 22, 23, 24,
  341. 25, 26, 27, 28,
  342. 29, 30, 31, 32))
  343. preamble = """
  344. uniform mat4 param1;
  345. uniform mat4 param2;
  346. """
  347. code = """
  348. assert(param1[0] == vec4(1, 2, 3, 4));
  349. assert(param1[1] == vec4(5, 6, 7, 8));
  350. assert(param1[2] == vec4(9, 10, 11, 12));
  351. assert(param1[3] == vec4(13, 14, 15, 16));
  352. assert(param2[0] == vec4(17, 18, 19, 20));
  353. assert(param2[1] == vec4(21, 22, 23, 24));
  354. assert(param2[2] == vec4(25, 26, 27, 28));
  355. assert(param2[3] == vec4(29, 30, 31, 32));
  356. """
  357. run_glsl_test(gsg, code, preamble, {'param1': param1, 'param2': param2})
  358. def test_glsl_pta_int(gsg):
  359. pta = core.PTA_int((0, 1, 2, 3))
  360. preamble = """
  361. uniform int pta[4];
  362. """
  363. code = """
  364. assert(pta[0] == 0);
  365. assert(pta[1] == 1);
  366. assert(pta[2] == 2);
  367. assert(pta[3] == 3);
  368. """
  369. run_glsl_test(gsg, code, preamble, {'pta': pta})
  370. def test_glsl_pta_ivec4(gsg):
  371. pta = core.PTA_LVecBase4i(((0, 1, 2, 3), (4, 5, 6, 7)))
  372. preamble = """
  373. uniform ivec4 pta[2];
  374. """
  375. code = """
  376. assert(pta[0] == ivec4(0, 1, 2, 3));
  377. assert(pta[1] == ivec4(4, 5, 6, 7));
  378. """
  379. run_glsl_test(gsg, code, preamble, {'pta': pta})
  380. def test_glsl_pta_mat3(gsg):
  381. pta = core.PTA_LMatrix3f((
  382. (0, 1, 2, 3, 4, 5, 6, 7, 8),
  383. (9, 10, 11, 12, 13, 14, 15, 16, 17),
  384. ))
  385. preamble = """
  386. uniform mat3 pta[2];
  387. """
  388. code = """
  389. assert(pta[0][0] == vec3(0, 1, 2));
  390. assert(pta[0][1] == vec3(3, 4, 5));
  391. assert(pta[0][2] == vec3(6, 7, 8));
  392. assert(pta[1][0] == vec3(9, 10, 11));
  393. assert(pta[1][1] == vec3(12, 13, 14));
  394. assert(pta[1][2] == vec3(15, 16, 17));
  395. """
  396. run_glsl_test(gsg, code, preamble, {'pta': pta})
  397. def test_glsl_pta_mat4(gsg):
  398. pta = core.PTA_LMatrix4f((
  399. (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
  400. (16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31),
  401. ))
  402. preamble = """
  403. uniform mat4 pta[2];
  404. """
  405. code = """
  406. assert(pta[0][0] == vec4(0, 1, 2, 3));
  407. assert(pta[0][1] == vec4(4, 5, 6, 7));
  408. assert(pta[0][2] == vec4(8, 9, 10, 11));
  409. assert(pta[0][3] == vec4(12, 13, 14, 15));
  410. assert(pta[1][0] == vec4(16, 17, 18, 19));
  411. assert(pta[1][1] == vec4(20, 21, 22, 23));
  412. assert(pta[1][2] == vec4(24, 25, 26, 27));
  413. assert(pta[1][3] == vec4(28, 29, 30, 31));
  414. """
  415. run_glsl_test(gsg, code, preamble, {'pta': pta})
  416. def test_glsl_param_vec4(gsg):
  417. param = core.ParamVecBase4((0, 1, 2, 3))
  418. preamble = """
  419. uniform vec4 param;
  420. """
  421. code = """
  422. assert(param.x == 0.0);
  423. assert(param.y == 1.0);
  424. assert(param.z == 2.0);
  425. assert(param.w == 3.0);
  426. """
  427. run_glsl_test(gsg, code, preamble, {'param': param})
  428. def test_glsl_param_ivec4(gsg):
  429. param = core.ParamVecBase4i((0, 1, 2, 3))
  430. preamble = """
  431. uniform ivec4 param;
  432. """
  433. code = """
  434. assert(param.x == 0);
  435. assert(param.y == 1);
  436. assert(param.z == 2);
  437. assert(param.w == 3);
  438. """
  439. run_glsl_test(gsg, code, preamble, {'param': param})
  440. def test_glsl_named_light_source(gsg):
  441. spot = core.Spotlight("spot")
  442. spot.get_lens().set_fov(90, 90)
  443. spot.set_color((1, 2, 3, 4))
  444. spot.set_specular_color((5, 6, 7, 8))
  445. preamble = """
  446. struct p3d_LightSourceParameters {
  447. vec4 color;
  448. vec4 specular;
  449. };
  450. uniform p3d_LightSourceParameters spot;
  451. """
  452. code = """
  453. assert(spot.color == vec4(1, 2, 3, 4));
  454. assert(spot.specular == vec4(5, 6, 7, 8));
  455. """
  456. run_glsl_test(gsg, code, preamble, {'spot': core.NodePath(spot)})
  457. def test_glsl_state_light_source(gsg):
  458. spot = core.Spotlight("spot")
  459. spot.priority = 3
  460. spot.get_lens().set_fov(120, 120)
  461. spot.set_color((1, 2, 3, 4))
  462. spot.set_specular_color((5, 6, 7, 8))
  463. spot.attenuation = (23, 24, 25)
  464. spot.exponent = 26
  465. dire = core.DirectionalLight("dire")
  466. dire.priority = 2
  467. dire.set_color((9, 10, 11, 12))
  468. dire.set_specular_color((13, 14, 15, 16))
  469. dire.direction = (17, 18, 19)
  470. preamble = """
  471. struct p3d_LightSourceParameters {
  472. vec4 color;
  473. vec4 specular;
  474. vec4 ambient;
  475. vec4 diffuse;
  476. vec4 position;
  477. vec3 attenuation;
  478. float constantAttenuation;
  479. float linearAttenuation;
  480. float quadraticAttenuation;
  481. float spotExponent;
  482. float spotCosCutoff;
  483. float spotCutoff;
  484. mat4 shadowViewMatrix;
  485. };
  486. uniform p3d_LightSourceParameters p3d_LightSource[3];
  487. """
  488. code = """
  489. assert(p3d_LightSource[0].color == vec4(1, 2, 3, 4));
  490. assert(p3d_LightSource[0].specular == vec4(5, 6, 7, 8));
  491. assert(p3d_LightSource[0].ambient == vec4(0, 0, 0, 1));
  492. assert(p3d_LightSource[0].diffuse == vec4(1, 2, 3, 4));
  493. assert(p3d_LightSource[0].position == vec4(20, 21, 22, 1));
  494. assert(p3d_LightSource[0].attenuation == vec3(23, 24, 25));
  495. assert(p3d_LightSource[0].constantAttenuation == 23);
  496. assert(p3d_LightSource[0].linearAttenuation == 24);
  497. assert(p3d_LightSource[0].quadraticAttenuation == 25);
  498. assert(p3d_LightSource[0].spotExponent == 26);
  499. assert(p3d_LightSource[0].spotCosCutoff > 0.499);
  500. assert(p3d_LightSource[0].spotCosCutoff < 0.501);
  501. assert(p3d_LightSource[0].spotCutoff == 60);
  502. assert(p3d_LightSource[0].shadowViewMatrix[0][0] > 0.2886);
  503. assert(p3d_LightSource[0].shadowViewMatrix[0][0] < 0.2887);
  504. assert(p3d_LightSource[0].shadowViewMatrix[0][1] == 0);
  505. assert(p3d_LightSource[0].shadowViewMatrix[0][2] == 0);
  506. assert(p3d_LightSource[0].shadowViewMatrix[0][3] == 0);
  507. assert(p3d_LightSource[0].shadowViewMatrix[1][0] == 0);
  508. assert(p3d_LightSource[0].shadowViewMatrix[1][1] > 0.2886);
  509. assert(p3d_LightSource[0].shadowViewMatrix[1][1] < 0.2887);
  510. assert(p3d_LightSource[0].shadowViewMatrix[1][2] == 0);
  511. assert(p3d_LightSource[0].shadowViewMatrix[1][3] == 0);
  512. assert(p3d_LightSource[0].shadowViewMatrix[2][0] == -0.5);
  513. assert(p3d_LightSource[0].shadowViewMatrix[2][1] == -0.5);
  514. assert(p3d_LightSource[0].shadowViewMatrix[2][2] > -1.00002);
  515. assert(p3d_LightSource[0].shadowViewMatrix[2][2] < -1.0);
  516. assert(p3d_LightSource[0].shadowViewMatrix[2][3] == -1);
  517. assert(p3d_LightSource[0].shadowViewMatrix[3][0] > -16.2736);
  518. assert(p3d_LightSource[0].shadowViewMatrix[3][0] < -16.2734);
  519. assert(p3d_LightSource[0].shadowViewMatrix[3][1] > -16.8510);
  520. assert(p3d_LightSource[0].shadowViewMatrix[3][1] < -16.8508);
  521. assert(p3d_LightSource[0].shadowViewMatrix[3][2] > -22.0003);
  522. assert(p3d_LightSource[0].shadowViewMatrix[3][2] < -22.0001);
  523. assert(p3d_LightSource[0].shadowViewMatrix[3][3] > -21.0001);
  524. assert(p3d_LightSource[0].shadowViewMatrix[3][3] < -20.9999);
  525. assert(p3d_LightSource[1].color == vec4(9, 10, 11, 12));
  526. assert(p3d_LightSource[1].specular == vec4(13, 14, 15, 16));
  527. assert(p3d_LightSource[1].diffuse == vec4(9, 10, 11, 12));
  528. assert(p3d_LightSource[1].ambient == vec4(0, 0, 0, 1));
  529. assert(p3d_LightSource[1].position == vec4(-17, -18, -19, 0));
  530. assert(p3d_LightSource[1].attenuation == vec3(1, 0, 0));
  531. assert(p3d_LightSource[1].constantAttenuation == 1);
  532. assert(p3d_LightSource[1].linearAttenuation == 0);
  533. assert(p3d_LightSource[1].quadraticAttenuation == 0);
  534. assert(p3d_LightSource[1].spotExponent == 0);
  535. assert(p3d_LightSource[1].spotCosCutoff == -1);
  536. assert(p3d_LightSource[2].color == vec4(0, 0, 0, 1));
  537. assert(p3d_LightSource[2].specular == vec4(0, 0, 0, 1));
  538. assert(p3d_LightSource[2].diffuse == vec4(0, 0, 0, 1));
  539. assert(p3d_LightSource[2].ambient == vec4(0, 0, 0, 1));
  540. assert(p3d_LightSource[2].position == vec4(0, 0, 1, 0));
  541. assert(p3d_LightSource[2].attenuation == vec3(1, 0, 0));
  542. assert(p3d_LightSource[2].constantAttenuation == 1);
  543. assert(p3d_LightSource[2].linearAttenuation == 0);
  544. assert(p3d_LightSource[2].quadraticAttenuation == 0);
  545. assert(p3d_LightSource[2].spotExponent == 0);
  546. assert(p3d_LightSource[2].spotCosCutoff == -1);
  547. """
  548. node = core.NodePath("state")
  549. spot_path = node.attach_new_node(spot)
  550. spot_path.set_pos(20, 21, 22)
  551. node.set_light(spot_path)
  552. dire_path = node.attach_new_node(dire)
  553. node.set_light(dire_path)
  554. run_glsl_test(gsg, code, preamble, state=node.get_state())
  555. def test_glsl_state_material(gsg):
  556. mat = core.Material("mat")
  557. mat.ambient = (1, 2, 3, 4)
  558. mat.diffuse = (5, 6, 7, 8)
  559. mat.emission = (9, 10, 11, 12)
  560. mat.specular = (13, 14, 15, 0)
  561. mat.shininess = 16
  562. mat.metallic = 0.5
  563. mat.refractive_index = 21
  564. preamble = """
  565. struct p3d_MaterialParameters {
  566. vec4 ambient;
  567. vec4 diffuse;
  568. vec4 emission;
  569. vec3 specular;
  570. float shininess;
  571. float metallic;
  572. float refractiveIndex;
  573. };
  574. uniform p3d_MaterialParameters p3d_Material;
  575. """
  576. code = """
  577. assert(p3d_Material.ambient == vec4(1, 2, 3, 4));
  578. assert(p3d_Material.diffuse == vec4(5, 6, 7, 8));
  579. assert(p3d_Material.emission == vec4(9, 10, 11, 12));
  580. assert(p3d_Material.specular == vec3(13, 14, 15));
  581. assert(p3d_Material.shininess == 16);
  582. assert(p3d_Material.metallic == 0.5);
  583. assert(p3d_Material.refractiveIndex == 21);
  584. """
  585. node = core.NodePath("state")
  586. node.set_material(mat)
  587. run_glsl_test(gsg, code, preamble, state=node.get_state())
  588. def test_glsl_state_material_pbr(gsg):
  589. mat = core.Material("mat")
  590. mat.base_color = (1, 2, 3, 4)
  591. mat.emission = (9, 10, 11, 12)
  592. mat.roughness = 16
  593. mat.metallic = 0.5
  594. mat.refractive_index = 21
  595. preamble = """
  596. struct p3d_MaterialParameters {
  597. vec4 baseColor;
  598. vec4 emission;
  599. float metallic;
  600. float refractiveIndex;
  601. float roughness;
  602. };
  603. uniform p3d_MaterialParameters p3d_Material;
  604. """
  605. code = """
  606. assert(p3d_Material.baseColor == vec4(1, 2, 3, 4));
  607. assert(p3d_Material.emission == vec4(9, 10, 11, 12));
  608. assert(p3d_Material.roughness == 16);
  609. assert(p3d_Material.metallic == 0.5);
  610. assert(p3d_Material.refractiveIndex == 21);
  611. """
  612. node = core.NodePath("state")
  613. node.set_material(mat)
  614. run_glsl_test(gsg, code, preamble, state=node.get_state())
  615. def test_glsl_state_fog(gsg):
  616. fog = core.Fog("fog")
  617. fog.color = (1, 2, 3, 4)
  618. fog.exp_density = 0.5
  619. fog.set_linear_range(6, 10)
  620. preamble = """
  621. struct p3d_FogParameters {
  622. vec4 color;
  623. float density;
  624. float start;
  625. float end;
  626. float scale;
  627. };
  628. uniform p3d_FogParameters p3d_Fog;
  629. """
  630. code = """
  631. assert(p3d_Fog.color == vec4(1, 2, 3, 4));
  632. assert(p3d_Fog.density == 0.5);
  633. assert(p3d_Fog.start == 6);
  634. assert(p3d_Fog.end == 10);
  635. assert(p3d_Fog.scale == 0.25);
  636. """
  637. node = core.NodePath("state")
  638. node.set_fog(fog)
  639. run_glsl_test(gsg, code, preamble, state=node.get_state())
  640. def test_glsl_frame_number(gsg):
  641. clock = core.ClockObject.get_global_clock()
  642. old_frame_count = clock.get_frame_count()
  643. try:
  644. clock.set_frame_count(123)
  645. preamble = """
  646. uniform int osg_FrameNumber;
  647. """
  648. code = """
  649. assert(osg_FrameNumber == 123);
  650. """
  651. run_glsl_test(gsg, code, preamble)
  652. finally:
  653. clock.set_frame_count(old_frame_count)
  654. def test_glsl_write_extract_image_buffer(gsg):
  655. # Tests that we can write to a buffer texture on the GPU, and then extract
  656. # the data on the CPU. We test two textures since there was in the past a
  657. # where it would only work correctly for one texture.
  658. tex1 = core.Texture("tex1")
  659. tex1.set_clear_color(0)
  660. tex1.setup_buffer_texture(1, core.Texture.T_unsigned_int, core.Texture.F_r32i,
  661. core.GeomEnums.UH_static)
  662. tex2 = core.Texture("tex2")
  663. tex2.set_clear_color(0)
  664. tex2.setup_buffer_texture(1, core.Texture.T_int, core.Texture.F_r32i,
  665. core.GeomEnums.UH_static)
  666. preamble = """
  667. layout(r32ui) uniform uimageBuffer tex1;
  668. layout(r32i) uniform iimageBuffer tex2;
  669. """
  670. code = """
  671. assert(imageLoad(tex1, 0).r == 0u);
  672. assert(imageLoad(tex2, 0).r == 0);
  673. imageStore(tex1, 0, uvec4(123));
  674. imageStore(tex2, 0, ivec4(-456));
  675. memoryBarrier();
  676. assert(imageLoad(tex1, 0).r == 123u);
  677. assert(imageLoad(tex2, 0).r == -456);
  678. """
  679. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
  680. engine = core.GraphicsEngine.get_global_ptr()
  681. assert engine.extract_texture_data(tex1, gsg)
  682. assert engine.extract_texture_data(tex2, gsg)
  683. assert struct.unpack('I', tex1.get_ram_image()) == (123,)
  684. assert struct.unpack('i', tex2.get_ram_image()) == (-456,)
  685. def test_glsl_compile_error(gsg):
  686. """Test getting compile errors from bad shaders"""
  687. suffix = ''
  688. if (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  689. suffix = '_legacy'
  690. vert_path = core.Filename(SHADERS_DIR, 'glsl_bad' + suffix + '.vert')
  691. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  692. run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=True)
  693. def test_glsl_from_file(gsg):
  694. """Test compiling GLSL shaders from files"""
  695. suffix = ''
  696. if (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  697. suffix = '_legacy'
  698. vert_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.vert')
  699. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  700. run_glsl_compile_check(gsg, vert_path, frag_path)
  701. def test_glsl_includes(gsg):
  702. """Test preprocessing includes in GLSL shaders"""
  703. suffix = ''
  704. if (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  705. suffix = '_legacy'
  706. vert_path = core.Filename(SHADERS_DIR, 'glsl_include' + suffix + '.vert')
  707. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  708. run_glsl_compile_check(gsg, vert_path, frag_path)
  709. def test_glsl_includes_angle_nodir(gsg):
  710. """Test preprocessing includes with angle includes without model-path"""
  711. suffix = ''
  712. if (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  713. suffix = '_legacy'
  714. vert_path = core.Filename(SHADERS_DIR, 'glsl_include_angle' + suffix + '.vert')
  715. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  716. assert core.Shader.load(core.Shader.SL_GLSL, vert_path, frag_path) is None
  717. @pytest.fixture
  718. def with_current_dir_on_model_path():
  719. model_path = core.get_model_path()
  720. model_path.prepend_directory(core.Filename.from_os_specific(os.path.dirname(__file__)))
  721. yield
  722. model_path.clear_local_value()
  723. def test_glsl_includes_angle_withdir(gsg, with_current_dir_on_model_path):
  724. """Test preprocessing includes with angle includes with model-path"""
  725. suffix = ''
  726. if (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  727. suffix = '_legacy'
  728. vert_path = core.Filename(SHADERS_DIR, 'glsl_include_angle' + suffix + '.vert')
  729. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  730. run_glsl_compile_check(gsg, vert_path, frag_path)