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