Merge lp:~timfelgentreff/stratagus/shaders into lp:stratagus

Proposed by timfelgentreff on 2015-10-16
Status: Merged
Merged at revision: 9033
Proposed branch: lp:~timfelgentreff/stratagus/shaders
Merge into: lp:stratagus
Diff against target: 687 lines (+557/-4)
6 files modified
CMakeLists.txt (+10/-1)
src/include/shaders.h (+11/-0)
src/include/video.h (+1/-0)
src/stratagus/stratagus.cpp (+7/-1)
src/video/sdl.cpp (+26/-2)
src/video/shaders.cpp (+502/-0)
To merge this branch: bzr merge lp:~timfelgentreff/stratagus/shaders
Reviewer Review Type Date Requested Status
Stratagus 2015-10-16 Pending
Review via email: mp+274693@code.launchpad.net

Description of the change

Adds shaders that are used with OpenGL to scale the entire screen. For now, the 'ctrl+alt+/' (backslash) key is globally bound to cycle through available shaders so you can try it.

To post a comment you must log in.
lp:~timfelgentreff/stratagus/shaders updated on 2015-10-19
9032. By timfelgentreff on 2015-10-19

add scale2x (aka advmame2x) as scaling shader

9033. By timfelgentreff on 2015-10-19

add cmdline switches for shaders, add ctrl+alt+/ as hard cycle keybinding, remove debug prints

timfelgentreff (timfelgentreff) wrote :

