OXYGENHUB
◆ main openmsx / src / video / GLSnow.cc
3.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "GLSnow.hh"
2
3
#include "Display.hh"
4
#include "GLContext.hh"
5
#include "gl_mat.hh"
6
#include "gl_vec.hh"
7
8
#include "random.hh"
9
10
#include <algorithm>
11
12
using namespace gl;
13
14
namespace openmsx {
15
16
GLSnow::GLSnow(Display& display_)
17
	: Layer(Coverage::FULL, ZIndex::BACKGROUND)
18
	, display(display_)
19
	, noiseTexture(true, true) // enable interpolation + wrapping
20
{
21
	// Create noise texture.
22
	auto& generator = global_urng(); // fast (non-cryptographic) random numbers
23
	std::uniform_int_distribution distribution(0, 255);
24
	std::array<uint8_t, 128 * 128> buf;
25
	std::ranges::generate(buf, [&] { return distribution(generator); });
26
#if OPENGL_VERSION < OPENGL_3_3
27
	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 128, 128, 0,
28
	             GL_LUMINANCE, GL_UNSIGNED_BYTE, buf.data());
29
#else
30
	// GL_LUMINANCE no longer supported in newer versions
31
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 128, 128, 0,
32
	             GL_RED, GL_UNSIGNED_BYTE, buf.data());
33
	GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE};
34
	glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
35
#endif
36
37
	static constexpr std::array pos = {
38
		std::array{vec2{-1, -1}, vec2{ 1, -1}, vec2{ 1,  1}, vec2{-1,  1}},
39
		std::array{vec2{-1,  1}, vec2{ 1,  1}, vec2{ 1, -1}, vec2{-1, -1}},
40
		std::array{vec2{-1,  1}, vec2{-1, -1}, vec2{ 1, -1}, vec2{ 1,  1}},
41
		std::array{vec2{ 1,  1}, vec2{ 1, -1}, vec2{-1, -1}, vec2{-1,  1}},
42
		std::array{vec2{ 1,  1}, vec2{-1,  1}, vec2{-1, -1}, vec2{ 1, -1}},
43
		std::array{vec2{ 1, -1}, vec2{-1, -1}, vec2{-1,  1}, vec2{ 1,  1}},
44
		std::array{vec2{ 1, -1}, vec2{ 1,  1}, vec2{-1,  1}, vec2{-1, -1}},
45
		std::array{vec2{-1, -1}, vec2{-1,  1}, vec2{ 1,  1}, vec2{ 1, -1}},
46
	};
47
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
48
	glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos.data(), GL_STATIC_DRAW);
49
	glBindBuffer(GL_ARRAY_BUFFER, 0);
50
}
51
52
void GLSnow::paint(OutputSurface& /*output*/)
53
{
54
	// Rotate and mirror noise texture in consecutive frames to avoid
55
	// seeing 'patterns' in the noise.
56
	static unsigned cnt = 0;
57
	cnt = (cnt + 1) % 8;
58
59
	vec2 offset(random_float(0.0f, 1.0f), random_float(0.0f, 1.0f));
60
	const std::array tex = {
61
		offset + vec2(0.0f, 2.0f),
62
		offset + vec2(2.0f, 2.0f),
63
		offset + vec2(2.0f, 0.0f),
64
		offset + vec2(0.0f, 0.0f),
65
	};
66
67
	const auto& glContext = *gl::context;
68
	glContext.progTex.activate();
69
	glUniform4f(glContext.unifTexColor, 1.0f, 1.0f, 1.0f, 1.0f);
70
	mat4 I;
71
	glUniformMatrix4fv(glContext.unifTexMvp, 1, GL_FALSE, I.data());
72
73
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
74
	const vec2* base = nullptr;
75
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, base + 4 * cnt);
76
	glEnableVertexAttribArray(0);
77
78
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1].get());
79
	glBufferData(GL_ARRAY_BUFFER, sizeof(tex), tex.data(), GL_STREAM_DRAW);
80
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
81
	glEnableVertexAttribArray(1);
82
83
	noiseTexture.bind();
84
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
85
	glDisableVertexAttribArray(1);
86
	glDisableVertexAttribArray(0);
87
	glBindBuffer(GL_ARRAY_BUFFER, 0);
88
89
	display.repaintDelayed(100 * 1000); // 10fps
90
}
91
92
} // namespace openmsx