GLSnow.cc 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include "GLSnow.hh"
  2. #include "GLContext.hh"
  3. #include "gl_mat.hh"
  4. #include "Display.hh"
  5. #include "gl_vec.hh"
  6. #include "openmsx.hh"
  7. #include "random.hh"
  8. using namespace gl;
  9. namespace openmsx {
  10. GLSnow::GLSnow(Display& display_)
  11. : Layer(COVER_FULL, Z_BACKGROUND)
  12. , display(display_)
  13. , noiseTexture(true, true) // enable interpolation + wrapping
  14. {
  15. // Create noise texture.
  16. auto& generator = global_urng(); // fast (non-cryptographic) random numbers
  17. std::uniform_int_distribution<int> distribution(0, 255);
  18. byte buf[128 * 128];
  19. for (auto& b : buf) {
  20. b = distribution(generator);
  21. }
  22. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 128, 128, 0,
  23. GL_RED, GL_UNSIGNED_BYTE, buf);
  24. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
  25. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
  26. const vec2 pos[8][4] = {
  27. { { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } },
  28. { { -1, 1 }, { 1, 1 }, { 1, -1 }, { -1, -1 } },
  29. { { -1, 1 }, { -1, -1 }, { 1, -1 }, { 1, 1 } },
  30. { { 1, 1 }, { 1, -1 }, { -1, -1 }, { -1, 1 } },
  31. { { 1, 1 }, { -1, 1 }, { -1, -1 }, { 1, -1 } },
  32. { { 1, -1 }, { -1, -1 }, { -1, 1 }, { 1, 1 } },
  33. { { 1, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 } },
  34. { { -1, -1 }, { -1, 1 }, { 1, 1 }, { 1, -1 } }
  35. };
  36. glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
  37. glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos, GL_STATIC_DRAW);
  38. }
  39. void GLSnow::paint(OutputSurface& /*output*/)
  40. {
  41. // Rotate and mirror noise texture in consecutive frames to avoid
  42. // seeing 'patterns' in the noise.
  43. static unsigned cnt = 0;
  44. cnt = (cnt + 1) % 8;
  45. vec2 offset(random_float(0.0f, 1.0f) ,random_float(0.0f, 1.0f));
  46. const vec2 tex[4] = {
  47. offset + vec2(0.0f, 2.0f),
  48. offset + vec2(2.0f, 2.0f),
  49. offset + vec2(2.0f, 0.0f),
  50. offset + vec2(0.0f, 0.0f)
  51. };
  52. gl::context->progTex.activate();
  53. glUniform4f(gl::context->unifTexColor, 1.0f, 1.0f, 1.0f, 1.0f);
  54. mat4 I;
  55. glUniformMatrix4fv(gl::context->unifTexMvp, 1, GL_FALSE, &I[0][0]);
  56. vao.bind();
  57. glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
  58. vec2* base = nullptr;
  59. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, base + cnt * 4);
  60. glEnableVertexAttribArray(0);
  61. glBindBuffer(GL_ARRAY_BUFFER, vbo[1].get());
  62. glBufferData(GL_ARRAY_BUFFER, sizeof(tex), tex, GL_STATIC_DRAW);
  63. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
  64. glEnableVertexAttribArray(1);
  65. noiseTexture.bind();
  66. glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  67. vao.unbind();
  68. display.repaintDelayed(100 * 1000); // 10fps
  69. }
  70. } // namespace openmsx