1 #include "stratagus.h"
2 #include "video.h"
3 #ifdef USE_OPENGL
4 const char* vertex_shader = "#version 130\n\
5 \n\
6 uniform sampler2D u_texture;\n\
7 \n\
8 void main()\n\
9 {\n\
10 gl_TexCoord[0] = gl_MultiTexCoord0;\n\
11 gl_Position = ftransform();\n\
12 }";
13
14 const char* fragment_shaders[MAX_SHADERS] = {
15 // Nearest-neighbour
16 "#version 130\n\
17 \n\
18 uniform sampler2D u_texture;\n\
19 uniform float u_width;\n\
20 uniform float u_height;\n\
21 uniform float u_widthrel;\n\
22 uniform float u_heightrel;\n\
23 void main()\n\
24 {\n\
25 vec4 myColor = texture2D(u_texture, gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel));\n\
26 gl_FragColor = myColor;\n\
27 }",
28 // Scale2x
29 "#version 110\n\
30 \n\
31 uniform sampler2D u_texture;\n\
32 uniform float u_width;\n\
33 uniform float u_height;\n\
34 uniform float u_widthrel;\n\
35 uniform float u_heightrel;\n\
36 \n\
37 void main() {\n\
38 // o = offset, the width of a pixel\n\
39 vec2 texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
40 vec2 textureDimensions = vec2(u_width, u_height);\n\
41 vec2 o = 1.0 / textureDimensions;\n\
42 // texel arrangement\n\
43 // A B C\n\
44 // D E F\n\
45 // G H I\n\
46 vec4 A = texture2D(u_texture, texCoord + vec2( -o.x, o.y));\n\
47 vec4 B = texture2D(u_texture, texCoord + vec2( 0, o.y));\n\
48 vec4 C = texture2D(u_texture, texCoord + vec2( o.x, o.y));\n\
49 vec4 D = texture2D(u_texture, texCoord + vec2( -o.x, 0));\n\
50 vec4 E = texture2D(u_texture, texCoord + vec2( 0, 0));\n\
51 vec4 F = texture2D(u_texture, texCoord + vec2( o.x, 0));\n\
52 vec4 G = texture2D(u_texture, texCoord + vec2( -o.x, -o.y));\n\
53 vec4 H = texture2D(u_texture, texCoord + vec2( 0, -o.y));\n\
54 vec4 I = texture2D(u_texture, texCoord + vec2( o.x, -o.y));\n\
55 vec2 p = texCoord * textureDimensions;\n\
56 // p = the position within a pixel [0...1]\n\
57 p = p - floor(p);\n\
58 if (p.x > .5) {\n\
59 if (p.y > .5) {\n\
60 // Top Right\n\
61 gl_FragColor = B == F && B != D && F != H ? F : E;\n\
62 } else {\n\
63 // Bottom Right\n\
64 gl_FragColor = H == F && D != H && B != F ? F : E;\n\
65 }\n\
66 } else {\n\
67 if (p.y > .5) {\n\
68 // Top Left\n\
69 gl_FragColor = D == B && B != F && D != H ? D : E;\n\
70 } else {\n\
71 // Bottom Left\n\
72 gl_FragColor = D == H && D != B && H != F ? D : E;\n\
73 }\n\
74 }\n\
75 }",
76 // HQX
77 "#version 130\n\
78 \n\
79 uniform sampler2D u_texture;\n\
80 uniform float u_width;\n\
81 uniform float u_height;\n\
82 uniform float u_widthrel;\n\
83 uniform float u_heightrel;\n\
84 \n\
85 const float mx = 0.325; // start smoothing wt.\n\
86 const float k = -0.250; // wt. decrease factor\n\
87 const float max_w = 0.25; // max filter weigth\n\
88 const float min_w =-0.05; // min filter weigth\n\
89 const float lum_add = 0.25; // effects smoothing \n\
90 \n\
91 void main()\n\
92 {\n\
93 vec2 v_texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
94 \n\
95 // hq2x\n\
96 float x = 0.5 * (1.0 / u_width);\n\
97 float y = 0.5 * (1.0 / u_height);\n\
98 vec2 dg1 = vec2( x, y);\n\
99 vec2 dg2 = vec2(-x, y);\n\
100 vec2 dx = vec2(x, 0.0);\n\
101 vec2 dy = vec2(0.0, y);\n\
102 \n\
103 vec4 TexCoord[5];\n\
104 TexCoord[0] = vec4(v_texCoord, 0.0, 0.0);\n\
105 TexCoord[1].xy = TexCoord[0].xy - dg1;\n\
106 TexCoord[1].zw = TexCoord[0].xy - dy;\n\
107 TexCoord[2].xy = TexCoord[0].xy - dg2;\n\
108 TexCoord[2].zw = TexCoord[0].xy + dx;\n\
109 TexCoord[3].xy = TexCoord[0].xy + dg1;\n\
110 TexCoord[3].zw = TexCoord[0].xy + dy;\n\
111 TexCoord[4].xy = TexCoord[0].xy + dg2;\n\
112 TexCoord[4].zw = TexCoord[0].xy - dx;\n\
113 \n\
114 vec3 c00 = texture2D(u_texture, TexCoord[1].xy).xyz; \n\
115 vec3 c10 = texture2D(u_texture, TexCoord[1].zw).xyz; \n\
116 vec3 c20 = texture2D(u_texture, TexCoord[2].xy).xyz; \n\
117 vec3 c01 = texture2D(u_texture, TexCoord[4].zw).xyz; \n\
118 vec3 c11 = texture2D(u_texture, TexCoord[0].xy).xyz; \n\
119 vec3 c21 = texture2D(u_texture, TexCoord[2].zw).xyz; \n\
120 vec3 c02 = texture2D(u_texture, TexCoord[4].xy).xyz; \n\
121 vec3 c12 = texture2D(u_texture, TexCoord[3].zw).xyz; \n\
122 vec3 c22 = texture2D(u_texture, TexCoord[3].xy).xyz; \n\
123 vec3 dt = vec3(1.0, 1.0, 1.0);\n\
124 \n\
125 float md1 = dot(abs(c00 - c22), dt);\n\
126 float md2 = dot(abs(c02 - c20), dt);\n\
127 \n\
128 float w1 = dot(abs(c22 - c11), dt) * md2;\n\
129 float w2 = dot(abs(c02 - c11), dt) * md1;\n\
130 float w3 = dot(abs(c00 - c11), dt) * md2;\n\
131 float w4 = dot(abs(c20 - c11), dt) * md1;\n\
132 \n\
133 float t1 = w1 + w3;\n\
134 float t2 = w2 + w4;\n\
135 float ww = max(t1, t2) + 0.0001;\n\
136 \n\
137 c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);\n\
138 \n\
139 float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);\n\
140 float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);\n\
141 \n\
142 w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);\n\
143 w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);\n\
144 w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);\n\
145 w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);\n\
146 \n\
147 gl_FragColor = vec4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1);\n\
148 }",
149 // 2xSAL
150 "#version 130\n\
151 \n\
152 uniform sampler2D u_texture;\n\
153 uniform float u_width;\n\
154 uniform float u_height;\n\
155 uniform float u_widthrel;\n\
156 uniform float u_heightrel;\n\
157 \n\
158 void main()\n\
159 {\n\
160 vec2 texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
161 vec2 UL, UR, DL, DR;\n\
162 float dx = pow(u_width, -1.0) * 0.25;\n\
163 float dy = pow(u_height, -1.0) * 0.25;\n\
164 vec3 dt = vec3(1.0, 1.0, 1.0);\n\
165 UL = texCoord + vec2(-dx, -dy);\n\
166 UR = texCoord + vec2(dx, -dy);\n\
167 DL = texCoord + vec2(-dx, dy);\n\
168 DR = texCoord + vec2(dx, dy);\n\
169 vec3 c00 = texture2D(u_texture, UL).xyz;\n\
170 vec3 c20 = texture2D(u_texture, UR).xyz;\n\
171 vec3 c02 = texture2D(u_texture, DL).xyz;\n\
172 vec3 c22 = texture2D(u_texture, DR).xyz;\n\
173 float m1=dot(abs(c00-c22),dt)+0.001;\n\
174 float m2=dot(abs(c02-c20),dt)+0.001;\n\
175 gl_FragColor = vec4((m1*(c02+c20)+m2*(c22+c00))/(2.0*(m1+m2)),1.0); \n\
176 }",
177 // SuperEagle
178 "#version 130\n\
179 \n\
180 uniform sampler2D u_texture;\n\
181 uniform float u_width;\n\
182 uniform float u_height;\n\
183 uniform float u_widthrel;\n\
184 uniform float u_heightrel;\n\
185 \n\
186 int GET_RESULT(float A, float B, float C, float D)\n\
187 {\n\
188 int x = 0; int y = 0; int r = 0;\n\
189 if (A == C) x+=1; else if (B == C) y+=1;\n\
190 if (A == D) x+=1; else if (B == D) y+=1;\n\
191 if (x <= 1) r+=1; \n\
192 if (y <= 1) r-=1;\n\
193 return r;\n\
194 } \n\
195 \n\
196 const vec3 dtt = vec3(65536.0,255.0,1.0);\n\
197 \n\
198 float reduce(vec3 color)\n\
199 { \n\
200 return dot(color, dtt);\n\
201 }\n\
202 \n\
203 void main()\n\
204 {\n\
205 // get texel size \n\
206 vec2 ps = vec2(0.999/u_width, 0.999/u_height);\n\
207 \n\
208 vec2 v_texCoord = gl_TexCoord[0].xy * vec2(u_widthrel, -u_heightrel);\n\
209 \n\
210 // calculating offsets, coordinates\n\
211 vec2 dx = vec2( ps.x, 0.0); \n\
212 vec2 dy = vec2( 0.0, ps.y);\n\
213 vec2 g1 = vec2( ps.x,ps.y);\n\
214 vec2 g2 = vec2(-ps.x,ps.y); \n\
215 \n\
216 vec2 pixcoord = v_texCoord/ps; //VAR.CT\n\
217 vec2 fp = fract(pixcoord);\n\
218 vec2 pC4 = v_texCoord-fp*ps;\n\
219 vec2 pC8 = pC4+g1; //VAR.CT\n\
220 \n\
221 // Reading the texels\n\
222 vec3 C0 = texture2D(u_texture,pC4-g1).xyz; \n\
223 vec3 C1 = texture2D(u_texture,pC4-dy).xyz;\n\
224 vec3 C2 = texture2D(u_texture,pC4-g2).xyz;\n\
225 vec3 D3 = texture2D(u_texture,pC4-g2+dx).xyz;\n\
226 vec3 C3 = texture2D(u_texture,pC4-dx).xyz;\n\
227 vec3 C4 = texture2D(u_texture,pC4 ).xyz;\n\
228 vec3 C5 = texture2D(u_texture,pC4+dx).xyz;\n\
229 vec3 D4 = texture2D(u_texture,pC8-g2).xyz;\n\
230 vec3 C6 = texture2D(u_texture,pC4+g2).xyz;\n\
231 vec3 C7 = texture2D(u_texture,pC4+dy).xyz;\n\
232 vec3 C8 = texture2D(u_texture,pC4+g1).xyz;\n\
233 vec3 D5 = texture2D(u_texture,pC8+dx).xyz;\n\
234 vec3 D0 = texture2D(u_texture,pC4+g2+dy).xyz;\n\
235 vec3 D1 = texture2D(u_texture,pC8+g2).xyz;\n\
236 vec3 D2 = texture2D(u_texture,pC8+dy).xyz;\n\
237 vec3 D6 = texture2D(u_texture,pC8+g1).xyz;\n\
238 \n\
239 vec3 p00,p10,p01,p11;\n\
240 \n\
241 // reducing vec3 to float \n\
242 float c0 = reduce(C0);float c1 = reduce(C1);\n\
243 float c2 = reduce(C2);float c3 = reduce(C3);\n\
244 float c4 = reduce(C4);float c5 = reduce(C5);\n\
245 float c6 = reduce(C6);float c7 = reduce(C7);\n\
246 float c8 = reduce(C8);float d0 = reduce(D0);\n\
247 float d1 = reduce(D1);float d2 = reduce(D2);\n\
248 float d3 = reduce(D3);float d4 = reduce(D4);\n\
249 float d5 = reduce(D5);float d6 = reduce(D6);\n\
250 \n\
251 /* SuperEagle code */\n\
252 /* Copied from the Dosbox source code */\n\
253 /* Copyright (C) 2002-2007 The DOSBox Team */\n\
254 /* License: GNU-GPL */\n\
255 /* Adapted by guest(r) on 16.4.2007 */ \n\
256 if (c4 != c8) {\n\
257 if (c7 == c5) {\n\
258 p01 = p10 = C7;\n\
259 if ((c6 == c7) || (c5 == c2)) {\n\
260 p00 = 0.25*(3.0*C7+C4);\n\
261 } else {\n\
262 p00 = 0.5*(C4+C5);\n\
263 }\n\
264 \n\
265 if ((c5 == d4) || (c7 == d1)) {\n\
266 p11 = 0.25*(3.0*C7+C8);\n\
267 } else {\n\
268 p11 = 0.5*(C7+C8);\n\
269 }\n\
270 } else {\n\
271 p11 = 0.125*(6.0*C8+C7+C5);\n\
272 p00 = 0.125*(6.0*C4+C7+C5);\n\
273 \n\
274 p10 = 0.125*(6.0*C7+C4+C8);\n\
275 p01 = 0.125*(6.0*C5+C4+C8);\n\
276 }\n\
277 } else {\n\
278 if (c7 != c5) {\n\
279 p11 = p00 = C4;\n\
280 \n\
281 if ((c1 == c4) || (c8 == d5)) {\n\
282 p01 = 0.25*(3.0*C4+C5);\n\
283 } else {\n\
284 p01 = 0.5*(C4+C5);\n\
285 }\n\
286 \n\
287 if ((c8 == d2) || (c3 == c4)) {\n\
288 p10 = 0.25*(3.0*C4+C7);\n\
289 } else {\n\
290 p10 = 0.5*(C7+C8);\n\
291 }\n\
292 } else {\n\
293 int r = 0;\n\
294 r += GET_RESULT(c5,c4,c6,d1);\n\
295 r += GET_RESULT(c5,c4,c3,c1);\n\
296 r += GET_RESULT(c5,c4,d2,d5);\n\
297 r += GET_RESULT(c5,c4,c2,d4);\n\
298 \n\
299 if (r > 0) {\n\
300 p01 = p10 = C7;\n\
301 p00 = p11 = 0.5*(C4+C5);\n\
302 } else if (r < 0) {\n\
303 p11 = p00 = C4;\n\
304 p01 = p10 = 0.5*(C4+C5);\n\
305 } else {\n\
306 p11 = p00 = C4;\n\
307 p01 = p10 = C7;\n\
308 }\n\
309 }\n\
310 }\n\
311 \n\
312 // Distributing the four products \n\
313 if (fp.x < 0.50)\n\
314 { if (fp.y < 0.50) p10 = p00;}\n\
315 else\n\
316 { if (fp.y < 0.50) p10 = p01; else p10 = p11;}\n\
317 \n\
318 gl_FragColor = vec4(p10, 1);\n\
319 }"
320 };
321
322 #ifndef __APPLE__
323 PFNGLCREATESHADERPROC glCreateShader;
324 PFNGLSHADERSOURCEPROC glShaderSource;
325 PFNGLCOMPILESHADERPROC glCompileShader;
326 PFNGLCREATEPROGRAMPROC glCreateProgram;
327 PFNGLATTACHSHADERPROC glAttachShader;
328 PFNGLLINKPROGRAMPROC glLinkProgram;
329 PFNGLUSEPROGRAMPROC glUseProgram;
330 PFNGLISPROGRAMPROC glIsProgram;
331 PFNGLDELETEPROGRAMPROC glDeleteProgram;
332 PFNGLDELETESHADERPROC glDeleteShader;
333 PFNGLGETSHADERIVPROC glGetShaderiv;
334 PFNGLGETPROGRAMIVPROC glGetProgramiv;
335 PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
336 PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
337 PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
338 PFNGLACTIVETEXTUREPROC glActiveTextureProc;
339 PFNGLUNIFORM1FPROC glUniform1f;
340 PFNGLUNIFORM1IPROC glUniform1i;
341 PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffers;
342 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer;
343 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture;
344 PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffers;
345 PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbuffer;
346 PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorage;
347 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbuffer;
348 PFNGLDRAWBUFFERSPROC glDrawBuffers;
349 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus;
350 #else
351 #define glGenFramebuffers glGenFramebuffersEXT
352 #define glBindFramebuffer glBindFramebufferEXT
353 #define glCheckFramebufferStatus glCheckFramebufferStatusEXT
354 #define glActiveTextureProc glActiveTexture
355 #define glFramebufferTexture glFramebufferTexture2DEXT
356 #endif
357
358 GLuint fullscreenShader;
359 GLuint fullscreenFramebuffer = 0;
360 GLuint fullscreenTexture;
361
printShaderInfoLog(GLuint obj,const char * prefix)362 void printShaderInfoLog(GLuint obj, const char* prefix)
363 {
364 int infologLength = 0;
365 int charsWritten = 0;
366 char *infoLog;
367
368 glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
369
370 if (infologLength > 0)
371 {
372 infoLog = (char *)malloc(infologLength);
373 glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
374 fprintf(stdout, "%s: %s\n", prefix, infoLog);
375 free(infoLog);
376 }
377 }
printProgramInfoLog(GLuint obj,const char * prefix)378 void printProgramInfoLog(GLuint obj, const char* prefix)
379 {
380 int infologLength = 0;
381 int charsWritten = 0;
382 char *infoLog;
383
384 glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
385
386 if (infologLength > 0)
387 {
388 infoLog = (char *)malloc(infologLength);
389 glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
390 fprintf(stdout, "%s: %s\n", prefix, infoLog);
391 free(infoLog);
392 }
393 }
394
395 //Wyrmgus start
396 //unsigned ShaderIndex = 0;
397 unsigned ShaderIndex = -1 % MAX_SHADERS;
398 //Wyrmgus end
399
LoadShaders()400 extern bool LoadShaders() {
401 GLuint vs, fs;
402 GLint params;
403 fs = glCreateShader(GL_FRAGMENT_SHADER);
404 if (fs == 0) {
405 return false;
406 }
407 glShaderSource(fs, 1, (const char**)&(fragment_shaders[ShaderIndex]), nullptr);
408 glCompileShader(fs);
409 glGetShaderiv(fs, GL_COMPILE_STATUS, ¶ms);
410 if (params == GL_FALSE) {
411 glDeleteShader(fs);
412 return false;
413 }
414 //printShaderInfoLog(fs, "Fragment Shader");
415 ShaderIndex = (ShaderIndex + 1) % MAX_SHADERS;
416 vs = glCreateShader(GL_VERTEX_SHADER);
417 if (fs == 0) {
418 glDeleteShader(fs);
419 return false;
420 }
421 glShaderSource(vs, 1, (const char**)&vertex_shader, nullptr);
422 glCompileShader(vs);
423 glGetShaderiv(fs, GL_COMPILE_STATUS, ¶ms);
424 if (params == GL_FALSE) {
425 glDeleteShader(fs);
426 glDeleteShader(vs);
427 return false;
428 }
429 //printShaderInfoLog(vs, "Vertex Shader");
430 if (glIsProgram(fullscreenShader)) {
431 glDeleteProgram(fullscreenShader);
432 }
433 fullscreenShader = glCreateProgram();
434 if (fullscreenShader == 0) {
435 glDeleteShader(fs);
436 glDeleteShader(vs);
437 return false;
438 }
439 glAttachShader(fullscreenShader, vs);
440 glAttachShader(fullscreenShader, fs);
441 glLinkProgram(fullscreenShader);
442 glGetProgramiv(fullscreenShader, GL_LINK_STATUS, ¶ms);
443 if (params == GL_FALSE) {
444 glDeleteShader(fs);
445 glDeleteShader(vs);
446 glDeleteProgram(fullscreenShader);
447 return false;
448 }
449 glDeleteShader(fs);
450 glDeleteShader(vs);
451 //printProgramInfoLog(fullscreenShader, "Shader Program");
452 return true;
453 }
454
LoadShaderExtensions()455 extern bool LoadShaderExtensions() {
456 #ifndef __APPLE__
457 glCreateShader = (PFNGLCREATESHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glCreateShader");
458 glShaderSource = (PFNGLSHADERSOURCEPROC)(uintptr_t)SDL_GL_GetProcAddress("glShaderSource");
459 glCompileShader = (PFNGLCOMPILESHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glCompileShader");
460 glCreateProgram = (PFNGLCREATEPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glCreateProgram");
461 glAttachShader = (PFNGLATTACHSHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glAttachShader");
462 glLinkProgram = (PFNGLLINKPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glLinkProgram");
463 glUseProgram = (PFNGLUSEPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glUseProgram");
464 glGetShaderiv = (PFNGLGETSHADERIVPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetShaderiv");
465 glGetProgramiv = (PFNGLGETPROGRAMIVPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetProgramiv");
466 glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetShaderInfoLog");
467 glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetProgramInfoLog");
468 glIsProgram = (PFNGLISPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glIsProgram");
469 glDeleteProgram = (PFNGLDELETEPROGRAMPROC)(uintptr_t)SDL_GL_GetProcAddress("glDeleteProgram");
470 glDeleteShader = (PFNGLDELETESHADERPROC)(uintptr_t)SDL_GL_GetProcAddress("glDeleteShader");
471
472 glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)(uintptr_t)SDL_GL_GetProcAddress("glGetUniformLocation");
473 glActiveTextureProc = (PFNGLACTIVETEXTUREPROC)(uintptr_t)SDL_GL_GetProcAddress("glActiveTexture");
474 glUniform1f = (PFNGLUNIFORM1FPROC)(uintptr_t)SDL_GL_GetProcAddress("glUniform1f");
475 glUniform1i = (PFNGLUNIFORM1IPROC)(uintptr_t)SDL_GL_GetProcAddress("glUniform1i");
476
477 glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glGenFramebuffers");
478 glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glBindFramebuffer");
479 glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glFramebufferTexture2D");
480 glGenRenderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glGenRenderbuffers");
481 glBindRenderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glBindRenderbuffer");
482 glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glRenderbufferStorage");
483 glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glFramebufferRenderbuffer");
484 glDrawBuffers = (PFNGLDRAWBUFFERSPROC)(uintptr_t)SDL_GL_GetProcAddress("glDrawBuffers");
485 glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glCheckFramebufferStatus");
486 #endif
487 if (glCreateShader && glGenFramebuffers && glGetUniformLocation && glActiveTextureProc) {
488 return LoadShaders();
489 } else {
490 return false;
491 }
492 }
493
SetupFramebuffer()494 extern void SetupFramebuffer() {
495 glGenTextures(1, &fullscreenTexture); // generate a texture to render to off-screen
496 glBindTexture(GL_TEXTURE_2D, fullscreenTexture); // bind it, so all texture functions go to it
497 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Video.ViewportWidth, Video.ViewportHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // give an empty image to opengl
498 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // make sure we use nearest filtering
499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
500 glGenFramebuffers(1, &fullscreenFramebuffer); // generate a framebuffer to render to
501 glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer); // bind it
502 glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fullscreenTexture, 0); // set our texture as the "screen" of the framebuffer
503 GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0_EXT };
504 glDrawBuffers(1, DrawBuffers);
505 if (glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
506 fprintf(stderr, "FATAL: Error Creating Framebuffer! Try running without OpenGL.");
507 exit(-1);
508 }
509 glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer);
510 }
511
RenderFramebufferToScreen()512 extern void RenderFramebufferToScreen() {
513 // switch the rendering target back to the real display
514 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
515 // setup our shader program
516 glUseProgram(fullscreenShader);
517 GLint textureloc = glGetUniformLocation(fullscreenShader, "u_texture");
518 GLint widthloc = glGetUniformLocation(fullscreenShader, "u_width");
519 GLint heightloc = glGetUniformLocation(fullscreenShader, "u_height");
520 GLint widthrelloc = glGetUniformLocation(fullscreenShader, "u_widthrel");
521 GLint heightrelloc = glGetUniformLocation(fullscreenShader, "u_heightrel");
522 glUniform1f(widthloc, Video.ViewportWidth);
523 glUniform1f(heightloc, Video.ViewportHeight);
524 glUniform1f(widthrelloc, (float)Video.Width / (float)Video.ViewportWidth);
525 glUniform1f(heightrelloc, (float)Video.Height / (float)Video.ViewportHeight);
526 glUniform1i(textureloc, 0);
527 glActiveTextureProc(GL_TEXTURE0);
528 // render the framebuffer texture to a fullscreen quad on the real display
529 glBindTexture(GL_TEXTURE_2D, fullscreenTexture);
530 glBegin(GL_QUADS);
531 glTexCoord2f(0, 0);
532 glVertex2i(0, 0);
533 glTexCoord2f(1, 0);
534 glVertex2i(Video.ViewportWidth, 0);
535 glTexCoord2f(1, 1);
536 glVertex2i(Video.ViewportWidth, Video.ViewportHeight);
537 glTexCoord2f(0, 1);
538 glVertex2i(0, Video.ViewportHeight);
539 glEnd();
540 SDL_GL_SwapBuffers();
541 glUseProgram(0); // Disable shaders again, and render to framebuffer again
542 glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer);
543 }
544 #endif
545