Last active
August 12, 2020 19:11
-
-
Save AliceLR/491bfd3002206a25974f8d5f92502ab9 to your computer and use it in GitHub Desktop.
The one that's actually getting merged is here: https://github.com/AliceLR/megazeux/pull/254
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
./megazeux.exe C:/a/MegaZeux/_testcases/mzxtests/graphics video_output=glsl gl_scaling_shader=nearest window_resolution=1280,700 | |
2.92e (draw 4 vertices + texcoord): | |
* speed 1: 4760 | |
* speed 1 smzx: 4345 | |
* logicow.mzx: 260 | |
* abuse0.mzx: 121 | |
initialize char vertices in C but don't send: | |
* speed 1: 4770 | |
* speed 1 smzx: 4370 | |
* logicow.mzx: 258 | |
draw char vertices: | |
* speed 1: 3780 | |
* speed 1 smzx: 3780 | |
* logicow.mzx: 112 | |
draw char vertices + calculate vTexcoord in vertex shader using uniforms: | |
* speed 1: 3900 | |
* speed 1 smzx: 3900 | |
* logicow.mzx: 180 | |
draw vertices + throw texcoord in the dumpster altogether: | |
* speed 1: 4070 | |
* speed 1 smzx: 4100 | |
* logicow.mzx: 180 | |
* abuse0.mzx: 93 | |
above + unpack in vertex shader using flat outs: negligible difference (GL 3.0, GLES 2) | |
draw 4 vertices + get rid of texcoord: | |
* speed 1: 4790 | |
* speed 1 smzx: 4360 | |
* logicow.mzx: 256.67 | |
* abuse0.mzx: 119.67 | |
draw 4 vertices + send layer data in a UBO (GL 3.1, GLES 3): | |
* speed 1: 2700 | |
* speed 1 smzx: 2740 (NOTE: not actually using the UBO data currently) | |
* logicow.mzx: 50 | |
* abuse0.mzx: 21.67 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/assets/glsl/tilemap.31.frag b/assets/glsl/tilemap.31.frag | |
new file mode 100644 | |
index 00000000..41cc5d3b | |
--- /dev/null | |
+++ b/assets/glsl/tilemap.31.frag | |
@@ -0,0 +1,148 @@ | |
+/* MegaZeux | |
+ * | |
+ * Copyright (C) 2008 Joel Bouchard Lamontagne <logicow@gmail.com> | |
+ * Copyright (C) 2009 Alistair John Strachan <alistair@devzero.co.uk> | |
+ * Copyright (C) 2017 Dr Lancer-X <drlancer@megazeux.org> | |
+ * Copyright (C) 2020 Alice Rowan <petrifiedrowan@gmail.com> | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License as | |
+ * published by the Free Software Foundation; either version 2 of | |
+ * the License, or (at your option) any later version. | |
+ * | |
+ * This program is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License | |
+ * along with this program; if not, write to the Free Software | |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
+ */ | |
+ | |
+#version 150 | |
+ | |
+// Keep these the same as in render_glsl.c | |
+#define CHARSET_COLS 64.0 | |
+#define TEX_DATA_WIDTH 512.0 | |
+#define TEX_DATA_HEIGHT 1024.0 | |
+#define TEX_DATA_PAL_Y 896.0 | |
+#define TEX_DATA_LAYER_X 0.0 | |
+#define TEX_DATA_LAYER_Y 901.0 | |
+ | |
+// This has to be slightly less than 14.0 to avoid propagating error | |
+// with some very old driver/video card combos. | |
+#define CHAR_H 13.99999 | |
+ | |
+uniform sampler2D baseMap; | |
+ | |
+layout(std140) uniform tilemap | |
+{ | |
+ ivec4 tiles[81*26/4+1]; | |
+}; | |
+uniform vec3 tilemap_size; | |
+in float protected_chr_position; | |
+in float protected_pal_position; | |
+ | |
+in vec2 vTexcoord; | |
+ | |
+out vec4 fragColor; | |
+ | |
+float fract_(float v) | |
+{ | |
+ return clamp(fract(v + 0.001) - 0.001, 0.000, 0.999); | |
+} | |
+ | |
+float floor_(float v) | |
+{ | |
+ return floor(v + 0.001); | |
+} | |
+ | |
+int int_(float v) | |
+{ | |
+ return int(v + 0.01); | |
+} | |
+ | |
+// NOTE: Layer data packing scheme | |
+// (highest two bits currently unused but included as part of the char) | |
+// w z y x | |
+// 00000000 00000000 00000000 00000000 | |
+// CCCCCCCC CCCCCCBB BBBBBBBF FFFFFFFF | |
+ | |
+// Some older cards/drivers tend o be slightly off; slight variations | |
+// in values here are intentional. | |
+ | |
+/** | |
+ * Get the char number from packed layer data as (approx.) an int. | |
+ */ | |
+ | |
+float layer_get_char(int layer_data) | |
+{ | |
+ return float((layer_data >> 18) & 0x3FFF); | |
+} | |
+ | |
+/** | |
+ * Get the foreground color from layer data relative to the texture width. | |
+ */ | |
+ | |
+float layer_get_fg_color(int layer_data) | |
+{ | |
+ return float(layer_data & 0x1FF) / TEX_DATA_WIDTH; | |
+} | |
+ | |
+/** | |
+ * Get the background color from layer data relative to the texture width. | |
+ */ | |
+ | |
+float layer_get_bg_color(int layer_data) | |
+{ | |
+ return float((layer_data >> 9) & 0x1FF) / TEX_DATA_WIDTH; | |
+} | |
+ | |
+void main(void) | |
+{ | |
+ /** | |
+ * Get the packed char/color data for this position from the current layer. | |
+ * vTexcoord will be provided in the range of x=[0..layer.w), y=[0..layer.h). | |
+ */ | |
+ float layer_x = (vTexcoord.x + TEX_DATA_LAYER_X) / TEX_DATA_WIDTH; | |
+ float layer_y = (vTexcoord.y + TEX_DATA_LAYER_Y) / TEX_DATA_HEIGHT; | |
+ int idx = int(floor(vTexcoord.y) * tilemap_size.x + floor(vTexcoord.x)); | |
+ int layer_data = tiles[idx / 4][idx & 3]; | |
+ //vec4 layer_data = texture2D(baseMap, vec2(layer_x, layer_y)); | |
+ | |
+ /** | |
+ * Get the current char and its base position in the texture charset. | |
+ * The x position will be normalized to the width of the texture, | |
+ * but for the y position it's easier to get the pixel position and | |
+ * normalize afterward. | |
+ */ | |
+ float char_num = layer_get_char(layer_data); | |
+ float char_x = fract_(char_num / CHARSET_COLS); | |
+ float char_y = floor_(char_num / CHARSET_COLS); | |
+ | |
+ /** | |
+ * Get the current pixel value of the current char from the texture. | |
+ */ | |
+ float char_tex_x = char_x + fract_(vTexcoord.x) / CHARSET_COLS; | |
+ float char_tex_y = (char_y + fract_(vTexcoord.y)) * CHAR_H / TEX_DATA_HEIGHT; | |
+ vec4 char_pix = texture2D(baseMap, vec2(char_tex_x, char_tex_y)); | |
+ | |
+ /** | |
+ * Determine whether this is the foreground or background color of the char, | |
+ * get that color from the texture, and output it. | |
+ */ | |
+ float color; | |
+ | |
+ // We could actually check any component here. | |
+ if(char_pix.x > 0.5) | |
+ { | |
+ color = layer_get_fg_color(layer_data); | |
+ } | |
+ else | |
+ { | |
+ color = layer_get_bg_color(layer_data); | |
+ } | |
+ | |
+ fragColor = texture2D(baseMap, vec2(color, TEX_DATA_PAL_Y / TEX_DATA_HEIGHT)); | |
+} | |
diff --git a/assets/glsl/tilemap.smzx.31.frag b/assets/glsl/tilemap.smzx.31.frag | |
new file mode 100644 | |
index 00000000..63f98c7c | |
--- /dev/null | |
+++ b/assets/glsl/tilemap.smzx.31.frag | |
@@ -0,0 +1,211 @@ | |
+/* MegaZeux | |
+ * | |
+ * Copyright (C) 2008 Joel Bouchard Lamontagne <logicow@gmail.com> | |
+ * Copyright (C) 2009 Alistair John Strachan <alistair@devzero.co.uk> | |
+ * Copyright (C) 2017 Dr Lancer-X <drlancer@megazeux.org> | |
+ * Copyright (C) 2020 Alice Rowan <petrifiedrowan@gmail.com> | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License as | |
+ * published by the Free Software Foundation; either version 2 of | |
+ * the License, or (at your option) any later version. | |
+ * | |
+ * This program is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License | |
+ * along with this program; if not, write to the Free Software | |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
+ */ | |
+ | |
+#version 150 | |
+ | |
+uniform sampler2D baseMap; | |
+ | |
+layout(std140) uniform tilemap | |
+{ | |
+ uint tiles[81*26]; | |
+}; | |
+uniform vec3 tilemap_size; | |
+uniform float protected_chr_position; | |
+uniform float protected_pal_position; | |
+ | |
+in vec2 vTexcoord; | |
+ | |
+out vec4 fragColor; | |
+ | |
+// Keep these the same as in render_glsl.c | |
+#define CHARSET_COLS 64.0 | |
+#define TEX_DATA_WIDTH 512.0 | |
+#define TEX_DATA_HEIGHT 1024.0 | |
+#define TEX_DATA_PAL_Y 896.0 | |
+#define TEX_DATA_IDX_Y 897.0 | |
+#define TEX_DATA_LAYER_X 0.0 | |
+#define TEX_DATA_LAYER_Y 901.0 | |
+ | |
+#define COLOR_TRANSPARENT (272.0 - 0.001) | |
+#define PIXEL_X 1.0 / TEX_DATA_WIDTH | |
+ | |
+// This has to be slightly less than 14.0 to avoid propagating error | |
+// with some very old driver/video card combos. | |
+#define CHAR_W 8.0 | |
+#define CHAR_H 13.99999 | |
+#define CHAR_W_I 8 | |
+#define CHAR_H_I 14 | |
+ | |
+float fract_(float v) | |
+{ | |
+ return clamp(fract(v + 0.001) - 0.001, 0.000, 0.999); | |
+} | |
+ | |
+float floor_(float v) | |
+{ | |
+ return floor(v + 0.001); | |
+} | |
+ | |
+float mod_(float v, float r) | |
+{ | |
+ return clamp(mod(v + 0.01, r) - 0.01, 0.0, r); | |
+} | |
+ | |
+int int_(float v) | |
+{ | |
+ return int(v + 0.01); | |
+} | |
+ | |
+// NOTE: Layer data packing scheme | |
+// (highest two bits currently unused but included as part of the char) | |
+// w z y x | |
+// 00000000 00000000 00000000 00000000 | |
+// CCCCCCCC CCCCCCBB BBBBBBBF FFFFFFFF | |
+ | |
+// Some older cards/drivers tend to be slightly off; slight variations | |
+// in values here are intentional. | |
+ | |
+/** | |
+ * Get the char number from packed layer data as (approx.) an int. | |
+ */ | |
+ | |
+float layer_get_char(vec4 layer_data) | |
+{ | |
+ return floor_(layer_data.z * 63.75) + (layer_data.w * 255.0) * 64.0; | |
+} | |
+ | |
+/** | |
+ * Get the foreground color from layer data as (approx.) an int. | |
+ */ | |
+ | |
+float layer_get_fg_color(vec4 layer_data) | |
+{ | |
+ return | |
+ (layer_data.x * 255.001) + | |
+ fract_(layer_data.y * 127.501) * 512.0; | |
+} | |
+ | |
+/** | |
+ * Get the background color from layer data as (approx.) an int. | |
+ */ | |
+ | |
+float layer_get_bg_color(vec4 layer_data) | |
+{ | |
+ return | |
+ floor_(layer_data.y * 127.5) + | |
+ fract_(layer_data.z * 63.751) * 512.0; | |
+} | |
+ | |
+void main( void ) | |
+{ | |
+ /** | |
+ * Get the packed char/color data for this position from the current layer. | |
+ * vTexcoord will be provided in the range of x=[0..layer.w), y=[0..layer.h). | |
+ */ | |
+ float layer_x = (vTexcoord.x + TEX_DATA_LAYER_X) / TEX_DATA_WIDTH; | |
+ float layer_y = (vTexcoord.y + TEX_DATA_LAYER_Y) / TEX_DATA_HEIGHT; | |
+ vec4 layer_data = texture2D(baseMap, vec2(layer_x, layer_y)); | |
+ | |
+ float fg_color = layer_get_fg_color(layer_data); | |
+ float bg_color = layer_get_bg_color(layer_data); | |
+ | |
+ if(fg_color >= COLOR_TRANSPARENT || bg_color >= COLOR_TRANSPARENT) | |
+ { | |
+ fragColor = vec4(0.0, 0.0, 0.0, 0.0); | |
+ } | |
+ else | |
+ { | |
+ /** | |
+ * The math in this shader is more complex than the math in the regular | |
+ * shader, so it's handled partly in integers instead of floats. Older cards | |
+ * seem less bad at calculating ints than floats (albeit slower too). | |
+ * | |
+ * Get the current char and: | |
+ * | |
+ * 1) determine the pixel position in the char we should be looking at. | |
+ * We're considering pairs of two pixels horizontally adjacent, so get | |
+ * the position of the left pixel in the pair specifically. | |
+ * | |
+ * 2) Calculate the position on the texture in pixel scale where the | |
+ * current char is and add the offset from step 1. | |
+ */ | |
+ float char_num = layer_get_char(layer_data); | |
+ | |
+ int px = int_(fract_(vTexcoord.x) * CHAR_W) / 2 * 2; | |
+ int py = int_(fract_(vTexcoord.y) * CHAR_H); | |
+ | |
+ int char_x = int_(mod_(char_num, CHARSET_COLS) * CHAR_W) + px; | |
+ int char_y = int_(char_num / CHARSET_COLS) * CHAR_H_I + py; | |
+ | |
+ /** | |
+ * Get the current pixels of the current char from the texture. | |
+ * Together, these determine which color of the current subpalette to use. | |
+ */ | |
+ float char_tex_x = float(char_x) / TEX_DATA_WIDTH; | |
+ float char_tex_y = float(char_y) / TEX_DATA_HEIGHT; | |
+ | |
+ vec4 char_pix_l = texture2D(baseMap, vec2(char_tex_x, char_tex_y)); | |
+ vec4 char_pix_r = texture2D(baseMap, vec2(char_tex_x + PIXEL_X, char_tex_y)); | |
+ | |
+ /** | |
+ * Determine the SMZX subpalette and SMZX index of the current pixel, | |
+ * get that color from the texture, and output it. | |
+ */ | |
+ | |
+ int smzx_col; | |
+ | |
+ // We could actually check any component here. | |
+ if(char_pix_l.x < 0.5) | |
+ { | |
+ if(char_pix_r.x < 0.5) | |
+ { | |
+ smzx_col = 0; | |
+ } | |
+ else | |
+ { | |
+ smzx_col = 1; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if(char_pix_r.x < 0.5) | |
+ { | |
+ smzx_col = 2; | |
+ } | |
+ else | |
+ { | |
+ smzx_col = 3; | |
+ } | |
+ } | |
+ | |
+ float subpal = mod_(floor_(bg_color), 16.0) * 16.0 + mod_(fg_color, 16.0); | |
+ | |
+ float smzx_tex_x = subpal / TEX_DATA_WIDTH; | |
+ float smzx_tex_y = (float(smzx_col) + TEX_DATA_IDX_Y) / TEX_DATA_HEIGHT; | |
+ | |
+ // NOTE: This must use the x component. | |
+ float real_col = texture2D(baseMap, vec2(smzx_tex_x, smzx_tex_y)).x * 255.001; | |
+ | |
+ fragColor = texture2D(baseMap, | |
+ vec2(real_col / TEX_DATA_WIDTH, TEX_DATA_PAL_Y / TEX_DATA_HEIGHT)); | |
+ } | |
+} | |
diff --git a/src/render_glsl.c b/src/render_glsl.c | |
index 64b1e03c..ca2527b8 100644 | |
--- a/src/render_glsl.c | |
+++ b/src/render_glsl.c | |
@@ -110,6 +110,30 @@ enum | |
NUM_FBOS | |
}; | |
+enum | |
+{ | |
+ UBO_TILEMAP, | |
+ NUM_UBOS | |
+}; | |
+ | |
+enum | |
+{ | |
+ U_TILEMAP_SIZE, | |
+ U_TILEMAP_SIZE_SMZX, | |
+ U_PRO_CHR, | |
+ U_PRO_CHR_SMZX, | |
+ U_PRO_PAL, | |
+ U_PRO_PAL_SMZX, | |
+ NUM_UNIFORMS | |
+}; | |
+ | |
+enum | |
+{ | |
+ UIDX_TILEMAP, | |
+ UIDX_TILEMAP_SMZX, | |
+ NUM_UINDICES | |
+}; | |
+ | |
enum | |
{ | |
ATTRIB_POSITION, | |
@@ -215,6 +239,23 @@ static struct | |
void (GL_APIENTRY *glBindFramebuffer)(GLenum target, GLuint framebuffer); | |
void (GL_APIENTRY *glFramebufferTexture2D)(GLenum target, GLenum attachment, | |
GLenum textarget, GLuint texture, GLint level); | |
+ | |
+ // Functions only used in conjunction with UBOs. | |
+ // Optional for GL (requires 3.1+), mandatory for GLES. | |
+ boolean has_ubo; | |
+ // GL_UNIFORM_BUFFER; GL_DYNAMIC_DRAW | |
+ void (GL_APIENTRY *glBindBuffer)(GLenum target, GLuint buffer); | |
+ void (GL_APIENTRY *glGenBuffers)(GLsizei n, GLuint *buffers); | |
+ void (GL_APIENTRY *glDeleteBuffers)(GLsizei n, const GLuint *buffers); | |
+ void (GL_APIENTRY *glBufferData)(GLenum target, GLsizeiptr size, | |
+ const void *data, GLenum usage); | |
+ void *(GL_APIENTRY *glMapBuffer)(GLenum target, GLenum access); | |
+ GLboolean (GL_APIENTRY *glUnmapBuffer)(GLenum target); | |
+ void (GL_APIENTRY *glBindBufferBase)(GLenum target, GLuint index, GLuint buffer); | |
+ GLuint (GL_APIENTRY *glGetUniformBlockIndex)(GLuint program, const char *name); | |
+ GLint (GL_APIENTRY *glGetUniformLocation)(GLuint program, const char *name); | |
+ void (GL_APIENTRY *glUniform1f)(GLint location, GLfloat v0); | |
+ void (GL_APIENTRY *glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); | |
} | |
glsl; | |
@@ -265,6 +306,22 @@ static const struct dso_syms_map glsl_syms_map_fbo[] = | |
{ NULL, NULL } | |
}; | |
+static const struct dso_syms_map glsl_syms_map_ubo[] = | |
+{ | |
+ { "glBindBuffer", (fn_ptr *)&glsl.glBindBuffer }, | |
+ { "glBindBufferBase", (fn_ptr *)&glsl.glBindBufferBase }, | |
+ { "glBufferData", (fn_ptr *)&glsl.glBufferData }, | |
+ { "glDeleteBuffers", (fn_ptr *)&glsl.glDeleteBuffers }, | |
+ { "glGenBuffers", (fn_ptr *)&glsl.glGenBuffers }, | |
+ { "glGetUniformBlockIndex", (fn_ptr *)&glsl.glGetUniformBlockIndex }, | |
+ { "glGetUniformLocation", (fn_ptr *)&glsl.glGetUniformLocation }, | |
+ { "glMapBuffer", (fn_ptr *)&glsl.glMapBuffer }, | |
+ { "glUniform1f", (fn_ptr *)&glsl.glUniform1f }, | |
+ { "glUniform3f", (fn_ptr *)&glsl.glUniform3f }, | |
+ { "glUnmapBuffer", (fn_ptr *)&glsl.glUnmapBuffer }, | |
+ { NULL, NULL } | |
+}; | |
+ | |
#define gl_check_error() gl_error(__FILE__, __LINE__, glsl.glGetError) | |
struct glsl_render_data | |
@@ -280,6 +337,10 @@ struct glsl_render_data | |
Uint32 background_texture[BG_WIDTH * BG_HEIGHT]; | |
GLuint textures[NUM_TEXTURES]; | |
GLuint fbos[NUM_FBOS]; | |
+ GLuint ubos[NUM_UBOS]; | |
+ GLuint uidx[NUM_UINDICES]; | |
+ GLint uniforms[NUM_UNIFORMS]; | |
+ Uint32 ubo_data[81 * 26]; | |
GLubyte palette[3 * FULL_PAL_SIZE]; | |
Uint8 remap_texture; | |
Uint8 remap_char[FULL_CHARSET_SIZE]; | |
@@ -563,7 +624,7 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
} | |
render_data->tilemap_program = glsl_load_program(graphics, | |
- GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_FRAG); | |
+ GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_31_FRAG); | |
if(render_data->tilemap_program) | |
{ | |
glsl.glBindAttribLocation(render_data->tilemap_program, | |
@@ -573,10 +634,26 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl.glLinkProgram(render_data->tilemap_program); | |
glsl_verify_link(render_data, render_data->tilemap_program); | |
glsl_delete_shaders(render_data->tilemap_program); | |
+ | |
+ render_data->uniforms[U_TILEMAP_SIZE] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_program, "tilemap_size"); | |
+ gl_check_error(); | |
+ | |
+ render_data->uniforms[U_PRO_PAL] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_program, "protected_pal_position"); | |
+ gl_check_error(); | |
+ | |
+ render_data->uniforms[U_PRO_CHR] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_program, "protected_chr_position"); | |
+ gl_check_error(); | |
+ | |
+ render_data->uidx[UIDX_TILEMAP] = | |
+ glsl.glGetUniformBlockIndex(render_data->tilemap_program, "tilemap"); | |
+ gl_check_error(); | |
} | |
render_data->tilemap_smzx_program = glsl_load_program(graphics, | |
- GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_SMZX_FRAG); | |
+ GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_SMZX_31_FRAG); | |
if(render_data->tilemap_smzx_program) | |
{ | |
glsl.glBindAttribLocation(render_data->tilemap_smzx_program, | |
@@ -586,6 +663,32 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl.glLinkProgram(render_data->tilemap_smzx_program); | |
glsl_verify_link(render_data, render_data->tilemap_smzx_program); | |
glsl_delete_shaders(render_data->tilemap_smzx_program); | |
+ | |
+ render_data->uniforms[U_TILEMAP_SIZE_SMZX] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_smzx_program, "tilemap_size"); | |
+ gl_check_error(); | |
+ | |
+ render_data->uniforms[U_PRO_PAL_SMZX] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_smzx_program, "protected_pal_position"); | |
+ gl_check_error(); | |
+ | |
+ render_data->uniforms[U_PRO_CHR_SMZX] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_smzx_program, "protected_chr_position"); | |
+ gl_check_error(); | |
+ | |
+ render_data->uidx[UIDX_TILEMAP_SMZX] = | |
+ glsl.glGetUniformBlockIndex(render_data->tilemap_smzx_program, "tilemap"); | |
+ gl_check_error(); | |
+ } | |
+ | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glBindBuffer(GL_UNIFORM_BUFFER, render_data->ubos[UBO_TILEMAP]); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBufferData(GL_UNIFORM_BUFFER, sizeof(render_data->ubo_data), | |
+ render_data->ubo_data, GL_DYNAMIC_DRAW); | |
+ gl_check_error(); | |
} | |
render_data->mouse_program = glsl_load_program(graphics, | |
@@ -682,6 +785,12 @@ static void glsl_free_video(struct graphics_data *graphics) | |
gl_check_error(); | |
} | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glDeleteBuffers(NUM_UBOS, render_data->ubos); | |
+ gl_check_error(); | |
+ } | |
+ | |
glsl.glDeleteTextures(NUM_TEXTURES, render_data->textures); | |
gl_check_error(); | |
@@ -757,6 +866,18 @@ static void glsl_resize_screen(struct graphics_data *graphics, | |
GL_TEXTURE_2D, render_data->textures[TEX_SCREEN_ID], 0); | |
} | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glDeleteBuffers(NUM_UBOS, render_data->ubos); | |
+ gl_check_error(); | |
+ | |
+ glsl.glGenBuffers(NUM_UBOS, render_data->ubos); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBindBuffer(GL_UNIFORM_BUFFER, render_data->ubos[UBO_TILEMAP]); | |
+ gl_check_error(); | |
+ } | |
+ | |
// Data texture | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
gl_check_error(); | |
@@ -776,6 +897,7 @@ static boolean glsl_set_video_mode(struct graphics_data *graphics, | |
int width, int height, int depth, boolean fullscreen, boolean resize) | |
{ | |
boolean load_fbo_syms = true; | |
+ boolean load_ubo_syms = false; // FIXME not supported by GLES 2 :( | |
gl_set_attributes(graphics); | |
@@ -819,10 +941,18 @@ static boolean glsl_set_video_mode(struct graphics_data *graphics, | |
return false; | |
} | |
+ load_fbo_syms = false; | |
+ load_ubo_syms = false; | |
if(version_float >= 3.0) | |
+ { | |
debug("Attempting to load FBO syms...\n"); | |
- else | |
- load_fbo_syms = false; | |
+ load_fbo_syms = true; | |
+ } | |
+ if(version_float >= 3.1) | |
+ { | |
+ debug("Attempting to load UBO syms...\n"); | |
+ load_ubo_syms = true; | |
+ } | |
initialized = true; | |
} | |
@@ -837,6 +967,14 @@ static boolean glsl_set_video_mode(struct graphics_data *graphics, | |
else | |
glsl.has_fbo = false; | |
+ if(load_ubo_syms && gl_load_syms(glsl_syms_map_ubo)) | |
+ { | |
+ debug("Using UBO syms and shaders for GLSL renderer.\n"); | |
+ glsl.has_ubo = true; | |
+ } | |
+ else | |
+ glsl.has_ubo = false; | |
+ | |
glsl_resize_screen(graphics, width, height); | |
return true; | |
} | |
@@ -974,7 +1112,7 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
{ | |
struct glsl_render_data *render_data = graphics->render_data; | |
struct char_element *src = layer->data; | |
- Uint32 *colorptr, *dest, i, j; | |
+ Uint32 *colorptr, *dest, *dest2, i, j; | |
int width, height; | |
Uint32 char_value, fg_color, bg_color; | |
@@ -1023,11 +1161,51 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
glsl.glViewport(0, 0, width, height); | |
gl_check_error(); | |
+ // Uniform buffer | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glBindBuffer(GL_UNIFORM_BUFFER, render_data->ubos[UBO_TILEMAP]); | |
+ gl_check_error(); | |
+ } | |
+ | |
if(layer->mode == 0) | |
+ { | |
glsl.glUseProgram(render_data->tilemap_program); | |
+ gl_check_error(); | |
+ | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glUniform3f(render_data->uniforms[U_TILEMAP_SIZE], layer->w, layer->h, layer->offset); | |
+ gl_check_error(); | |
+ glsl.glUniform1f(render_data->uniforms[U_PRO_CHR], PRO_CH); | |
+ gl_check_error(); | |
+ glsl.glUniform1f(render_data->uniforms[U_PRO_PAL], graphics->protected_pal_position); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBindBufferBase(GL_UNIFORM_BUFFER, render_data->uidx[UIDX_TILEMAP], | |
+ render_data->ubos[UBO_TILEMAP]); | |
+ gl_check_error(); | |
+ } | |
+ } | |
else | |
+ { | |
glsl.glUseProgram(render_data->tilemap_smzx_program); | |
- gl_check_error(); | |
+ gl_check_error(); | |
+ | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glUniform3f(render_data->uniforms[U_TILEMAP_SIZE_SMZX], layer->w, layer->h, layer->offset); | |
+ gl_check_error(); | |
+ glsl.glUniform1f(render_data->uniforms[U_PRO_CHR_SMZX], PRO_CH); | |
+ gl_check_error(); | |
+ glsl.glUniform1f(render_data->uniforms[U_PRO_PAL_SMZX], graphics->protected_pal_position); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBindBufferBase(GL_UNIFORM_BUFFER, render_data->uidx[UIDX_TILEMAP_SMZX], | |
+ render_data->ubos[UBO_TILEMAP]); | |
+ gl_check_error(); | |
+ } | |
+ } | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
gl_check_error(); | |
@@ -1052,8 +1230,9 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
// Layer data | |
dest = render_data->background_texture; | |
+ dest2 = render_data->ubo_data; | |
- for(i = 0; i < layer->w * layer->h; i++, dest++, src++) | |
+ for(i = 0; i < layer->w * layer->h; i++, dest++, dest2++, src++) | |
{ | |
char_value = src->char_value; | |
bg_color = src->bg_color; | |
@@ -1080,6 +1259,17 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
(char_value << LAYER_CHAR_POS) | | |
(bg_color << LAYER_BG_POS) | | |
(fg_color << LAYER_FG_POS); | |
+ *dest2 = *dest; | |
+ } | |
+ | |
+ // Uniform buffer | |
+ if(glsl.has_ubo) | |
+ { | |
+ void *p = glsl.glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); | |
+ gl_check_error(); | |
+ memcpy(p, render_data->ubo_data, layer->w * layer->h * sizeof(Uint32)); | |
+ glsl.glUnmapBuffer(GL_UNIFORM_BUFFER); | |
+ gl_check_error(); | |
} | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
diff --git a/src/util.c b/src/util.c | |
index f31b41f3..20994ee5 100644 | |
--- a/src/util.c | |
+++ b/src/util.c | |
@@ -81,6 +81,8 @@ static struct mzx_resource mzx_res[] = | |
{ GLSL_SHADERS "tilemap.vert", NULL, false, false }, | |
{ GLSL_SHADERS "tilemap.frag", NULL, false, false }, | |
{ GLSL_SHADERS "tilemap.smzx.frag", NULL, false, false }, | |
+ { GLSL_SHADERS "tilemap.31.frag", NULL, false, false }, | |
+ { GLSL_SHADERS "tilemap.smzx.31.frag",NULL, false, false }, | |
{ GLSL_SHADERS "mouse.vert", NULL, false, false }, | |
{ GLSL_SHADERS "mouse.frag", NULL, false, false }, | |
{ GLSL_SHADERS "cursor.vert", NULL, false, false }, | |
diff --git a/src/util.h b/src/util.h | |
index 25f92da9..7b6bbc18 100644 | |
--- a/src/util.h | |
+++ b/src/util.h | |
@@ -65,6 +65,8 @@ enum resource_id | |
GLSL_SHADER_TILEMAP_VERT, | |
GLSL_SHADER_TILEMAP_FRAG, | |
GLSL_SHADER_TILEMAP_SMZX_FRAG, | |
+ GLSL_SHADER_TILEMAP_31_FRAG, | |
+ GLSL_SHADER_TILEMAP_SMZX_31_FRAG, | |
GLSL_SHADER_MOUSE_VERT, | |
GLSL_SHADER_MOUSE_FRAG, | |
GLSL_SHADER_CURSOR_VERT, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/assets/glsl/tilemap.31.frag b/assets/glsl/tilemap.31.frag | |
new file mode 100644 | |
index 00000000..1b4144bf | |
--- /dev/null | |
+++ b/assets/glsl/tilemap.31.frag | |
@@ -0,0 +1,108 @@ | |
+/* MegaZeux | |
+ * | |
+ * Copyright (C) 2008 Joel Bouchard Lamontagne <logicow@gmail.com> | |
+ * Copyright (C) 2009 Alistair John Strachan <alistair@devzero.co.uk> | |
+ * Copyright (C) 2017 Dr Lancer-X <drlancer@megazeux.org> | |
+ * Copyright (C) 2020 Alice Rowan <petrifiedrowan@gmail.com> | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License as | |
+ * published by the Free Software Foundation; either version 2 of | |
+ * the License, or (at your option) any later version. | |
+ * | |
+ * This program is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License | |
+ * along with this program; if not, write to the Free Software | |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
+ */ | |
+ | |
+#version 150 | |
+ | |
+// Keep these the same as in render_glsl.c | |
+#define CHARSET_COLS 64.0 | |
+#define TEX_DATA_WIDTH 512.0 | |
+#define TEX_DATA_HEIGHT 1024.0 | |
+#define TEX_DATA_PAL_Y 896.0 | |
+ | |
+// This has to be slightly less than 14.0 to avoid propagating error | |
+// with some very old driver/video card combos. | |
+#define CHAR_H 13.99999 | |
+ | |
+// The tilemap data needs to be packed into vec4s to make as much use of the | |
+// uniform buffer block as possible. | |
+#define TILEMAP_VEC4_SIZE (81 * 26 / 4 + 1) | |
+ | |
+uniform sampler2D baseMap; | |
+ | |
+uniform vec4 tilemap_size; | |
+layout(std140) uniform tilemap_char_x | |
+{ | |
+ vec4 char_x[TILEMAP_VEC4_SIZE]; | |
+}; | |
+layout(std140) uniform tilemap_char_y | |
+{ | |
+ vec4 char_y[TILEMAP_VEC4_SIZE]; | |
+}; | |
+layout(std140) uniform tilemap_color_fg | |
+{ | |
+ vec4 color_fg[TILEMAP_VEC4_SIZE]; | |
+}; | |
+layout(std140) uniform tilemap_color_bg | |
+{ | |
+ vec4 color_bg[TILEMAP_VEC4_SIZE]; | |
+}; | |
+ | |
+in vec2 vTexcoord; | |
+ | |
+out vec4 fragColor; | |
+ | |
+float fract_(float v) | |
+{ | |
+ return clamp(fract(v + 0.001) - 0.001, 0.000, 0.999); | |
+} | |
+ | |
+float floor_(float v) | |
+{ | |
+ return floor(v + 0.001); | |
+} | |
+ | |
+int int_(float v) | |
+{ | |
+ return int(v + 0.01); | |
+} | |
+ | |
+void main(void) | |
+{ | |
+ int idx = int_(floor_(vTexcoord.y) * tilemap_size.x + floor_(vTexcoord.x)); | |
+ int i = idx / 4; | |
+ int j = idx & 3; | |
+ | |
+ /** | |
+ * Get the current pixel value of the current char from the texture. | |
+ */ | |
+ float char_tex_x = char_x[i][j] + fract_(vTexcoord.x) / CHARSET_COLS; | |
+ float char_tex_y = char_y[i][j] + (fract_(vTexcoord.y) * CHAR_H / TEX_DATA_HEIGHT); | |
+ vec4 char_pix = texture2D(baseMap, vec2(char_tex_x, char_tex_y)); | |
+ | |
+ /** | |
+ * Determine whether this is the foreground or background color of the char, | |
+ * get that color from the texture, and output it. | |
+ */ | |
+ float color; | |
+ | |
+ // We could actually check any component here. | |
+ if(char_pix.x > 0.5) | |
+ { | |
+ color = color_fg[i][j] / TEX_DATA_WIDTH; | |
+ } | |
+ else | |
+ { | |
+ color = color_bg[i][j] / TEX_DATA_WIDTH; | |
+ } | |
+ | |
+ fragColor = texture2D(baseMap, vec2(color, TEX_DATA_PAL_Y / TEX_DATA_HEIGHT)); | |
+} | |
diff --git a/assets/glsl/tilemap.smzx.31.frag b/assets/glsl/tilemap.smzx.31.frag | |
new file mode 100644 | |
index 00000000..73b6c246 | |
--- /dev/null | |
+++ b/assets/glsl/tilemap.smzx.31.frag | |
@@ -0,0 +1,165 @@ | |
+/* MegaZeux | |
+ * | |
+ * Copyright (C) 2008 Joel Bouchard Lamontagne <logicow@gmail.com> | |
+ * Copyright (C) 2009 Alistair John Strachan <alistair@devzero.co.uk> | |
+ * Copyright (C) 2017 Dr Lancer-X <drlancer@megazeux.org> | |
+ * Copyright (C) 2020 Alice Rowan <petrifiedrowan@gmail.com> | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License as | |
+ * published by the Free Software Foundation; either version 2 of | |
+ * the License, or (at your option) any later version. | |
+ * | |
+ * This program is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License | |
+ * along with this program; if not, write to the Free Software | |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
+ */ | |
+ | |
+#version 150 | |
+ | |
+uniform sampler2D baseMap; | |
+ | |
+// The tilemap data needs to be packed into vec4s to make as much use of the | |
+// uniform buffer block as possible. | |
+#define TILEMAP_VEC4_SIZE (81 * 26 / 4 + 1) | |
+ | |
+uniform vec4 tilemap_size; | |
+layout(std140) uniform tilemap_char_x | |
+{ | |
+ vec4 char_x[TILEMAP_VEC4_SIZE]; | |
+}; | |
+layout(std140) uniform tilemap_char_y | |
+{ | |
+ vec4 char_y[TILEMAP_VEC4_SIZE]; | |
+}; | |
+layout(std140) uniform tilemap_color_fg | |
+{ | |
+ vec4 color_fg[TILEMAP_VEC4_SIZE]; | |
+}; | |
+layout(std140) uniform tilemap_color_bg | |
+{ | |
+ vec4 color_bg[TILEMAP_VEC4_SIZE]; | |
+}; | |
+ | |
+in vec2 vTexcoord; | |
+ | |
+out vec4 fragColor; | |
+ | |
+// Keep these the same as in render_glsl.c | |
+#define CHARSET_COLS 64.0 | |
+#define TEX_DATA_WIDTH 512.0 | |
+#define TEX_DATA_HEIGHT 1024.0 | |
+#define TEX_DATA_PAL_Y 896.0 | |
+#define TEX_DATA_IDX_Y 897.0 | |
+ | |
+#define COLOR_TRANSPARENT (272.0 - 0.001) | |
+#define PIXEL_X 1.0 / TEX_DATA_WIDTH | |
+ | |
+// This has to be slightly less than 14.0 to avoid propagating error | |
+// with some very old driver/video card combos. | |
+#define CHAR_W 8.0 | |
+#define CHAR_H 13.99999 | |
+#define CHAR_W_I 8 | |
+#define CHAR_H_I 14 | |
+ | |
+float fract_(float v) | |
+{ | |
+ return clamp(fract(v + 0.001) - 0.001, 0.000, 0.999); | |
+} | |
+ | |
+float floor_(float v) | |
+{ | |
+ return floor(v + 0.001); | |
+} | |
+ | |
+float mod_(float v, float r) | |
+{ | |
+ return clamp(mod(v + 0.01, r) - 0.01, 0.0, r); | |
+} | |
+ | |
+int int_(float v) | |
+{ | |
+ return int(v + 0.01); | |
+} | |
+ | |
+void main( void ) | |
+{ | |
+ int idx = int_(floor_(vTexcoord.y) * tilemap_size.x + floor_(vTexcoord.x)); | |
+ int i = idx / 4; | |
+ int j = idx & 3; | |
+ | |
+ float fg_color = color_fg[i][j]; | |
+ float bg_color = color_bg[i][j]; | |
+ | |
+ if(fg_color >= COLOR_TRANSPARENT || bg_color >= COLOR_TRANSPARENT) | |
+ { | |
+ fragColor = vec4(0.0, 0.0, 0.0, 0.0); | |
+ } | |
+ else | |
+ { | |
+ /** | |
+ * Determine the pixel position in the char we should be looking at. | |
+ * We're considering pairs of two pixels horizontally adjacent, so get | |
+ * the position of the left pixel in the pair specifically. | |
+ */ | |
+ int px = int_(fract_(vTexcoord.x) * CHAR_W) / 2 * 2; | |
+ int py = int_(fract_(vTexcoord.y) * CHAR_H); | |
+ | |
+ /** | |
+ * Get the current pixels of the current char from the texture. | |
+ * Together, these determine which color of the current subpalette to use. | |
+ */ | |
+ float char_tex_x = char_x[i][j] + float(px) / TEX_DATA_WIDTH; | |
+ float char_tex_y = char_y[i][j] + float(py) / TEX_DATA_HEIGHT; | |
+ | |
+ vec4 char_pix_l = texture2D(baseMap, vec2(char_tex_x, char_tex_y)); | |
+ vec4 char_pix_r = texture2D(baseMap, vec2(char_tex_x + PIXEL_X, char_tex_y)); | |
+ | |
+ /** | |
+ * Determine the SMZX subpalette and SMZX index of the current pixel, | |
+ * get that color from the texture, and output it. | |
+ */ | |
+ | |
+ int smzx_col; | |
+ | |
+ // We could actually check any component here. | |
+ if(char_pix_l.x < 0.5) | |
+ { | |
+ if(char_pix_r.x < 0.5) | |
+ { | |
+ smzx_col = 0; | |
+ } | |
+ else | |
+ { | |
+ smzx_col = 1; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if(char_pix_r.x < 0.5) | |
+ { | |
+ smzx_col = 2; | |
+ } | |
+ else | |
+ { | |
+ smzx_col = 3; | |
+ } | |
+ } | |
+ | |
+ float subpal = mod_(floor_(bg_color), 16.0) * 16.0 + mod_(fg_color, 16.0); | |
+ | |
+ float smzx_tex_x = subpal / TEX_DATA_WIDTH; | |
+ float smzx_tex_y = (float(smzx_col) + TEX_DATA_IDX_Y) / TEX_DATA_HEIGHT; | |
+ | |
+ // NOTE: This must use the x component. | |
+ float real_col = texture2D(baseMap, vec2(smzx_tex_x, smzx_tex_y)).x * 255.001; | |
+ | |
+ fragColor = texture2D(baseMap, | |
+ vec2(real_col / TEX_DATA_WIDTH, TEX_DATA_PAL_Y / TEX_DATA_HEIGHT)); | |
+ } | |
+} | |
diff --git a/src/render_glsl.c b/src/render_glsl.c | |
index 80d2116e..545bf3de 100644 | |
--- a/src/render_glsl.c | |
+++ b/src/render_glsl.c | |
@@ -116,6 +116,28 @@ enum | |
NUM_FBOS | |
}; | |
+enum | |
+{ | |
+ PROG_MZX, | |
+ PROG_SMZX, | |
+ NUM_PROGS | |
+}; | |
+ | |
+enum | |
+{ | |
+ UBO_CHAR_X, | |
+ UBO_CHAR_Y, | |
+ UBO_COLOR_FG, | |
+ UBO_COLOR_BG, | |
+ NUM_UBOS | |
+}; | |
+ | |
+enum | |
+{ | |
+ U_TILEMAP_SIZE, | |
+ NUM_UNIFORMS | |
+}; | |
+ | |
enum | |
{ | |
ATTRIB_POSITION, | |
@@ -123,6 +145,19 @@ enum | |
ATTRIB_COLOR, | |
}; | |
+static const char *uniform_name[NUM_UNIFORMS] = | |
+{ | |
+ [U_TILEMAP_SIZE] = "tilemap_size", | |
+}; | |
+ | |
+static const char *ubo_name[NUM_UBOS] = | |
+{ | |
+ [UBO_CHAR_X] = "tilemap_char_x", | |
+ [UBO_CHAR_Y] = "tilemap_char_y", | |
+ [UBO_COLOR_FG] = "tilemap_color_fg", | |
+ [UBO_COLOR_BG] = "tilemap_color_bg" | |
+}; | |
+ | |
/** | |
* Some GL drivers attempt to run GLSL in software, resulting in extremely poor | |
* performance for MegaZeux. When one of the drivers in this blacklist is | |
@@ -224,6 +259,24 @@ static struct | |
void (GL_APIENTRY *glBindFramebuffer)(GLenum target, GLuint framebuffer); | |
void (GL_APIENTRY *glFramebufferTexture2D)(GLenum target, GLenum attachment, | |
GLenum textarget, GLuint texture, GLint level); | |
+ | |
+ // Functions only used in conjunction with UBOs. | |
+ // Optional for GL (requires 3.1+), optional for GLES (requires 3.0). | |
+ boolean has_ubo; | |
+ void (GL_APIENTRY *glBindBuffer)(GLenum target, GLuint buffer); | |
+ void (GL_APIENTRY *glGenBuffers)(GLsizei n, GLuint *buffers); | |
+ void (GL_APIENTRY *glDeleteBuffers)(GLsizei n, const GLuint *buffers); | |
+ void (GL_APIENTRY *glBufferData)(GLenum target, GLsizeiptr size, | |
+ const void *data, GLenum usage); | |
+ void (GL_APIENTRY *glBufferSubData)(GLenum target, GLintptr offset, | |
+ GLsizeiptr size, const void *data); | |
+ void (GL_APIENTRY *glBindBufferBase)(GLenum target, GLuint index, GLuint buffer); | |
+ void (GL_APIENTRY *glUniformBlockBinding)(GLuint program, | |
+ GLuint uniformBlockIndex, GLuint uniformBlockBinding); | |
+ GLuint (GL_APIENTRY *glGetUniformBlockIndex)(GLuint program, const char *name); | |
+ GLint (GL_APIENTRY *glGetUniformLocation)(GLuint program, const char *name); | |
+ void (GL_APIENTRY *glUniform4f)(GLint location, GLfloat v0, GLfloat v1, | |
+ GLfloat v2, GLfloat v3); | |
} | |
glsl; | |
@@ -277,6 +330,21 @@ static const struct dso_syms_map glsl_syms_map_fbo[] = | |
{ NULL, NULL } | |
}; | |
+static const struct dso_syms_map glsl_syms_map_ubo[] = | |
+{ | |
+ { "glBindBuffer", (fn_ptr *)&glsl.glBindBuffer }, | |
+ { "glBindBufferBase", (fn_ptr *)&glsl.glBindBufferBase }, | |
+ { "glBufferData", (fn_ptr *)&glsl.glBufferData }, | |
+ { "glBufferSubData", (fn_ptr *)&glsl.glBufferSubData }, | |
+ { "glDeleteBuffers", (fn_ptr *)&glsl.glDeleteBuffers }, | |
+ { "glGenBuffers", (fn_ptr *)&glsl.glGenBuffers }, | |
+ { "glGetUniformBlockIndex", (fn_ptr *)&glsl.glGetUniformBlockIndex }, | |
+ { "glGetUniformLocation", (fn_ptr *)&glsl.glGetUniformLocation }, | |
+ { "glUniform4f", (fn_ptr *)&glsl.glUniform4f }, | |
+ { "glUniformBlockBinding", (fn_ptr *)&glsl.glUniformBlockBinding }, | |
+ { NULL, NULL } | |
+}; | |
+ | |
#define gl_check_error() gl_error(__FILE__, __LINE__, glsl.glGetError) | |
struct glsl_render_data | |
@@ -292,6 +360,10 @@ struct glsl_render_data | |
Uint32 background_texture[BG_WIDTH * BG_HEIGHT]; | |
GLuint textures[NUM_TEXTURES]; | |
GLuint fbos[NUM_FBOS]; | |
+ GLuint ubos[NUM_UBOS]; | |
+ GLuint uidx[NUM_PROGS][NUM_UBOS]; | |
+ GLint uniforms[NUM_PROGS][NUM_UNIFORMS]; | |
+ float ubo_data[NUM_UBOS][81 * 26]; | |
GLubyte palette[3 * FULL_PAL_SIZE]; | |
Uint8 remap_texture; | |
Uint8 remap_char[FULL_CHARSET_SIZE]; | |
@@ -563,6 +635,7 @@ static void glsl_delete_shaders(GLuint program) | |
static void glsl_load_shaders(struct graphics_data *graphics) | |
{ | |
struct glsl_render_data *render_data = graphics->render_data; | |
+ int i; | |
render_data->scaler_program = glsl_load_program(graphics, | |
GLSL_SHADER_SCALER_VERT, GLSL_SHADER_SCALER_FRAG); | |
@@ -577,8 +650,9 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl_delete_shaders(render_data->scaler_program); | |
} | |
+ // FIXME use fragment shader for correct version. | |
render_data->tilemap_program = glsl_load_program(graphics, | |
- GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_FRAG); | |
+ GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_31_FRAG); | |
if(render_data->tilemap_program) | |
{ | |
glsl.glBindAttribLocation(render_data->tilemap_program, | |
@@ -588,10 +662,32 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl.glLinkProgram(render_data->tilemap_program); | |
glsl_verify_link(render_data, render_data->tilemap_program); | |
glsl_delete_shaders(render_data->tilemap_program); | |
+ | |
+ if(glsl.has_ubo) | |
+ { | |
+ for(i = 0; i < NUM_UNIFORMS; i++) | |
+ { | |
+ render_data->uniforms[PROG_MZX][i] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_program, uniform_name[i]); | |
+ gl_check_error(); | |
+ } | |
+ | |
+ for(i = 0; i < NUM_UBOS; i++) | |
+ { | |
+ render_data->uidx[PROG_MZX][i] = | |
+ glsl.glGetUniformBlockIndex(render_data->tilemap_program, ubo_name[i]); | |
+ gl_check_error(); | |
+ | |
+ glsl.glUniformBlockBinding(render_data->tilemap_program, | |
+ render_data->uidx[PROG_MZX][i], i); | |
+ gl_check_error(); | |
+ } | |
+ } | |
} | |
+ // FIXME use fragment shader for correct version. | |
render_data->tilemap_smzx_program = glsl_load_program(graphics, | |
- GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_SMZX_FRAG); | |
+ GLSL_SHADER_TILEMAP_VERT, GLSL_SHADER_TILEMAP_SMZX_31_FRAG); | |
if(render_data->tilemap_smzx_program) | |
{ | |
glsl.glBindAttribLocation(render_data->tilemap_smzx_program, | |
@@ -601,6 +697,27 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl.glLinkProgram(render_data->tilemap_smzx_program); | |
glsl_verify_link(render_data, render_data->tilemap_smzx_program); | |
glsl_delete_shaders(render_data->tilemap_smzx_program); | |
+ | |
+ if(glsl.has_ubo) | |
+ { | |
+ for(i = 0; i < NUM_UNIFORMS; i++) | |
+ { | |
+ render_data->uniforms[PROG_SMZX][i] = | |
+ glsl.glGetUniformLocation(render_data->tilemap_smzx_program, uniform_name[i]); | |
+ gl_check_error(); | |
+ } | |
+ | |
+ for(i = 0; i < NUM_UBOS; i++) | |
+ { | |
+ render_data->uidx[PROG_SMZX][i] = | |
+ glsl.glGetUniformBlockIndex(render_data->tilemap_smzx_program, ubo_name[i]); | |
+ gl_check_error(); | |
+ | |
+ glsl.glUniformBlockBinding(render_data->tilemap_smzx_program, | |
+ render_data->uidx[PROG_SMZX][i], i); | |
+ gl_check_error(); | |
+ } | |
+ } | |
} | |
render_data->mouse_program = glsl_load_program(graphics, | |
@@ -697,6 +814,12 @@ static void glsl_free_video(struct graphics_data *graphics) | |
gl_check_error(); | |
} | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glDeleteBuffers(NUM_UBOS, render_data->ubos); | |
+ gl_check_error(); | |
+ } | |
+ | |
glsl.glDeleteTextures(NUM_TEXTURES, render_data->textures); | |
gl_check_error(); | |
@@ -730,6 +853,7 @@ static void glsl_resize_screen(struct graphics_data *graphics, | |
int width, int height) | |
{ | |
struct glsl_render_data *render_data = graphics->render_data; | |
+ int i; | |
glsl.glViewport(0, 0, width, height); | |
gl_check_error(); | |
@@ -772,6 +896,28 @@ static void glsl_resize_screen(struct graphics_data *graphics, | |
GL_TEXTURE_2D, render_data->textures[TEX_SCREEN_ID], 0); | |
} | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glDeleteBuffers(NUM_UBOS, render_data->ubos); | |
+ gl_check_error(); | |
+ | |
+ glsl.glGenBuffers(NUM_UBOS, render_data->ubos); | |
+ gl_check_error(); | |
+ | |
+ for(i = 0; i < NUM_UBOS; i++) | |
+ { | |
+ glsl.glBindBuffer(GL_UNIFORM_BUFFER, render_data->ubos[i]); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBufferData(GL_UNIFORM_BUFFER, sizeof(render_data->ubo_data[i]), | |
+ render_data->ubo_data[i], GL_DYNAMIC_DRAW); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBindBufferBase(GL_UNIFORM_BUFFER, i, render_data->ubos[i]); | |
+ gl_check_error(); | |
+ } | |
+ } | |
+ | |
// Data texture | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
gl_check_error(); | |
@@ -806,6 +952,7 @@ static boolean glsl_set_video_mode(struct graphics_data *graphics, | |
int width, int height, int depth, boolean fullscreen, boolean resize) | |
{ | |
boolean load_fbo_syms = true; | |
+ boolean load_ubo_syms = false; // FIXME not supported by GLES 2 :( | |
gl_set_attributes(graphics); | |
@@ -846,11 +993,17 @@ static boolean glsl_set_video_mode(struct graphics_data *graphics, | |
} | |
load_fbo_syms = false; | |
+ load_ubo_syms = false; | |
if(version_float >= 3.0) | |
{ | |
debug("Attempting to load FBO syms...\n"); | |
load_fbo_syms = true; | |
} | |
+ if(version_float >= 3.1) | |
+ { | |
+ debug("Attempting to load UBO syms...\n"); | |
+ load_ubo_syms = true; | |
+ } | |
} | |
#endif | |
@@ -862,6 +1015,14 @@ static boolean glsl_set_video_mode(struct graphics_data *graphics, | |
else | |
glsl.has_fbo = false; | |
+ if(load_ubo_syms && gl_load_syms(glsl_syms_map_ubo)) | |
+ { | |
+ debug("Using UBO syms and shaders for GLSL renderer.\n"); | |
+ glsl.has_ubo = true; | |
+ } | |
+ else | |
+ glsl.has_ubo = false; | |
+ | |
#ifdef ENABLE_GL_DEBUG_OUTPUT | |
glsl.glEnable(GL_DEBUG_OUTPUT); | |
glsl.glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | |
@@ -887,7 +1048,8 @@ static boolean glsl_auto_set_video_mode(struct graphics_data *graphics, | |
renderer = (const char *)glsl.glGetString(GL_RENDERER); | |
// Print the full renderer string for reference. | |
- info("GL driver: %s\n\n", renderer); | |
+ info("GL driver: %s\n", renderer); | |
+ info("GL version: %s\n\n", (const char *)glsl.glGetString(GL_VERSION)); | |
for(i = 0; i < auto_glsl_blacklist_len; i++) | |
{ | |
@@ -1006,8 +1168,10 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
struct glsl_render_data *render_data = graphics->render_data; | |
struct char_element *src = layer->data; | |
Uint32 *colorptr, *dest, i, j; | |
+ float *ubo_char_x, *ubo_char_y, *ubo_color_fg, *ubo_color_bg; | |
int width, height; | |
Uint32 char_value, fg_color, bg_color; | |
+ Uint32 program; | |
int x1 = layer->x; | |
int x2 = layer->x + layer->w * CHAR_W; | |
@@ -1055,10 +1219,19 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
gl_check_error(); | |
if(layer->mode == 0) | |
+ { | |
glsl.glUseProgram(render_data->tilemap_program); | |
+ gl_check_error(); | |
+ | |
+ program = PROG_MZX; | |
+ } | |
else | |
+ { | |
glsl.glUseProgram(render_data->tilemap_smzx_program); | |
- gl_check_error(); | |
+ gl_check_error(); | |
+ | |
+ program = PROG_SMZX; | |
+ } | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
gl_check_error(); | |
@@ -1083,6 +1256,10 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
// Layer data | |
dest = render_data->background_texture; | |
+ ubo_char_x = render_data->ubo_data[UBO_CHAR_X]; | |
+ ubo_char_y = render_data->ubo_data[UBO_CHAR_Y]; | |
+ ubo_color_fg = render_data->ubo_data[UBO_COLOR_FG]; | |
+ ubo_color_bg = render_data->ubo_data[UBO_COLOR_BG]; | |
for(i = 0; i < layer->w * layer->h; i++, dest++, src++) | |
{ | |
@@ -1107,19 +1284,49 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
fg_color = FULL_PAL_SIZE; | |
} | |
- *dest = gl_pack_u32( | |
- (char_value << LAYER_CHAR_POS) | | |
- (bg_color << LAYER_BG_POS) | | |
- (fg_color << LAYER_FG_POS)); | |
+ if(glsl.has_ubo) | |
+ { | |
+ *(ubo_char_x++) = (char_value % CHARSET_COLS * CHAR_W) * 1.0f / (TEX_DATA_WIDTH * 1.0f); | |
+ *(ubo_char_y++) = (char_value / CHARSET_COLS * CHAR_H) * 1.0f / (TEX_DATA_HEIGHT * 1.0f); | |
+ *(ubo_color_fg++) = fg_color * 1.0f; | |
+ *(ubo_color_bg++) = bg_color * 1.0f; | |
+ } | |
+ else | |
+ { | |
+ *dest = gl_pack_u32( | |
+ (char_value << LAYER_CHAR_POS) | | |
+ (bg_color << LAYER_BG_POS) | | |
+ (fg_color << LAYER_FG_POS)); | |
+ } | |
} | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
gl_check_error(); | |
- glsl.glTexSubImage2D(GL_TEXTURE_2D, 0, | |
- TEX_DATA_LAYER_X, TEX_DATA_LAYER_Y, layer->w, layer->h, | |
- GL_RGBA, GL_UNSIGNED_BYTE, render_data->background_texture); | |
- gl_check_error(); | |
+ // Uniform buffers. | |
+ if(glsl.has_ubo) | |
+ { | |
+ glsl.glUniform4f(render_data->uniforms[program][U_TILEMAP_SIZE], | |
+ layer->w, layer->h, 0.0f, 0.0f); | |
+ gl_check_error(); | |
+ | |
+ for(i = 0; i < NUM_UBOS; i++) | |
+ { | |
+ glsl.glBindBuffer(GL_UNIFORM_BUFFER, render_data->ubos[i]); | |
+ gl_check_error(); | |
+ | |
+ glsl.glBufferSubData(GL_UNIFORM_BUFFER, 0, | |
+ layer->w * layer->h * sizeof(float), render_data->ubo_data[i]); | |
+ gl_check_error(); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ glsl.glTexSubImage2D(GL_TEXTURE_2D, 0, | |
+ TEX_DATA_LAYER_X, TEX_DATA_LAYER_Y, layer->w, layer->h, | |
+ GL_RGBA, GL_UNSIGNED_BYTE, render_data->background_texture); | |
+ gl_check_error(); | |
+ } | |
// Palette | |
if(render_data->dirty_palette || | |
diff --git a/src/util.c b/src/util.c | |
index f31b41f3..20994ee5 100644 | |
--- a/src/util.c | |
+++ b/src/util.c | |
@@ -81,6 +81,8 @@ static struct mzx_resource mzx_res[] = | |
{ GLSL_SHADERS "tilemap.vert", NULL, false, false }, | |
{ GLSL_SHADERS "tilemap.frag", NULL, false, false }, | |
{ GLSL_SHADERS "tilemap.smzx.frag", NULL, false, false }, | |
+ { GLSL_SHADERS "tilemap.31.frag", NULL, false, false }, | |
+ { GLSL_SHADERS "tilemap.smzx.31.frag",NULL, false, false }, | |
{ GLSL_SHADERS "mouse.vert", NULL, false, false }, | |
{ GLSL_SHADERS "mouse.frag", NULL, false, false }, | |
{ GLSL_SHADERS "cursor.vert", NULL, false, false }, | |
diff --git a/src/util.h b/src/util.h | |
index 25f92da9..7b6bbc18 100644 | |
--- a/src/util.h | |
+++ b/src/util.h | |
@@ -65,6 +65,8 @@ enum resource_id | |
GLSL_SHADER_TILEMAP_VERT, | |
GLSL_SHADER_TILEMAP_FRAG, | |
GLSL_SHADER_TILEMAP_SMZX_FRAG, | |
+ GLSL_SHADER_TILEMAP_31_FRAG, | |
+ GLSL_SHADER_TILEMAP_SMZX_31_FRAG, | |
GLSL_SHADER_MOUSE_VERT, | |
GLSL_SHADER_MOUSE_FRAG, | |
GLSL_SHADER_CURSOR_VERT, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/assets/glsl/tilemap.frag b/assets/glsl/tilemap.frag | |
index ef297986..637bdbad 100644 | |
--- a/assets/glsl/tilemap.frag | |
+++ b/assets/glsl/tilemap.frag | |
@@ -20,7 +20,7 @@ | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
-#version 110 | |
+#version 130 | |
// Keep these the same as in render_glsl.c | |
#define CHARSET_COLS 64.0 | |
@@ -37,6 +37,8 @@ | |
uniform sampler2D baseMap; | |
varying vec2 vTexcoord; | |
+flat in float vchr; | |
+flat in vec2 vcolor; | |
float fract_(float v) | |
{ | |
@@ -99,9 +101,9 @@ void main(void) | |
* Get the packed char/color data for this position from the current layer. | |
* vTexcoord will be provided in the range of x=[0..layer.w), y=[0..layer.h). | |
*/ | |
- float layer_x = (vTexcoord.x + TEX_DATA_LAYER_X) / TEX_DATA_WIDTH; | |
- float layer_y = (vTexcoord.y + TEX_DATA_LAYER_Y) / TEX_DATA_HEIGHT; | |
- vec4 layer_data = texture2D(baseMap, vec2(layer_x, layer_y)); | |
+ //float layer_x = (vTexcoord.x + TEX_DATA_LAYER_X) / TEX_DATA_WIDTH; | |
+ //float layer_y = (vTexcoord.y + TEX_DATA_LAYER_Y) / TEX_DATA_HEIGHT; | |
+ //vec4 layer_data = texture2D(baseMap, vec2(layer_x, layer_y)); | |
/** | |
* Get the current char and its base position in the texture charset. | |
@@ -109,9 +111,9 @@ void main(void) | |
* but for the y position it's easier to get the pixel position and | |
* normalize afterward. | |
*/ | |
- float char_num = layer_get_char(layer_data); | |
- float char_x = fract_(char_num / CHARSET_COLS); | |
- float char_y = floor_(char_num / CHARSET_COLS); | |
+ //float char_num = layer_get_char(layer_data); | |
+ float char_x = fract_(vchr / CHARSET_COLS); | |
+ float char_y = floor_(vchr / CHARSET_COLS); | |
/** | |
* Get the current pixel value of the current char from the texture. | |
@@ -127,14 +129,17 @@ void main(void) | |
float color; | |
// We could actually check any component here. | |
- if(char_pix.x > 0.5) | |
+ color = vcolor[int_(char_pix.x + 0.5)]; | |
+ /*if(char_pix.x > 0.5) | |
{ | |
- color = layer_get_fg_color(layer_data); | |
+ //color = layer_get_fg_color(layer_data); | |
+ color = vcolor.x; | |
} | |
else | |
{ | |
- color = layer_get_bg_color(layer_data); | |
- } | |
+ //color = layer_get_bg_color(layer_data); | |
+ color = vcolor.y; | |
+ }*/ | |
gl_FragColor = texture2D(baseMap, | |
vec2(color, TEX_DATA_PAL_Y / TEX_DATA_HEIGHT)); | |
diff --git a/assets/glsl/tilemap.smzx.frag b/assets/glsl/tilemap.smzx.frag | |
index 234be7ec..8073b4c9 100644 | |
--- a/assets/glsl/tilemap.smzx.frag | |
+++ b/assets/glsl/tilemap.smzx.frag | |
@@ -20,11 +20,13 @@ | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
-#version 110 | |
+#version 130 | |
uniform sampler2D baseMap; | |
varying vec2 vTexcoord; | |
+flat in float chr; | |
+flat in vec2 color; | |
// Keep these the same as in render_glsl.c | |
#define CHARSET_COLS 64.0 | |
diff --git a/assets/glsl/tilemap.vert b/assets/glsl/tilemap.vert | |
index 1e67a545..5690a504 100644 | |
--- a/assets/glsl/tilemap.vert | |
+++ b/assets/glsl/tilemap.vert | |
@@ -19,15 +19,107 @@ | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
-#version 110 | |
+#version 130 | |
+// Keep these the same as in render_glsl.c | |
+#define CHARSET_COLS 64.0 | |
+#define TEX_DATA_WIDTH 512.0 | |
+#define TEX_DATA_HEIGHT 1024.0 | |
+#define TEX_DATA_PAL_Y 896.0 | |
+#define TEX_DATA_LAYER_X 0.0 | |
+#define TEX_DATA_LAYER_Y 901.0 | |
+ | |
+// This has to be slightly less than 14.0 to avoid propagating error | |
+// with some very old driver/video card combos. | |
+#define CHAR_H 13.99999 | |
+ | |
+uniform sampler2D baseMap; | |
attribute vec2 Position; | |
-attribute vec2 Texcoord; | |
+//attribute vec2 Texcoord; | |
+ | |
+uniform vec2 layer_size; | |
+uniform vec2 screen_xy; | |
+uniform vec2 screen_size; | |
varying vec2 vTexcoord; | |
+flat out float vchr; | |
+flat out vec2 vcolor; | |
+ | |
+float fract_(float v) | |
+{ | |
+ return clamp(fract(v + 0.001) - 0.001, 0.000, 0.999); | |
+} | |
+ | |
+float floor_(float v) | |
+{ | |
+ return floor(v + 0.001); | |
+} | |
+ | |
+int int_(float v) | |
+{ | |
+ return int(v + 0.01); | |
+} | |
+ | |
+// NOTE: Layer data packing scheme | |
+// (highest two bits currently unused but included as part of the char) | |
+// w z y x | |
+// 00000000 00000000 00000000 00000000 | |
+// CCCCCCCC CCCCCCBB BBBBBBBF FFFFFFFF | |
+ | |
+// Some older cards/drivers tend o be slightly off; slight variations | |
+// in values here are intentional. | |
+ | |
+/** | |
+ * Get the char number from packed layer data as (approx.) an int. | |
+ */ | |
+ | |
+float layer_get_char(vec4 layer_data) | |
+{ | |
+ return floor_(layer_data.z * 63.75) + (layer_data.w * 255.0) * 64.0; | |
+} | |
+ | |
+/** | |
+ * Get the foreground color from layer data relative to the texture width. | |
+ */ | |
+ | |
+float layer_get_fg_color(vec4 layer_data) | |
+{ | |
+ return | |
+ (layer_data.x * 255.001) / TEX_DATA_WIDTH + | |
+ fract_(layer_data.y * 127.501) * 512.0 / TEX_DATA_WIDTH; | |
+} | |
+ | |
+/** | |
+ * Get the background color from layer data relative to the texture width. | |
+ */ | |
+ | |
+float layer_get_bg_color(vec4 layer_data) | |
+{ | |
+ return | |
+ floor_(layer_data.y * 127.5) / TEX_DATA_WIDTH + | |
+ fract_(layer_data.z * 63.751) * 512.0 / TEX_DATA_WIDTH; | |
+} | |
void main(void) | |
{ | |
gl_Position = vec4(Position.x, Position.y, 0.0, 1.0); | |
- vTexcoord = Texcoord; | |
+ //vTexcoord = Texcoord; | |
+ | |
+ /** | |
+ * Get the position of the current char relative to the layer. The provoking | |
+ * vertex will always be the top-left corner of this char. | |
+ */ | |
+ vTexcoord.x = floor_((Position.x - screen_xy.x) * layer_size.x / screen_size.x); | |
+ vTexcoord.y = floor_((screen_xy.y - Position.y) * layer_size.y / screen_size.y); | |
+ | |
+ /** | |
+ * Unpack char/color data for this position from the current layer. | |
+ */ | |
+ float layer_x = (vTexcoord.x + TEX_DATA_LAYER_X) / TEX_DATA_WIDTH; | |
+ float layer_y = (vTexcoord.y + TEX_DATA_LAYER_Y) / TEX_DATA_HEIGHT; | |
+ vec4 layer_data = texture2D(baseMap, vec2(layer_x, layer_y)); | |
+ | |
+ vchr = layer_get_char(layer_data); | |
+ vcolor[0] = layer_get_bg_color(layer_data); | |
+ vcolor[1] = layer_get_fg_color(layer_data); | |
} | |
diff --git a/src/render_glsl.c b/src/render_glsl.c | |
index 64b1e03c..0a5bdd6d 100644 | |
--- a/src/render_glsl.c | |
+++ b/src/render_glsl.c | |
@@ -207,6 +207,8 @@ static struct | |
void (GL_APIENTRY *glDeleteProgram)(GLuint program); | |
void (GL_APIENTRY *glGetAttachedShaders)(GLuint program, GLsizei maxCount, | |
GLsizei *count, GLuint *shaders); | |
+ GLint (GL_APIENTRY *glGetUniformLocation)(GLuint program, const char *name); | |
+ void (GL_APIENTRY *glUniform2f)(GLint location, GLfloat v0, GLfloat v1); | |
// FBO functions are optional for GL (requires 3.0+), mandatory for GLES. | |
boolean has_fbo; | |
@@ -245,11 +247,13 @@ static const struct dso_syms_map glsl_syms_map[] = | |
{ "glGetShaderInfoLog", (fn_ptr *)&glsl.glGetShaderInfoLog }, | |
{ "glGetShaderiv", (fn_ptr *)&glsl.glGetShaderiv }, | |
{ "glGetString", (fn_ptr *)&glsl.glGetString }, | |
+ { "glGetUniformLocation", (fn_ptr *)&glsl.glGetUniformLocation }, | |
{ "glLinkProgram", (fn_ptr *)&glsl.glLinkProgram }, | |
{ "glShaderSource", (fn_ptr *)&glsl.glShaderSource }, | |
{ "glTexImage2D", (fn_ptr *)&glsl.glTexImage2D }, | |
{ "glTexParameterf", (fn_ptr *)&glsl.glTexParameterf }, | |
{ "glTexSubImage2D", (fn_ptr *)&glsl.glTexSubImage2D }, | |
+ { "glUniform2f", (fn_ptr *)&glsl.glUniform2f }, | |
{ "glUseProgram", (fn_ptr *)&glsl.glUseProgram }, | |
{ "glVertexAttribPointer", (fn_ptr *)&glsl.glVertexAttribPointer }, | |
{ "glViewport", (fn_ptr *)&glsl.glViewport }, | |
@@ -288,6 +292,15 @@ struct glsl_render_data | |
GLuint tilemap_smzx_program; | |
GLuint mouse_program; | |
GLuint cursor_program; | |
+ GLint u_layer_size; | |
+ GLint u_screen_xy; | |
+ GLint u_screen_size; | |
+ GLint u_smzx_layer_size; | |
+ GLint u_smzx_screen_xy; | |
+ GLint u_smzx_screen_size; | |
+ float *vertex_array; | |
+ float *texcoord_array; | |
+ int vertex_array_allocated; | |
struct config_info *conf; | |
}; | |
@@ -573,6 +586,13 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl.glLinkProgram(render_data->tilemap_program); | |
glsl_verify_link(render_data, render_data->tilemap_program); | |
glsl_delete_shaders(render_data->tilemap_program); | |
+ | |
+ render_data->u_layer_size = glsl.glGetUniformLocation(render_data->tilemap_program, "layer_size"); | |
+ gl_check_error(); | |
+ render_data->u_screen_xy = glsl.glGetUniformLocation(render_data->tilemap_program, "screen_xy"); | |
+ gl_check_error(); | |
+ render_data->u_screen_size = glsl.glGetUniformLocation(render_data->tilemap_program, "screen_size"); | |
+ gl_check_error(); | |
} | |
render_data->tilemap_smzx_program = glsl_load_program(graphics, | |
@@ -586,6 +606,13 @@ static void glsl_load_shaders(struct graphics_data *graphics) | |
glsl.glLinkProgram(render_data->tilemap_smzx_program); | |
glsl_verify_link(render_data, render_data->tilemap_smzx_program); | |
glsl_delete_shaders(render_data->tilemap_smzx_program); | |
+ | |
+ render_data->u_smzx_layer_size = glsl.glGetUniformLocation(render_data->tilemap_smzx_program, "layer_size"); | |
+ gl_check_error(); | |
+ render_data->u_smzx_screen_xy = glsl.glGetUniformLocation(render_data->tilemap_smzx_program, "screen_xy"); | |
+ gl_check_error(); | |
+ render_data->u_smzx_screen_size = glsl.glGetUniformLocation(render_data->tilemap_smzx_program, "screen_size"); | |
+ gl_check_error(); | |
} | |
render_data->mouse_program = glsl_load_program(graphics, | |
@@ -690,6 +717,8 @@ static void glsl_free_video(struct graphics_data *graphics) | |
gl_cleanup(graphics); | |
free(render_data->pixels); | |
+ free(render_data->vertex_array); | |
+ free(render_data->texcoord_array); | |
free(render_data); | |
graphics->render_data = NULL; | |
} | |
@@ -987,6 +1016,10 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
float v_right = 1.0f * x2 / SCREEN_PIX_W_F * 2.0f - 1.0f; | |
float v_top = 1.0f * y1 / SCREEN_PIX_H_F * 2.0f - 1.0f; | |
float v_bottom = 1.0f * y2 / SCREEN_PIX_H_F * 2.0f - 1.0f; | |
+ float *vertex_array; | |
+ float *texcoord_array; | |
+ int vertices; | |
+ Uint32 x, y; | |
float vertex_array_single[2 * 4] = | |
{ | |
@@ -1004,6 +1037,52 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
layer->w, layer->h, | |
}; | |
+ // Set up the vertex array. | |
+ vertices = 6 * layer->w * layer->h; | |
+ if(render_data->vertex_array_allocated < vertices) | |
+ { | |
+ render_data->vertex_array = crealloc(render_data->vertex_array, vertices * 2 * sizeof(float)); | |
+ //render_data->texcoord_array = crealloc(render_data->texcoord_array, vertices * 2 * sizeof(float)); | |
+ render_data->vertex_array_allocated = vertices; | |
+ } | |
+ vertex_array = render_data->vertex_array; | |
+ //texcoord_array = render_data->texcoord_array; | |
+ i = 0; | |
+ //j = 0; | |
+ for(y = 0; y < layer->h; y++) | |
+ { | |
+ for(x = 0; x < layer->w; x++) | |
+ { | |
+#define CHAR_W_F (1.0f * CHAR_W / SCREEN_PIX_W_F * 2.0f) | |
+#define CHAR_H_F (1.0f * CHAR_H / SCREEN_PIX_H_F * 2.0f) | |
+ vertex_array[i++] = CHAR_W_F * x + v_left; | |
+ vertex_array[i++] = -CHAR_H_F * y - v_top; | |
+ vertex_array[i++] = CHAR_W_F * x + v_left; | |
+ vertex_array[i++] = -CHAR_H_F * (y+1) - v_top; | |
+ vertex_array[i++] = CHAR_W_F * (x+1) + v_left; | |
+ vertex_array[i++] = -CHAR_H_F * (y+1) - v_top; | |
+ vertex_array[i++] = CHAR_W_F * x + v_left; | |
+ vertex_array[i++] = -CHAR_H_F * y - v_top; | |
+ vertex_array[i++] = CHAR_W_F * (x+1) + v_left; | |
+ vertex_array[i++] = -CHAR_H_F * y - v_top; | |
+ vertex_array[i++] = CHAR_W_F * (x+1) + v_left; | |
+ vertex_array[i++] = -CHAR_H_F * (y+1) - v_top; | |
+ /* | |
+ texcoord_array[j++] = x; | |
+ texcoord_array[j++] = y; | |
+ texcoord_array[j++] = x; | |
+ texcoord_array[j++] = y+1; | |
+ texcoord_array[j++] = x+1; | |
+ texcoord_array[j++] = y+1; | |
+ texcoord_array[j++] = x; | |
+ texcoord_array[j++] = y; | |
+ texcoord_array[j++] = x+1; | |
+ texcoord_array[j++] = y; | |
+ texcoord_array[j++] = x+1; | |
+ texcoord_array[j++] = y+1;*/ | |
+ } | |
+ } | |
+ | |
// Clamp draw area to size of screen texture. | |
get_context_width_height(graphics, &width, &height); | |
if(width < SCREEN_PIX_W || height < SCREEN_PIX_H) | |
@@ -1024,9 +1103,21 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
gl_check_error(); | |
if(layer->mode == 0) | |
+ { | |
glsl.glUseProgram(render_data->tilemap_program); | |
+ gl_check_error(); | |
+ glsl.glUniform2f(render_data->u_layer_size, layer->w, layer->h); | |
+ glsl.glUniform2f(render_data->u_screen_xy, v_left, -v_top); | |
+ glsl.glUniform2f(render_data->u_screen_size, v_right - v_left, v_bottom - v_top); | |
+ } | |
else | |
+ { | |
glsl.glUseProgram(render_data->tilemap_smzx_program); | |
+ gl_check_error(); | |
+ glsl.glUniform2f(render_data->u_smzx_layer_size, layer->w, layer->h); | |
+ glsl.glUniform2f(render_data->u_smzx_screen_xy, v_left, -v_top); | |
+ glsl.glUniform2f(render_data->u_smzx_screen_size, v_right - v_left, v_bottom - v_top); | |
+ } | |
gl_check_error(); | |
glsl.glBindTexture(GL_TEXTURE_2D, render_data->textures[TEX_DATA_ID]); | |
@@ -1118,24 +1209,25 @@ static void glsl_render_layer(struct graphics_data *graphics, | |
gl_check_error(); | |
glsl.glEnableVertexAttribArray(ATTRIB_POSITION); | |
- glsl.glEnableVertexAttribArray(ATTRIB_TEXCOORD); | |
+ //glsl.glEnableVertexAttribArray(ATTRIB_TEXCOORD); | |
glsl.glEnable(GL_BLEND); | |
glsl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
glsl.glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, | |
- vertex_array_single); | |
+ vertex_array);//vertex_array_single); | |
gl_check_error(); | |
- | |
+/* | |
glsl.glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, | |
- tex_coord_array_single); | |
+ texcoord_array);//tex_coord_array_single); | |
gl_check_error(); | |
- | |
- glsl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
+*/ | |
+ glsl.glDrawArrays(GL_TRIANGLES, 0, vertices); | |
+ //glsl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
gl_check_error(); | |
glsl.glDisableVertexAttribArray(ATTRIB_POSITION); | |
- glsl.glDisableVertexAttribArray(ATTRIB_TEXCOORD); | |
+ //glsl.glDisableVertexAttribArray(ATTRIB_TEXCOORD); | |
glsl.glDisable(GL_BLEND); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment