Skip to content

Commit 023533f

Browse files
committed
Added Shader Example & PGEX - VERY EXPERIMENTAL
1 parent d55cb8a commit 023533f

3 files changed

Lines changed: 1194 additions & 5 deletions

File tree

examples/TEST_Shaders.cpp

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/*
2+
Example file for olcPGEX_Shaders.h
3+
4+
License (OLC-3)
5+
~~~~~~~~~~~~~~~
6+
7+
Copyright 2018 - 2025 OneLoneCoder.com
8+
9+
Redistribution and use in source and binary forms, with or without
10+
modification, are permitted provided that the following conditions
11+
are met:
12+
13+
1. Redistributions or derivations of source code must retain the above
14+
copyright notice, this list of conditions and the following disclaimer.
15+
16+
2. Redistributions or derivative works in binary form must reproduce
17+
the above copyright notice. This list of conditions and the following
18+
disclaimer must be reproduced in the documentation and/or other
19+
materials provided with the distribution.
20+
21+
3. Neither the name of the copyright holder nor the names of its
22+
contributors may be used to endorse or promote products derived
23+
from this software without specific prior written permission.
24+
25+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36+
37+
Links
38+
~~~~~
39+
YouTube: https://www.youtube.com/javidx9
40+
Discord: https://discord.gg/WhwHUMV
41+
Twitter: https://www.twitter.com/javidx9
42+
Twitch: https://www.twitch.tv/javidx9
43+
GitHub: https://www.github.com/onelonecoder
44+
Homepage: https://www.onelonecoder.com
45+
46+
Author
47+
~~~~~~
48+
David Barr, aka javidx9
49+
©OneLoneCoder 2019, 2020, 2021, 2022, 2022, 2023, 2024, 2025
50+
51+
*/
52+
53+
#define OLC_PGE_APPLICATION
54+
#define OLC_GFX_OPENGL33
55+
#include "olcPixelGameEngine.h"
56+
57+
#define OLC_PGEX_SHADERS
58+
#include "extensions/olcPGEX_Shaders.h"
59+
60+
#define OLC_PGEX_TRANSFORMEDVIEW
61+
#include "extensions/olcPGEX_TransformedView.h"
62+
63+
class Example : public olc::PixelGameEngine
64+
{
65+
public:
66+
Example()
67+
{
68+
// Name your application
69+
sAppName = "Example";
70+
}
71+
72+
/*
73+
74+
PLEASE NOTE! This is all an ill-thought through idea. I do not recommend you actually use this.
75+
76+
*/
77+
78+
// You need an instance of a shader object to apply pixel shading
79+
olc::Shade shader;
80+
81+
// Effects are the pixel shaders. They can be custom, or selected from a built in library
82+
olc::Effect fxScanlines;
83+
olc::Effect fxNormal;
84+
olc::Effect fxBoxblur;
85+
olc::Effect fxGreyscale;
86+
olc::Effect fxThreshold;
87+
olc::Effect fxSobel;
88+
89+
// Pixel shading is all done in Decal land, so for this demo we render to several decals with
90+
// different shading, and composite the result
91+
olc::Renderable gfxNormalBouncers;
92+
olc::Renderable gfxShadedBouncers;
93+
olc::Renderable gfxTexture1;
94+
olc::Renderable gfxTexture2;
95+
96+
olc::Renderable gfxEffect1;
97+
olc::Renderable gfxEffect2;
98+
olc::Renderable gfxEffect3;
99+
olc::Renderable gfxEffect4;
100+
olc::Renderable gfxEffect5;
101+
102+
103+
size_t nBouncers = 50;
104+
std::vector<std::pair<olc::vf2d, olc::vf2d>> vBouncers;
105+
106+
olc::TransformedView tv;
107+
108+
109+
public:
110+
bool OnUserCreate() override
111+
{
112+
// Transformed view is for panning and zooming
113+
tv.Initialise({ ScreenWidth(), ScreenHeight() }, { 1.0f, 1.0f });
114+
115+
// These are decals, but created manually rather than from a file
116+
gfxNormalBouncers.Create(ScreenWidth(), ScreenHeight());
117+
gfxShadedBouncers.Create(ScreenWidth(), ScreenHeight());
118+
gfxEffect1.Create(200, 200);
119+
gfxEffect2.Create(200, 200);
120+
gfxEffect3.Create(200, 200);
121+
gfxEffect4.Create(200, 200);
122+
gfxEffect5.Create(200, 200);
123+
124+
// This decal uses a graphic - you'll need your own
125+
gfxTexture2.Load("E:\\work\\repos\\OneLoneCoder\\olcProjects2\\DEMO_Quad3D\\assets\\Baby.png");
126+
127+
// All of these effects "pixel shaders" are built-in. You can easily define your own EffectConfig
128+
fxScanlines = shader.MakeEffect(olc::fx::FX_SCANLINE);
129+
fxNormal = shader.MakeEffect(olc::fx::FX_NORMAL);
130+
fxBoxblur = shader.MakeEffect(olc::fx::FX_BOXBLUR);
131+
fxGreyscale = shader.MakeEffect(olc::fx::FX_GREYSCALE);
132+
fxThreshold = shader.MakeEffect(olc::fx::FX_THRESHOLD);
133+
fxSobel = shader.MakeEffect(olc::fx::FX_SOBEL);
134+
135+
136+
137+
138+
139+
vBouncers.resize(nBouncers);
140+
for (size_t i = 0; i < nBouncers; i++)
141+
{
142+
float a = (float(rand()) / float(RAND_MAX)) * 2.0f * 3.14159f;
143+
144+
vBouncers[i] =
145+
std::make_pair<olc::vf2d, olc::vf2d>(
146+
{ float(rand() % (ScreenWidth() - gfxTexture2.Sprite()->width)) + 100, float(rand() % (ScreenHeight() - gfxTexture2.Sprite()->height)) + 100 },
147+
{ cos(a), sin(a) });
148+
}
149+
150+
return true;
151+
}
152+
153+
bool OnUserUpdate(float fElapsedTime) override
154+
{
155+
// Handle Pan & Zoom
156+
if (GetMouse(2).bPressed) tv.StartPan(GetMousePos());
157+
if (GetMouse(2).bHeld) tv.UpdatePan(GetMousePos());
158+
if (GetMouse(2).bReleased) tv.EndPan(GetMousePos());
159+
if (GetMouseWheel() > 0) tv.ZoomAtScreenPos(2.0f, GetMousePos());
160+
if (GetMouseWheel() < 0) tv.ZoomAtScreenPos(0.5f, GetMousePos());
161+
162+
163+
// Stage 1) Just draw the bouncers normally into the NormalBouncers decal
164+
// This uses the "pass-thru" effect, i.e. nothing
165+
166+
// Set the target decal
167+
shader.SetTargetDecal(gfxNormalBouncers.Decal(), 0);
168+
// Tell the shading system to use a shader
169+
shader.Start(&fxNormal);
170+
// Several PGE-like drawing commands are available. Here we clear the decal
171+
shader.Clear();
172+
173+
// Update Locations & Render "Stock" Bouncers
174+
for (auto& bouncer : vBouncers)
175+
{
176+
bouncer.first += bouncer.second * fElapsedTime * 100.0f;
177+
178+
if (bouncer.first.x < 0.0f)
179+
{
180+
bouncer.first.x = 0.0f; bouncer.second.x *= -1.0f;
181+
}
182+
if (bouncer.first.x + gfxTexture2.Sprite()->width > ScreenWidth())
183+
{
184+
bouncer.first.x = float(ScreenWidth() - gfxTexture2.Sprite()->width); bouncer.second.x *= -1.0f;
185+
}
186+
187+
if (bouncer.first.y < 0.0f)
188+
{
189+
bouncer.first.y = 0.0f; bouncer.second.y *= -1.0f;
190+
}
191+
if (bouncer.first.y + gfxTexture2.Sprite()->height > ScreenHeight())
192+
{
193+
bouncer.first.y = float(ScreenHeight() - gfxTexture2.Sprite()->height); bouncer.second.y *= -1.0f;
194+
}
195+
196+
// Using the transformed view, draw the bouncer using the pass-thru shader
197+
tv.DrawDecal(shader, bouncer.first, gfxTexture2.Decal(), { 1.0f, 1.0f }, olc::WHITE);
198+
}
199+
200+
// Stop shading
201+
shader.End();
202+
203+
// Stage 2) A selection of different effects are demonstrated. For each one, we "cut" out of normal bouncers
204+
// a small region, then draw it into its own decal just for that effect. The cut is done with DrawPartialDecal()
205+
206+
shader.SetTargetDecal(gfxEffect1.Decal(), 0);
207+
shader.Start(&fxBoxblur);
208+
shader.Clear(olc::WHITE);
209+
shader.DrawPartialDecal({ 0.0f, 0.0f }, gfxNormalBouncers.Decal(), { 50.0f, 50.0f }, { 200.0f, 200.0f });
210+
shader.End();
211+
212+
shader.SetTargetDecal(gfxEffect2.Decal(), 0);
213+
shader.Start(&fxScanlines);
214+
shader.Clear(olc::WHITE);
215+
shader.DrawPartialDecal({ 0.0f, 0.0f }, gfxNormalBouncers.Decal(), { 300.0f, 50.0f }, { 200.0f, 200.0f });
216+
shader.End();
217+
218+
shader.SetTargetDecal(gfxEffect3.Decal(), 0);
219+
shader.Start(&fxGreyscale);
220+
shader.Clear(olc::WHITE);
221+
shader.DrawPartialDecal({ 0.0f, 0.0f }, gfxNormalBouncers.Decal(), { 550.0f, 50.0f }, { 200.0f, 200.0f });
222+
shader.End();
223+
224+
shader.SetTargetDecal(gfxEffect4.Decal(), 0);
225+
shader.Start(&fxThreshold);
226+
shader.Clear(olc::WHITE);
227+
shader.DrawPartialDecal({ 0.0f, 0.0f }, gfxNormalBouncers.Decal(), { 800.0f, 50.0f }, { 200.0f, 200.0f });
228+
shader.End();
229+
230+
shader.SetTargetDecal(gfxEffect5.Decal(), 0);
231+
shader.Start(&fxSobel);
232+
shader.Clear(olc::WHITE);
233+
shader.DrawPartialDecal({ 0.0f, 0.0f }, gfxNormalBouncers.Decal(), { 1050.0f, 50.0f }, { 200.0f, 200.0f });
234+
shader.End();
235+
236+
// Stage 3) Composite final display - NOT USING SHADERS NOW
237+
238+
Clear(olc::WHITE);
239+
DrawDecal({ 0,0 }, gfxNormalBouncers.Decal());
240+
241+
FillRectDecal({ 48.0f, 48.0f }, { 204.0f, 204.0f }, olc::BLUE);
242+
DrawDecal({ 50.0f, 50.0f }, gfxEffect1.Decal());
243+
244+
FillRectDecal({ 298.0f, 48.0f }, { 204.0f, 204.0f }, olc::BLUE);
245+
DrawDecal({ 300.0f, 50.0f }, gfxEffect2.Decal());
246+
247+
FillRectDecal({ 548.0f, 48.0f }, { 204.0f, 204.0f }, olc::BLUE);
248+
DrawDecal({ 550.0f, 50.0f }, gfxEffect3.Decal());
249+
250+
FillRectDecal({ 798.0f, 48.0f }, { 204.0f, 204.0f }, olc::BLUE);
251+
DrawDecal({ 800.0f, 50.0f }, gfxEffect4.Decal());
252+
253+
FillRectDecal({ 1048.0f, 48.0f }, { 204.0f, 204.0f }, olc::BLUE);
254+
DrawDecal({ 1050.0f, 50.0f }, gfxEffect5.Decal());
255+
256+
257+
return true;
258+
}
259+
};
260+
261+
int main()
262+
{
263+
Example demo;
264+
if (demo.Construct(1280, 720, 1, 1, false, false))
265+
demo.Start();
266+
return 0;
267+
}

0 commit comments

Comments
 (0)