Ok, I've made a few cleanups, there is now a global key-combo to cycle through shaders (ctrl+alt+/) and the shaders can also be selected from the cmdline. If anyone has time to test this, that would be great. Otherwise, I'll just merge this in a couple of days

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-04-12 09:55:12 +0000
3+++ CMakeLists.txt 2015-10-19 16:16:43 +0000
4@@ -348,6 +348,7 @@
5 src/video/movie.cpp
6 src/video/png.cpp
7 src/video/sdl.cpp
8+ src/video/shaders.cpp
9 src/video/sprite.cpp
10 src/video/video.cpp
11 )
12@@ -554,6 +555,7 @@
13 src/include/script.h
14 src/include/script_sound.h
15 src/include/settings.h
16+ src/include/shaders.h
17 src/include/sound.h
18 src/include/sound_server.h
19 src/include/spells.h
20@@ -932,7 +934,14 @@
21
22 if(ENABLE_MULTIBUILD)
23 if(WIN32 AND MSVC)
24- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
25+ if(MSVC_VERSION GREATER 1800) # if > VC13
26+ message("The project must be compiled with VS2013 or older. VS2015 has deprecated many functions that we still use.")
27+ set(CMAKE_GENERATOR_TOOLSET "v120" CACHE STRING "Platform Toolset" FORCE)
28+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:MSVCRT")
29+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:MSVCRT")
30+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:MSVCRT")
31+ endif()
32+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
33 message(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
34 endif()
35 endif()
36
37=== added file 'src/include/shaders.h'
38--- src/include/shaders.h 1970-01-01 00:00:00 +0000
39+++ src/include/shaders.h 2015-10-19 16:16:43 +0000
40@@ -0,0 +1,11 @@
41+#ifndef __SHADERS_H__
42+#define __SHADERS_H__
43+#ifdef USE_OPENGL
44+#define MAX_SHADERS 5
45+extern unsigned ShaderIndex;
46+extern void LoadShaders();
47+extern bool LoadShaderExtensions();
48+extern void SetupFramebuffer();
49+extern void RenderFramebufferToScreen();
50+#endif
51+#endif
52
53=== modified file 'src/include/video.h'
54--- src/include/video.h 2015-03-11 19:07:07 +0000
55+++ src/include/video.h 2015-10-19 16:16:43 +0000
56@@ -41,6 +41,7 @@
57
58 #ifdef USE_OPENGL
59 #include "SDL_opengl.h"
60+#include "shaders.h"
61 #endif
62
63 #include "guichan.h"
64
65=== modified file 'src/stratagus/stratagus.cpp'
66--- src/stratagus/stratagus.cpp 2015-04-12 09:54:50 +0000
67+++ src/stratagus/stratagus.cpp 2015-10-19 16:16:43 +0000
68@@ -477,6 +477,9 @@
69 "\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n"
70 "\t-W\t\tWindowed video mode\n"
71 #if defined(USE_OPENGL) || defined(USE_GLES)
72+ "\t-x\t\tControls fullscreen scaling if your graphics card supports shaders.\n"\
73+ "\t \t\tPass 1 for nearest-neigubour, 2 for EPX/AdvMame, 3 for HQx, 4 for SAL, 5 for SuperEagle\n"\
74+ "\t \t\tYou can also use Ctrl+Alt+/ to cycle between these scaling algorithms at runtime.\n"
75 "\t-Z\t\tUse OpenGL to scale the screen to the viewport (retro-style). Implies -O.\n"
76 #endif
77 "map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n",
78@@ -529,7 +532,7 @@
79 void ParseCommandLine(int argc, char **argv, Parameters &parameters)
80 {
81 for (;;) {
82- switch (getopt(argc, argv, "ac:d:D:eE:FhiI:lN:oOP:ps:S:u:v:WZ?")) {
83+ switch (getopt(argc, argv, "ac:d:D:eE:FhiI:lN:oOP:ps:S:u:v:Wx:Z?")) {
84 case 'a':
85 EnableAssert = true;
86 continue;
87@@ -629,6 +632,9 @@
88 Video.FullScreen = 0;
89 continue;
90 #if defined(USE_OPENGL) || defined(USE_GLES)
91+ case 'x':
92+ ShaderIndex = atoi(optarg) % MAX_SHADERS;
93+ continue;
94 case 'Z':
95 ForceUseOpenGL = 1;
96 UseOpenGL = 1;
97
98=== modified file 'src/video/sdl.cpp'
99--- src/video/sdl.cpp 2015-03-05 17:12:52 +0000
100+++ src/video/sdl.cpp 2015-10-19 16:16:43 +0000
101@@ -70,6 +70,7 @@
102
103 #ifdef USE_OPENGL
104 #include "SDL_opengl.h"
105+#include "shaders.h"
106 #endif
107
108 #ifdef USE_BEOS
109@@ -122,6 +123,7 @@
110 GLint GLMaxTextureSizeOverride; /// User-specified limit for ::GLMaxTextureSize
111 bool GLTextureCompressionSupported; /// Is OpenGL texture compression supported
112 bool UseGLTextureCompression; /// Use OpenGL texture compression
113+bool GLShaderPipelineSupported;
114 #endif
115
116 static std::map<int, std::string> Key2Str;
117@@ -256,8 +258,11 @@
118 } else {
119 GLTextureCompressionSupported = false;
120 }
121+
122+ GLShaderPipelineSupported = LoadShaderExtensions();
123 #else
124 GLTextureCompressionSupported = false;
125+ GLShaderPipelineSupported = false;
126 #endif
127 }
128
129@@ -281,7 +286,11 @@
130 #endif
131
132 #ifdef USE_OPENGL
133- glOrtho(0, Video.Width, Video.Height, 0, -1, 1);
134+ if (!GLShaderPipelineSupported) {
135+ glOrtho(0, Video.Width, Video.Height, 0, -1, 1);
136+ } else {
137+ glOrtho(0, Video.ViewportWidth, Video.ViewportHeight, 0, -1, 1);
138+ }
139 #endif
140
141 glMatrixMode(GL_MODELVIEW);
142@@ -299,6 +308,10 @@
143
144 #ifdef USE_OPENGL
145 glClearDepth(1.0f);
146+
147+ if (GLShaderPipelineSupported) {
148+ SetupFramebuffer();
149+ }
150 #endif
151
152 glShadeModel(GL_FLAT);
153@@ -879,6 +892,13 @@
154 break;
155
156 case SDL_KEYDOWN:
157+ if (GLShaderPipelineSupported
158+ && event.key.keysym.sym == SDLK_SLASH
159+ && event.key.keysym.mod & KMOD_ALT
160+ && event.key.keysym.mod & KMOD_CTRL) {
161+ LoadShaders();
162+ break;
163+ }
164 InputKeyButtonPress(callbacks, SDL_GetTicks(),
165 event.key.keysym.sym, event.key.keysym.unicode);
166 break;
167@@ -999,7 +1019,11 @@
168 eglSwapBuffers(eglDisplay, eglSurface);
169 #endif
170 #if defined(USE_OPENGL) || defined(USE_GLES_NATIVE)
171- SDL_GL_SwapBuffers();
172+ if (GLShaderPipelineSupported) {
173+ RenderFramebufferToScreen();
174+ } else {
175+ SDL_GL_SwapBuffers();
176+ }
177 #endif
178 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
179 } else
180
181=== added file 'src/video/shaders.cpp'
182--- src/video/shaders.cpp 1970-01-01 00:00:00 +0000
183+++ src/video/shaders.cpp 2015-10-19 16:16:43 +0000
184@@ -0,0 +1,502 @@
185+#include "stratagus.h"
186+#include "video.h"
187+#ifdef USE_OPENGL
188+const char* vertex_shader = "#version 130\n\
189+\n\
190+uniform sampler2D u_texture;\n\
191+\n\
192+void main()\n\
193+{\n\
194+ gl_TexCoord[0] = gl_MultiTexCoord0;\n\
195+ gl_Position = ftransform();\n\
196+}";
197+
198+const char* fragment_shaders[MAX_SHADERS] = {
199+ // Nearest-neighbour
200+ "#version 130\n\
201+ \n\
202+ uniform sampler2D u_texture;\n\
203+ uniform float u_width;\n\
204+ uniform float u_height;\n\
205+ uniform float u_widthrel;\n\
206+ uniform float u_heightrel;\n\
207+ void main()\n\
208+ {\n\
209+ vec4 myColor = texture2D(u_texture, gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel));\n\
210+ gl_FragColor = myColor;\n\
211+ }",
212+ // Scale2x
213+ "#version 110\n\
214+ \n\
215+ uniform sampler2D u_texture;\n\
216+ uniform float u_width;\n\
217+ uniform float u_height;\n\
218+ uniform float u_widthrel;\n\
219+ uniform float u_heightrel;\n\
220+ \n\
221+ void main() {\n\
222+ // o = offset, the width of a pixel\n\
223+ vec2 texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
224+ vec2 textureDimensions = vec2(u_width, u_height);\n\
225+ vec2 o = 1.0 / textureDimensions;\n\
226+ // texel arrangement\n\
227+ // A B C\n\
228+ // D E F\n\
229+ // G H I\n\
230+ vec4 A = texture2D(u_texture, texCoord + vec2( -o.x, o.y));\n\
231+ vec4 B = texture2D(u_texture, texCoord + vec2( 0, o.y));\n\
232+ vec4 C = texture2D(u_texture, texCoord + vec2( o.x, o.y));\n\
233+ vec4 D = texture2D(u_texture, texCoord + vec2( -o.x, 0));\n\
234+ vec4 E = texture2D(u_texture, texCoord + vec2( 0, 0));\n\
235+ vec4 F = texture2D(u_texture, texCoord + vec2( o.x, 0));\n\
236+ vec4 G = texture2D(u_texture, texCoord + vec2( -o.x, -o.y));\n\
237+ vec4 H = texture2D(u_texture, texCoord + vec2( 0, -o.y));\n\
238+ vec4 I = texture2D(u_texture, texCoord + vec2( o.x, -o.y));\n\
239+ vec2 p = texCoord * textureDimensions;\n\
240+ // p = the position within a pixel [0...1]\n\
241+ p = p - floor(p);\n\
242+ if (p.x > .5) {\n\
243+ if (p.y > .5) {\n\
244+ // Top Right\n\
245+ gl_FragColor = B == F && B != D && F != H ? F : E;\n\
246+ } else {\n\
247+ // Bottom Right\n\
248+ gl_FragColor = H == F && D != H && B != F ? F : E;\n\
249+ }\n\
250+ } else {\n\
251+ if (p.y > .5) {\n\
252+ // Top Left\n\
253+ gl_FragColor = D == B && B != F && D != H ? D : E;\n\
254+ } else {\n\
255+ // Bottom Left\n\
256+ gl_FragColor = D == H && D != B && H != F ? D : E;\n\
257+ }\n\
258+ }\n\
259+ }",
260+ // HQX
261+ "#version 130\n\
262+ \n\
263+ uniform sampler2D u_texture;\n\
264+ uniform float u_width;\n\
265+ uniform float u_height;\n\
266+ uniform float u_widthrel;\n\
267+ uniform float u_heightrel;\n\
268+ \n\
269+ const float mx = 0.325; // start smoothing wt.\n\
270+ const float k = -0.250; // wt. decrease factor\n\
271+ const float max_w = 0.25; // max filter weigth\n\
272+ const float min_w =-0.05; // min filter weigth\n\
273+ const float lum_add = 0.25; // effects smoothing \n\
274+ \n\
275+ void main()\n\
276+ {\n\
277+ vec2 v_texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
278+ \n\
279+ // hq2x\n\
280+ float x = 0.5 * (1.0 / u_width);\n\
281+ float y = 0.5 * (1.0 / u_height);\n\
282+ vec2 dg1 = vec2( x, y);\n\
283+ vec2 dg2 = vec2(-x, y);\n\
284+ vec2 dx = vec2(x, 0.0);\n\
285+ vec2 dy = vec2(0.0, y);\n\
286+ \n\
287+ vec4 TexCoord[5];\n\
288+ TexCoord[0] = vec4(v_texCoord, 0.0, 0.0);\n\
289+ TexCoord[1].xy = TexCoord[0].xy - dg1;\n\
290+ TexCoord[1].zw = TexCoord[0].xy - dy;\n\
291+ TexCoord[2].xy = TexCoord[0].xy - dg2;\n\
292+ TexCoord[2].zw = TexCoord[0].xy + dx;\n\
293+ TexCoord[3].xy = TexCoord[0].xy + dg1;\n\
294+ TexCoord[3].zw = TexCoord[0].xy + dy;\n\
295+ TexCoord[4].xy = TexCoord[0].xy + dg2;\n\
296+ TexCoord[4].zw = TexCoord[0].xy - dx;\n\
297+ \n\
298+ vec3 c00 = texture2D(u_texture, TexCoord[1].xy).xyz; \n\
299+ vec3 c10 = texture2D(u_texture, TexCoord[1].zw).xyz; \n\
300+ vec3 c20 = texture2D(u_texture, TexCoord[2].xy).xyz; \n\
301+ vec3 c01 = texture2D(u_texture, TexCoord[4].zw).xyz; \n\
302+ vec3 c11 = texture2D(u_texture, TexCoord[0].xy).xyz; \n\
303+ vec3 c21 = texture2D(u_texture, TexCoord[2].zw).xyz; \n\
304+ vec3 c02 = texture2D(u_texture, TexCoord[4].xy).xyz; \n\
305+ vec3 c12 = texture2D(u_texture, TexCoord[3].zw).xyz; \n\
306+ vec3 c22 = texture2D(u_texture, TexCoord[3].xy).xyz; \n\
307+ vec3 dt = vec3(1.0, 1.0, 1.0);\n\
308+ \n\
309+ float md1 = dot(abs(c00 - c22), dt);\n\
310+ float md2 = dot(abs(c02 - c20), dt);\n\
311+ \n\
312+ float w1 = dot(abs(c22 - c11), dt) * md2;\n\
313+ float w2 = dot(abs(c02 - c11), dt) * md1;\n\
314+ float w3 = dot(abs(c00 - c11), dt) * md2;\n\
315+ float w4 = dot(abs(c20 - c11), dt) * md1;\n\
316+ \n\
317+ float t1 = w1 + w3;\n\
318+ float t2 = w2 + w4;\n\
319+ float ww = max(t1, t2) + 0.0001;\n\
320+ \n\
321+ c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);\n\
322+ \n\
323+ float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);\n\
324+ float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);\n\
325+ \n\
326+ w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);\n\
327+ w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);\n\
328+ w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);\n\
329+ w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);\n\
330+ \n\
331+ gl_FragColor = vec4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1);\n\
332+ }",
333+ // 2xSAL
334+ "#version 130\n\
335+ \n\
336+ uniform sampler2D u_texture;\n\
337+ uniform float u_width;\n\
338+ uniform float u_height;\n\
339+ uniform float u_widthrel;\n\
340+ uniform float u_heightrel;\n\
341+ \n\
342+ void main()\n\
343+ {\n\
344+ vec2 texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
345+ vec2 UL, UR, DL, DR;\n\
346+ float dx = pow(u_width, -1.0) * 0.25;\n\
347+ float dy = pow(u_height, -1.0) * 0.25;\n\
348+ vec3 dt = vec3(1.0, 1.0, 1.0);\n\
349+ UL = texCoord + vec2(-dx, -dy);\n\
350+ UR = texCoord + vec2(dx, -dy);\n\
351+ DL = texCoord + vec2(-dx, dy);\n\
352+ DR = texCoord + vec2(dx, dy);\n\
353+ vec3 c00 = texture2D(u_texture, UL).xyz;\n\
354+ vec3 c20 = texture2D(u_texture, UR).xyz;\n\
355+ vec3 c02 = texture2D(u_texture, DL).xyz;\n\
356+ vec3 c22 = texture2D(u_texture, DR).xyz;\n\
357+ float m1=dot(abs(c00-c22),dt)+0.001;\n\
358+ float m2=dot(abs(c02-c20),dt)+0.001;\n\
359+ gl_FragColor = vec4((m1*(c02+c20)+m2*(c22+c00))/(2.0*(m1+m2)),1.0); \n\
360+ }",
361+ // SuperEagle
362+ "#version 130\n\
363+ \n\
364+ uniform sampler2D u_texture;\n\
365+ uniform float u_width;\n\
366+ uniform float u_height;\n\
367+ uniform float u_widthrel;\n\
368+ uniform float u_heightrel;\n\
369+ \n\
370+ int GET_RESULT(float A, float B, float C, float D)\n\
371+ {\n\
372+ int x = 0; int y = 0; int r = 0;\n\
373+ if (A == C) x+=1; else if (B == C) y+=1;\n\
374+ if (A == D) x+=1; else if (B == D) y+=1;\n\
375+ if (x <= 1) r+=1; \n\
376+ if (y <= 1) r-=1;\n\
377+ return r;\n\
378+ } \n\
379+ \n\
380+ const vec3 dtt = vec3(65536.0,255.0,1.0);\n\
381+ \n\
382+ float reduce(vec3 color)\n\
383+ { \n\
384+ return dot(color, dtt);\n\
385+ }\n\
386+ \n\
387+ void main()\n\
388+ {\n\
389+ // get texel size \n\
390+ vec2 ps = vec2(0.999/u_width, 0.999/u_height);\n\
391+ \n\
392+ vec2 v_texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
393+ \n\
394+ // calculating offsets, coordinates\n\
395+ vec2 dx = vec2( ps.x, 0.0); \n\
396+ vec2 dy = vec2( 0.0, ps.y);\n\
397+ vec2 g1 = vec2( ps.x,ps.y);\n\
398+ vec2 g2 = vec2(-ps.x,ps.y); \n\
399+ \n\
400+ vec2 pixcoord = v_texCoord/ps; //VAR.CT\n\
401+ vec2 fp = fract(pixcoord);\n\
402+ vec2 pC4 = v_texCoord-fp*ps;\n\
403+ vec2 pC8 = pC4+g1; //VAR.CT\n\
404+ \n\
405+ // Reading the texels\n\
406+ vec3 C0 = texture2D(u_texture,pC4-g1).xyz; \n\
407+ vec3 C1 = texture2D(u_texture,pC4-dy).xyz;\n\
408+ vec3 C2 = texture2D(u_texture,pC4-g2).xyz;\n\
409+ vec3 D3 = texture2D(u_texture,pC4-g2+dx).xyz;\n\
410+ vec3 C3 = texture2D(u_texture,pC4-dx).xyz;\n\
411+ vec3 C4 = texture2D(u_texture,pC4 ).xyz;\n\
412+ vec3 C5 = texture2D(u_texture,pC4+dx).xyz;\n\
413+ vec3 D4 = texture2D(u_texture,pC8-g2).xyz;\n\
414+ vec3 C6 = texture2D(u_texture,pC4+g2).xyz;\n\
415+ vec3 C7 = texture2D(u_texture,pC4+dy).xyz;\n\
416+ vec3 C8 = texture2D(u_texture,pC4+g1).xyz;\n\
417+ vec3 D5 = texture2D(u_texture,pC8+dx).xyz;\n\
418+ vec3 D0 = texture2D(u_texture,pC4+g2+dy).xyz;\n\
419+ vec3 D1 = texture2D(u_texture,pC8+g2).xyz;\n\
420+ vec3 D2 = texture2D(u_texture,pC8+dy).xyz;\n\
421+ vec3 D6 = texture2D(u_texture,pC8+g1).xyz;\n\
422+ \n\
423+ vec3 p00,p10,p01,p11;\n\
424+ \n\
425+ // reducing vec3 to float \n\
426+ float c0 = reduce(C0);float c1 = reduce(C1);\n\
427+ float c2 = reduce(C2);float c3 = reduce(C3);\n\
428+ float c4 = reduce(C4);float c5 = reduce(C5);\n\
429+ float c6 = reduce(C6);float c7 = reduce(C7);\n\
430+ float c8 = reduce(C8);float d0 = reduce(D0);\n\
431+ float d1 = reduce(D1);float d2 = reduce(D2);\n\
432+ float d3 = reduce(D3);float d4 = reduce(D4);\n\
433+ float d5 = reduce(D5);float d6 = reduce(D6);\n\
434+ \n\
435+ /* SuperEagle code */\n\
436+ /* Copied from the Dosbox source code */\n\
437+ /* Copyright (C) 2002-2007 The DOSBox Team */\n\
438+ /* License: GNU-GPL */\n\
439+ /* Adapted by guest(r) on 16.4.2007 */ \n\
440+ if (c4 != c8) {\n\
441+ if (c7 == c5) {\n\
442+ p01 = p10 = C7;\n\
443+ if ((c6 == c7) || (c5 == c2)) {\n\
444+ p00 = 0.25*(3.0*C7+C4);\n\
445+ } else {\n\
446+ p00 = 0.5*(C4+C5);\n\
447+ }\n\
448+ \n\
449+ if ((c5 == d4) || (c7 == d1)) {\n\
450+ p11 = 0.25*(3.0*C7+C8);\n\
451+ } else {\n\
452+ p11 = 0.5*(C7+C8);\n\
453+ }\n\
454+ } else {\n\
455+ p11 = 0.125*(6.0*C8+C7+C5);\n\
456+ p00 = 0.125*(6.0*C4+C7+C5);\n\
457+ \n\
458+ p10 = 0.125*(6.0*C7+C4+C8);\n\
459+ p01 = 0.125*(6.0*C5+C4+C8);\n\
460+ }\n\
461+ } else {\n\
462+ if (c7 != c5) {\n\
463+ p11 = p00 = C4;\n\
464+ \n\
465+ if ((c1 == c4) || (c8 == d5)) {\n\
466+ p01 = 0.25*(3.0*C4+C5);\n\
467+ } else {\n\
468+ p01 = 0.5*(C4+C5);\n\
469+ }\n\
470+ \n\
471+ if ((c8 == d2) || (c3 == c4)) {\n\
472+ p10 = 0.25*(3.0*C4+C7);\n\
473+ } else {\n\
474+ p10 = 0.5*(C7+C8);\n\
475+ }\n\
476+ } else {\n\
477+ int r = 0;\n\
478+ r += GET_RESULT(c5,c4,c6,d1);\n\
479+ r += GET_RESULT(c5,c4,c3,c1);\n\
480+ r += GET_RESULT(c5,c4,d2,d5);\n\
481+ r += GET_RESULT(c5,c4,c2,d4);\n\
482+ \n\
483+ if (r > 0) {\n\
484+ p01 = p10 = C7;\n\
485+ p00 = p11 = 0.5*(C4+C5);\n\
486+ } else if (r < 0) {\n\
487+ p11 = p00 = C4;\n\
488+ p01 = p10 = 0.5*(C4+C5);\n\
489+ } else {\n\
490+ p11 = p00 = C4;\n\
491+ p01 = p10 = C7;\n\
492+ }\n\
493+ }\n\
494+ }\n\
495+ \n\
496+ // Distributing the four products \n\
497+ if (fp.x < 0.50)\n\
498+ { if (fp.y < 0.50) p10 = p00;}\n\
499+ else\n\
500+ { if (fp.y < 0.50) p10 = p01; else p10 = p11;}\n\
501+ \n\
502+ gl_FragColor = vec4(p10, 1);\n\
503+ }"
504+};
505+
506+
507+PFNGLCREATESHADERPROC glCreateShader;
508+PFNGLSHADERSOURCEPROC glShaderSource;
509+PFNGLCOMPILESHADERPROC glCompileShader;
510+PFNGLCREATEPROGRAMPROC glCreateProgram;
511+PFNGLATTACHSHADERPROC glAttachShader;
512+PFNGLLINKPROGRAMPROC glLinkProgram;
513+PFNGLUSEPROGRAMPROC glUseProgram;
514+PFNGLISPROGRAMPROC glIsProgram;
515+PFNGLDELETEPROGRAMPROC glDeleteProgram;
516+PFNGLDELETESHADERPROC glDeleteShader;
517+PFNGLGETSHADERIVPROC glGetShaderiv;
518+PFNGLGETPROGRAMIVPROC glGetProgramiv;
519+PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
520+PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
521+PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
522+PFNGLACTIVETEXTUREPROC glActiveTexture;
523+PFNGLUNIFORM1FPROC glUniform1f;
524+PFNGLUNIFORM1IPROC glUniform1i;
525+
526+GLuint fullscreenShader;
527+GLuint fullscreenFramebuffer = 0;
528+GLuint fullscreenTexture;
529+PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffers;
530+PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer;
531+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture;
532+PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffers;
533+PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbuffer;
534+PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorage;
535+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbuffer;
536+PFNGLDRAWBUFFERSPROC glDrawBuffers;
537+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus;
538+
539+void printShaderInfoLog(GLuint obj, const char* prefix)
540+{
541+ int infologLength = 0;
542+ int charsWritten = 0;
543+ char *infoLog;
544+
545+ glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
546+
547+ if (infologLength > 0)
548+ {
549+ infoLog = (char *)malloc(infologLength);
550+ glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
551+ fprintf(stdout, "%s: %s\n", prefix, infoLog);
552+ free(infoLog);
553+ }
554+}
555+void printProgramInfoLog(GLuint obj, const char* prefix)
556+{
557+ int infologLength = 0;
558+ int charsWritten = 0;
559+ char *infoLog;
560+
561+ glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
562+
563+ if (infologLength > 0)
564+ {
565+ infoLog = (char *)malloc(infologLength);
566+ glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
567+ fprintf(stdout, "%s: %s\n", prefix, infoLog);
568+ free(infoLog);
569+ }
570+}
571+
572+extern unsigned ShaderIndex = 0;
573+
574+extern void LoadShaders() {
575+ GLuint vs, fs;
576+ fs = glCreateShader(GL_FRAGMENT_SHADER);
577+ glShaderSource(fs, 1, (const char**)&(fragment_shaders[ShaderIndex]), NULL);
578+ glCompileShader(fs);
579+ //printShaderInfoLog(fs, "Fragment Shader");
580+ ShaderIndex = (ShaderIndex + 1) % MAX_SHADERS;
581+ vs = glCreateShader(GL_VERTEX_SHADER);
582+ glShaderSource(vs, 1, (const char**)&vertex_shader, NULL);
583+ glCompileShader(vs);
584+ //printShaderInfoLog(vs, "Vertex Shader");
585+ if (glIsProgram(fullscreenShader)) {
586+ glDeleteProgram(fullscreenShader);
587+ }
588+ fullscreenShader = glCreateProgram();
589+ glAttachShader(fullscreenShader, vs);
590+ glAttachShader(fullscreenShader, fs);
591+ glLinkProgram(fullscreenShader);
592+ glDeleteShader(fs);
593+ glDeleteShader(vs);
594+ //printProgramInfoLog(fullscreenShader, "Shader Program");
595+}
596+
597+extern bool LoadShaderExtensions() {
598+ glCreateShader = (PFNGLCREATESHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glCreateShader");
599+ glShaderSource = (PFNGLSHADERSOURCEPROC)(uintptr_t)SDL_GL_GetProcAddress("glShaderSource");
600+ glCompileShader = (PFNGLCOMPILESHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glCompileShader");
601+ glCreateProgram = (PFNGLCREATEPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glCreateProgram");
602+ glAttachShader = (PFNGLATTACHSHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glAttachShader");
603+ glLinkProgram = (PFNGLLINKPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glLinkProgram");
604+ glUseProgram = (PFNGLUSEPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glUseProgram");
605+ glGetShaderiv = (PFNGLGETSHADERIVPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetShaderiv");
606+ glGetProgramiv = (PFNGLGETPROGRAMIVPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetProgramiv");
607+ glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetShaderInfoLog");
608+ glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetProgramInfoLog");
609+ glIsProgram = (PFNGLISPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glIsProgram");
610+ glDeleteProgram = (PFNGLDELETEPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glDeleteProgram");
611+ glDeleteShader = (PFNGLDELETESHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glDeleteShader");
612+
613+ glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetUniformLocation");
614+ glActiveTexture = (PFNGLACTIVETEXTUREPROC)(uintptr_t)SDL_GL_GetProcAddress("glActiveTexture");
615+ glUniform1f = (PFNGLUNIFORM1FPROC)(uintptr_t)SDL_GL_GetProcAddress("glUniform1f");
616+ glUniform1i = (PFNGLUNIFORM1IPROC)(uintptr_t)SDL_GL_GetProcAddress("glUniform1i");
617+
618+ glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glGenFramebuffers");
619+ glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glBindFramebuffer");
620+ glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glFramebufferTexture2D");
621+ glGenRenderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glGenRenderbuffers");
622+ glBindRenderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glBindRenderbuffer");
623+ glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glRenderbufferStorage");
624+ glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glFramebufferRenderbuffer");
625+ glDrawBuffers = (PFNGLDRAWBUFFERSPROC)(uintptr_t)SDL_GL_GetProcAddress("glDrawBuffers");
626+ glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glCheckFramebufferStatus");
627+
628+ if (glCreateShader && glGenFramebuffers && glGetUniformLocation && glActiveTexture) {
629+ LoadShaders();
630+ return true;
631+ } else {
632+ return false;
633+ }
634+}
635+
636+extern void SetupFramebuffer() {
637+ glGenTextures(1, &fullscreenTexture); // generate a texture to render to off-screen
638+ glBindTexture(GL_TEXTURE_2D, fullscreenTexture); // bind it, so all texture functions go to it
639+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Video.ViewportWidth, Video.ViewportHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // give an empty image to opengl
640+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // make sure we use nearest filtering
641+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
642+ glGenFramebuffers(1, &fullscreenFramebuffer); // generate a framebuffer to render to
643+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer); // bind it
644+ glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fullscreenTexture, 0); // set our texture as the "screen" of the framebuffer
645+ GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0_EXT };
646+ glDrawBuffers(1, DrawBuffers);
647+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
648+ fprintf(stderr, "FATAL: Error Creating Framebuffer! Try running without OpenGL.");
649+ exit(-1);
650+ }
651+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer);
652+}
653+
654+extern void RenderFramebufferToScreen() {
655+ // switch the rendering target back to the real display
656+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
657+ // setup our shader program
658+ glUseProgram(fullscreenShader);
659+ GLint textureloc = glGetUniformLocation(fullscreenShader, "u_texture");
660+ GLint widthloc = glGetUniformLocation(fullscreenShader, "u_width");
661+ GLint heightloc = glGetUniformLocation(fullscreenShader, "u_height");
662+ GLint widthrelloc = glGetUniformLocation(fullscreenShader, "u_widthrel");
663+ GLint heightrelloc = glGetUniformLocation(fullscreenShader, "u_heightrel");
664+ glUniform1f(widthloc, Video.ViewportWidth);
665+ glUniform1f(heightloc, Video.ViewportHeight);
666+ glUniform1f(widthrelloc, (float)Video.Width / (float)Video.ViewportWidth);
667+ glUniform1f(heightrelloc, (float)Video.Height / (float)Video.ViewportHeight);
668+ glUniform1i(textureloc, 0);
669+ glActiveTexture(GL_TEXTURE0);
670+ // render the framebuffer texture to a fullscreen quad on the real display
671+ glBindTexture(GL_TEXTURE_2D, fullscreenTexture);
672+ glBegin(GL_QUADS);
673+ glTexCoord2f(0, 0);
674+ glVertex2i(0, 0);
675+ glTexCoord2f(1, 0);
676+ glVertex2i(Video.ViewportWidth, 0);
677+ glTexCoord2f(1, 1);
678+ glVertex2i(Video.ViewportWidth, Video.ViewportHeight);
679+ glTexCoord2f(0, 1);
680+ glVertex2i(0, Video.ViewportHeight);
681+ glEnd();
682+ SDL_GL_SwapBuffers();
683+ glUseProgram(0); // Disable shaders again, and render to framebuffer again
684+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer);
685+}
686+#endif
687\ No newline at end of file

Subscribers

People subscribed via source and target branches

to status/vote changes: