Gamp v0.0.8
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
RedSquare01.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11
12#include <gamp/Gamp.hpp>
13
14#include <cstdio>
15#include <cmath>
16#include <memory>
17
18#include <jau/basic_types.hpp>
19#include <jau/fraction_type.hpp>
20#include <jau/io/file_util.hpp>
21
22#include <gamp/Gamp.hpp>
27
28using namespace jau::math;
29using namespace jau::math::util;
30
31using namespace gamp::wt;
32using namespace gamp::wt::event;
33
34// Vertex shader
35static GLint u_pmv;
36static GLint a_vertices, a_colors;
37
38// 2 <= ES < 3: #version 100
39// ES >= 3: #version 300 es
40//
41// ES2/ES3 precision:
42// precision highp float;
43// precision highp int;
44static const GLchar* vertexSource =
45 "#version 100\n"
46 "precision highp float;\n"
47 "precision highp int;\n"
48 "\n"
49 "#if __VERSION__ >= 130\n"
50 " #define attribute in\n"
51 " #define varying out\n"
52 "#endif\n"
53 "\n"
54 "uniform mat4 mgl_PMVMatrix[2];\n"
55 "attribute vec4 mgl_Vertex;\n"
56 "attribute vec4 mgl_Color;\n"
57 "varying vec4 frontColor;\n"
58 "\n"
59 "void main(void)\n"
60 "{\n"
61 " frontColor=mgl_Color;\n"
62 " gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;\n"
63 "}\n";
64
65// Fragment/pixel shader
66//
67// ES2 precision
68// precision mediump float;
69// precision mediump int;
70// ES3 precision:
71// precision highp float;
72// precision highp int;
73static const GLchar* fragmentSource =
74 "#version 100\n"
75 "precision mediump float;\n"
76 "precision mediump int;\n"
77 "\n"
78 "#if __VERSION__ >= 130\n"
79 " #define varying in\n"
80 " out vec4 mgl_FragColor;\n"
81 "#else\n"
82 " #define mgl_FragColor gl_FragColor\n"
83 "#endif\n"
84 "\n"
85 "varying vec4 frontColor;\n"
86 "\n"
87 "void main (void)\n"
88 "{\n"
89 " mgl_FragColor = frontColor;\n"
90 "}\n";
91
92static std::vector<Vec3f> vertices2 = { Vec3f(-2, 2, 0),
93 Vec3f( 2, 2, 0),
94 Vec3f(-2, -2, 0),
95 Vec3f( 2, -2, 0) };
96
97static std::vector<Vec4f> colors2 = { Vec4f( 1, 0, 0, 1),
98 Vec4f( 0, 0, 1, 1),
99 Vec4f( 1, 0, 0, 1),
100 Vec4f( 1, 0, 0, 1) };
101
102static bool animating = true;
103
105 public:
106 void keyPressed(KeyEvent& e, const KeyboardTracker& kt) override {
107 printf("KeyPressed: %s; keys %zu\n", e.toString().c_str(), kt.pressedKeyCodes().count());
108 if( e.keySym() == VKeyCode::VK_ESCAPE ) {
109 WindowSRef win = e.source().lock();
110 if( win ) {
111 win->dispose(e.when());
112 }
113 } else if( e.keySym() == VKeyCode::VK_PAUSE || e.keySym() == VKeyCode::VK_P ) {
115 } else if( e.keySym() == VKeyCode::VK_W ) {
116 WindowSRef win = e.source().lock();
117 printf("Source: %s\n", win ? win->toString().c_str() : "null");
118 }
119 }
120 void keyReleased(KeyEvent& e, const KeyboardTracker& kt) override {
121 printf("KeyRelease: %s; keys %zu\n", e.toString().c_str(), kt.pressedKeyCodes().count());
122 }
123};
124typedef std::shared_ptr<MyKeyListener> MyKeyListenerRef;
125
127 private:
128 Recti m_viewport;
129 PMVMat4f m_pmv;
130 bool m_initialized;
132
133 void updatePMv() {
134 if( !m_initialized ) {
135 return;
136 }
137 const PMVMat4f::SyncMats4& spmv = m_pmv.makeSyncPMv();
138 glUniformMatrix4fv(u_pmv, (GLsizei)spmv.matrixCount(), false, spmv.floats());
139 }
140
141 public:
143 : RenderListener(RenderListener::Private()), m_pmv(), m_initialized(false) { }
144
145 Recti& viewport() noexcept { return m_viewport; }
146 const Recti& viewport() const noexcept { return m_viewport; }
147
148 PMVMat4f& pmv() noexcept { return m_pmv; }
149 const PMVMat4f& pmv() const noexcept { return m_pmv; }
150
151 bool init(const WindowSRef&, const jau::fraction_timespec& when) override {
152 printf("RL::init: %s\n", toString().c_str());
153 m_tlast = when;
154 // Create and compile vertex shader
155 GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
156 glShaderSource(vertexShader, 1, &vertexSource, nullptr);
157 glCompileShader(vertexShader);
158
159 // Create and compile fragment shader
160 GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
161 glShaderSource(fragmentShader, 1, &fragmentSource, nullptr);
162 glCompileShader(fragmentShader);
163
164 // Link vertex and fragment shader into shader program and use it
165 GLuint shaderProgram = glCreateProgram();
166 glAttachShader(shaderProgram, vertexShader);
167 glAttachShader(shaderProgram, fragmentShader);
168 glLinkProgram(shaderProgram);
169 glUseProgram(shaderProgram);
170
171 // Get shader variables and initialize them
172
173 u_pmv = glGetUniformLocation(shaderProgram, "mgl_PMVMatrix");
174 a_vertices = glGetAttribLocation(shaderProgram, "mgl_Vertex");
175 a_colors = glGetAttribLocation(shaderProgram, "mgl_Color");
176
177 {
178 // Create vertex buffer object and copy vertex data into it
179 GLuint vbos[2];
180 glGenBuffers(2, vbos);
181
182 // Specify the layout of the shader vertex data (positions only, 3 floats)
183 glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
184 glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(vertices2.size() * Vec3f::byte_size), vertices2.data(), GL_STATIC_DRAW);
185 glEnableVertexAttribArray(a_vertices);
186 glVertexAttribPointer(a_vertices, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
187
188 // Specify the layout of the shader vertex data (positions only, 4 floats)
189 glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
190 glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(colors2.size() * Vec4f::byte_size), colors2.data(), GL_STATIC_DRAW);
191 glEnableVertexAttribArray(a_colors);
192 glVertexAttribPointer(a_colors, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
193 }
194
195 m_pmv.getP().loadIdentity();
196 m_pmv.getMv().loadIdentity();
197 m_pmv.translateMv(0, 0, -10);
198
199 glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
200 glEnable(GL_DEPTH_TEST);
201
202 m_initialized = 0 != shaderProgram;
203 return m_initialized;
204 }
205
206 void dispose(const WindowSRef&, const jau::fraction_timespec& /*when*/) override {
207 printf("RL::dispose: %s\n", toString().c_str());
208 m_initialized = false;
209 }
210
211 void display(const WindowSRef&, const jau::fraction_timespec& when) override {
212 // printf("RL::display: %s, %s\n", toString().c_str(), win->toString().c_str());
213 if( !m_initialized ) {
214 return;
215 }
216 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
217
218 m_pmv.getMv().loadIdentity();
219 m_pmv.translateMv(0, 0, -10);
220 static float t_sum_ms = 0;
221 if( animating ) {
222 t_sum_ms += float( (when - m_tlast).to_ms() );
223 }
224 const float ang = jau::adeg_to_rad(t_sum_ms * 360.0f) / 4000.0f;
225 m_pmv.rotateMv(ang, 0, 0, 1);
226 m_pmv.rotateMv(ang, 0, 1, 0);
227 updatePMv();
228
229 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
230 m_tlast = when;
231 }
232
233 void reshape(const WindowSRef&, const jau::math::Recti& viewport, const jau::fraction_timespec& /*when*/) override {
234 printf("RL::reshape: %s\n", toString().c_str());
235 m_viewport = viewport;
236
237 m_pmv.getP().loadIdentity();
238
239 const float aspect = 1.0f;
240 const float fovy_deg=45.0f;
241 const float aspect2 = ( (float) m_viewport.width() / (float) m_viewport.height() ) / aspect;
242 const float zNear=1.0f;
243 const float zFar=100.0f;
244 m_pmv.perspectiveP(jau::adeg_to_rad(fovy_deg), aspect2, zNear, zFar);
245
246 updatePMv();
247 }
248
249};
250
251int main(int argc, char *argv[]) // NOLINT(bugprone-exception-escape)
252{
253 std::string_view sfile(__FILE__);
254 std::string demo_name = std::string("gamp ").append(jau::io::fs::basename(sfile, ".cpp"));
255 std::cout << "Launching: " << demo_name << ", source " << sfile << " , exe " << argv[0] << "\n";
256
257 int win_width = 1920, win_height = 1000;
258 #if defined(__EMSCRIPTEN__)
259 win_width = 1024, win_height = 576; // 16:9
260 #endif
261 {
262 for(int i=1; i<argc; ++i) {
263 if( 0 == strcmp("-width", argv[i]) && i+1<argc) {
264 win_width = atoi(argv[i+1]);
265 ++i;
266 } else if( 0 == strcmp("-height", argv[i]) && i+1<argc) {
267 win_height = atoi(argv[i+1]);
268 ++i;
269 } else if( 0 == strcmp("-fps", argv[i]) && i+1<argc) {
270 gamp::set_gpu_forced_fps( atoi(argv[i+1]) );
271 ++i;
272 }
273 }
274 printf("-fps: %d\n", gamp::gpu_forced_fps());
275 }
276
277 if( !gamp::init_gfx_subsystem(argv[0]) ) {
278 printf("Exit (0)...");
279 return 1;
280 }
281 WindowSRef main_win = Window::create(demo_name.c_str(), win_width, win_height, gamp::render::gl::GLCapabilities(), true /* verbose */);
282 if( !main_win ) {
283 printf("Exit (1): Failed to create window.\n");
284 return 1;
285 }
287 printf("Exit (2): Failed to create context\n");
288 main_win->dispose(jau::getMonotonicTime());
289 return 1;
290 }
292 printf("GL Context: %s\n", gl.toString().c_str());
293 {
294 const int w = main_win->surfaceSize().x;
295 const int h = main_win->surfaceSize().y;
296 const float a = (float)w / (float)h;
297 printf("FB %d x %d [w x h], aspect %f [w/h]; Win %s\n", w, h, a, main_win->windowBounds().toString().c_str());
298 }
299 main_win->addKeyListener(std::make_shared<MyKeyListener>());
300 main_win->addRenderListener(std::make_shared<RedSquareES2>());
301
302 #if defined(__EMSCRIPTEN__)
303 emscripten_set_main_loop(gamp::mainloop_void, 0, 1);
304 #else
305 while( gamp::mainloop_default() ) { }
306 #endif
307 printf("Exit: %s\n", main_win->toString().c_str());
308 return 0;
309}
int main(int argc, char *argv[])
static bool animating
static GLint a_colors
static std::vector< Vec3f > vertices2
static GLint a_vertices
static const GLchar * vertexSource
std::shared_ptr< MyKeyListener > MyKeyListenerRef
static std::vector< Vec4f > colors2
static const GLchar * fragmentSource
static GLint u_pmv
void keyReleased(KeyEvent &e, const KeyboardTracker &kt) override
A key has been released, excluding auto-repeat modifier keys.
void keyPressed(KeyEvent &e, const KeyboardTracker &kt) override
A key has been pressed, excluding auto-repeat modifier keys.
Recti & viewport() noexcept
void display(const WindowSRef &, const jau::fraction_timespec &when) override
Called by the drawable to initiate rendering by the client.
PMVMat4f & pmv() noexcept
void dispose(const WindowSRef &, const jau::fraction_timespec &) override
Notifies the listener to perform the release of all renderer resources per context,...
void reshape(const WindowSRef &, const jau::math::Recti &viewport, const jau::fraction_timespec &) override
Called by the drawable during the first repaint after the component has been resized.
const PMVMat4f & pmv() const noexcept
bool init(const WindowSRef &, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
const Recti & viewport() const noexcept
bool animating() const noexcept
Specifies a set of OpenGL capabilities.
static GLContext & downcast(RenderContext *rc)
Downcast dereferenced given RenderContext* to GLContext&, throws exception if signature doesn't match...
std::string toString() const override
Specifies the OpenGL profile.
Definition GLContext.hpp:42
static constexpr std::string_view GLES2
The embedded OpenGL profile ES 2.x, with x >= 0.
Definition GLContext.hpp:65
constexpr RenderListener(Private) noexcept
Private ctor for shared_ptr<RenderListener> instance method w/o public ctor.
Definition Window.hpp:60
std::string toString() const noexcept
Definition Window.hpp:112
const gamp::render::RenderContext * renderContext() const noexcept
Definition Surface.hpp:131
constexpr const Vec2i & surfaceSize() const noexcept
Returns the surface size of the client area excluding insets (window decorations) in pixel units.
Definition Surface.hpp:177
bool createContext(const gamp::render::RenderProfile &profile, const gamp::render::RenderContextFlags &contextFlags)
Definition Surface.hpp:117
static WindowSRef create(const char *title, int wwidth, int wheight, const Capabilities &requested, bool verbose=false)
Create an new instance using a native windowing toolkit.
void addKeyListener(const KeyListenerSRef &l)
Definition Window.hpp:310
constexpr const Recti & windowBounds() const noexcept
Returns the window client-area top-left position and size excluding insets (window decorations) in wi...
Definition Window.hpp:236
void dispose(const jau::fraction_timespec &when) noexcept override
Definition Window.hpp:355
std::string toString() const noexcept
Definition gamp_wt.cpp:145
void addRenderListener(const RenderListenerSRef &l)
Definition Window.hpp:333
std::string toString() const noexcept
Definition KeyEvent.hpp:855
constexpr VKeyCode keySym() const noexcept
Returns the virtual key symbol reflecting the current keyboard layout.
Definition KeyEvent.hpp:798
Listener for multiple KeyEvent.
Definition KeyEvent.hpp:894
virtual const PressedKeyCodes & pressedKeyCodes() const noexcept=0
constexpr const WindowWeakPtr & source() const noexcept
Definition Event.hpp:85
constexpr const jau::fraction_timespec & when() const noexcept
Definition Event.hpp:84
size_type count() const noexcept
Definition bitfield.hpp:368
std::string toString() const noexcept
Definition recti.hpp:137
value_type y
Definition vec2i.hpp:64
value_type x
Definition vec2i.hpp:63
static constexpr const size_t byte_size
Definition vec3f.hpp:59
static constexpr const size_t byte_size
Definition vec4f.hpp:59
SyncMatrices4< value_type > SyncMats4
Definition pmvmat4.hpp:130
constexpr size_t matrixCount() const noexcept
Return the number of Mat4 referenced by matrices()
constexpr const value_type * floats() const noexcept
Return the underlying float data buffer.
std::string basename(std::string_view path) noexcept
Return stripped leading directory components from given path separated by /.
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
@ verbose
Verbose operations (debugging).
std::shared_ptr< Window > WindowSRef
Definition Event.hpp:36
@ VK_ESCAPE
Constant for the ESCAPE function key.
Definition KeyEvent.hpp:129
@ VK_PAUSE
Constant for the PAUSE function key.
Definition KeyEvent.hpp:115
void mainloop_void() noexcept
Calls mainloop_default(), but exits application if returning false.
bool init_gfx_subsystem(const char *exe_path)
GFX Toolkit: Initialize the subsystem once.
bool mainloop_default() noexcept
Performs the whole tasks for all created gamp::wt::Window instances.
int gpu_forced_fps() noexcept
Returns optional forced frames per seconds or -1 if unset, set via set_gpu_forced_fps().
Definition gamp_sdl2.cpp:84
void set_gpu_forced_fps(int fps) noexcept
Optional forced frames per seconds, pass to swap_gpu_buffer() by default.
Definition gamp_sdl2.cpp:86
Vector4F< float > Vec4f
Definition vec4f.hpp:360
RectI< int > Recti
Definition recti.hpp:146
Vector3F< float > Vec3f
Definition vec3f.hpp:422
PMVMatrix4< float > PMVMat4f
Definition pmvmat4.hpp:1463
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
int printf(const char *format,...)
Operating Systems predefined macros.