openMSX
GLSnow.cc
Go to the documentation of this file.
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 
9 using namespace gl;
10 
11 namespace openmsx {
12 
13 GLSnow::GLSnow(Display& display_)
14  : Layer(COVER_FULL, Z_BACKGROUND)
15  , display(display_)
16  , noiseTexture(true, true) // enable interpolation + wrapping
17 {
18  // Create noise texture.
19  auto& generator = global_urng(); // fast (non-cryptographic) random numbers
20  std::uniform_int_distribution<int> distribution(0, 255);
21  byte buf[128 * 128];
22  ranges::generate(buf, [&] { return distribution(generator); });
23 #if OPENGL_VERSION < OPENGL_3_3
24  glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 128, 128, 0,
25  GL_LUMINANCE, GL_UNSIGNED_BYTE, buf);
26 #else
27  // GL_LUMINANCE no longer supported in newer versions
28  glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 128, 128, 0,
29  GL_RED, GL_UNSIGNED_BYTE, buf);
30  GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE};
31  glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
32 #endif
33 
34  static constexpr vec2 pos[8][4] = {
35  {{-1, -1}, { 1, -1}, { 1, 1}, {-1, 1}},
36  {{-1, 1}, { 1, 1}, { 1, -1}, {-1, -1}},
37  {{-1, 1}, {-1, -1}, { 1, -1}, { 1, 1}},
38  {{ 1, 1}, { 1, -1}, {-1, -1}, {-1, 1}},
39  {{ 1, 1}, {-1, 1}, {-1, -1}, { 1, -1}},
40  {{ 1, -1}, {-1, -1}, {-1, 1}, { 1, 1}},
41  {{ 1, -1}, { 1, 1}, {-1, 1}, {-1, -1}},
42  {{-1, -1}, {-1, 1}, { 1, 1}, { 1, -1}},
43  };
44  glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
45  glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos, GL_STATIC_DRAW);
46  glBindBuffer(GL_ARRAY_BUFFER, 0);
47 }
48 
49 void GLSnow::paint(OutputSurface& /*output*/)
50 {
51  // Rotate and mirror noise texture in consecutive frames to avoid
52  // seeing 'patterns' in the noise.
53  static unsigned cnt = 0;
54  cnt = (cnt + 1) % 8;
55 
56  vec2 offset(random_float(0.0f, 1.0f) ,random_float(0.0f, 1.0f));
57  const vec2 tex[4] = {
58  offset + vec2(0.0f, 2.0f),
59  offset + vec2(2.0f, 2.0f),
60  offset + vec2(2.0f, 0.0f),
61  offset + vec2(0.0f, 0.0f)
62  };
63 
64  gl::context->progTex.activate();
65  glUniform4f(gl::context->unifTexColor, 1.0f, 1.0f, 1.0f, 1.0f);
66  mat4 I;
67  glUniformMatrix4fv(gl::context->unifTexMvp, 1, GL_FALSE, &I[0][0]);
68 
69  glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
70  const vec2* base = nullptr;
71  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, base + 4 * cnt);
72  glEnableVertexAttribArray(0);
73 
74  glBindBuffer(GL_ARRAY_BUFFER, vbo[1].get());
75  glBufferData(GL_ARRAY_BUFFER, sizeof(tex), tex, GL_STREAM_DRAW);
76  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
77  glEnableVertexAttribArray(1);
78 
79  noiseTexture.bind();
80  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
81  glDisableVertexAttribArray(1);
82  glDisableVertexAttribArray(0);
83  glBindBuffer(GL_ARRAY_BUFFER, 0);
84 
85  display.repaintDelayed(100 * 1000); // 10fps
86 }
87 
88 } // namespace openmsx
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:83
Represents the output window/screen of openMSX.
Definition: Display.hh:33
void repaintDelayed(uint64_t delta)
Definition: Display.cc:375
void paint(OutputSurface &output) override
Paint this layer.
Definition: GLSnow.cc:49
Interface for display layers.
Definition: Layer.hh:12
A frame buffer where pixels can be written to.
Definition: gl_mat.hh:23
vecN< 2, float > vec2
Definition: gl_vec.hh:139
std::unique_ptr< Context > context
Definition: GLContext.cc:9
This file implemented 3 utility functions:
Definition: Autofire.cc:9
void generate(ForwardRange &&range, Generator &&g)
Definition: ranges.hh:167
auto & global_urng()
Return reference to a (shared) global random number generator.
Definition: random.hh:8
float random_float(float from, float upto)
Return a random float in the range [from, upto) (note: half-open interval).
Definition: random.hh:50