Fix textures being internally Y-flipped (#142)
* WIP: upload textures with the bottom-left-origin convention, as OpenGL expects * unflip: fix spellcard_walloftext, text_hud * unflip: fix reimu's and marisa's bombs * unflip: fix stagetext * unflip: fix graph.frag.glsl * fix sprite_circleclipped_indicator
This commit is contained in:
parent
4e9ec77c91
commit
e4f49310ff
19 changed files with 159 additions and 48 deletions
|
@ -29,9 +29,9 @@ float get_sample(float x) {
|
|||
|
||||
void main(void) {
|
||||
vec4 c = vec4(1.0);
|
||||
vec2 coord = vec2(texCoord.x, 1.0 - texCoord.y); // TODO: move to vertex shader
|
||||
vec2 coord = flip_native_to_bottomleft(texCoord); // TODO: move to vertex shader
|
||||
float s = get_sample(coord.x);
|
||||
|
||||
|
||||
c.a = float(coord.y <= s);
|
||||
c.a *= (0.2 + 0.8 * s);
|
||||
c.a = 0.05 + 0.95 * c.a;
|
||||
|
|
|
@ -29,4 +29,8 @@
|
|||
#define ATTRIBUTE(l) LOC(l) in
|
||||
#endif
|
||||
|
||||
#if !defined(NATIVE_ORIGIN_TOPLEFT) && !defined(NATIVE_ORIGIN_BOTTOMLEFT)
|
||||
#define NATIVE_ORIGIN_BOTTOMLEFT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,4 +77,56 @@ vec3 hsv2rgb(vec3 c) {
|
|||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
float flip_topleft_to_native(float x) {
|
||||
#ifdef NATIVE_ORIGIN_BOTTOMLEFT
|
||||
return 1 - x;
|
||||
#else
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2 flip_topleft_to_native(vec2 v) {
|
||||
v.y = flip_topleft_to_native(v.y);
|
||||
return v;
|
||||
}
|
||||
|
||||
float flip_bottomleft_to_native(float x) {
|
||||
#ifdef NATIVE_ORIGIN_TOPLEFT
|
||||
return 1 - x;
|
||||
#else
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2 flip_bottomleft_to_native(vec2 v) {
|
||||
v.y = flip_bottomleft_to_native(v.y);
|
||||
return v;
|
||||
}
|
||||
|
||||
float flip_native_to_topleft(float x) {
|
||||
#ifdef NATIVE_ORIGIN_TOPLEFT
|
||||
return x;
|
||||
#else
|
||||
return 1 - x;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2 flip_native_to_topleft(vec2 v) {
|
||||
v.y = flip_native_to_topleft(v.y);
|
||||
return v;
|
||||
}
|
||||
|
||||
float flip_native_to_bottomleft(float x) {
|
||||
#ifdef NATIVE_ORIGIN_BOTTOMLEFT
|
||||
return x;
|
||||
#else
|
||||
return 1 - x;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2 flip_native_to_bottomleft(vec2 v) {
|
||||
v.y = flip_native_to_bottomleft(v.y);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,14 +12,14 @@ void main(void) {
|
|||
// This thing is supposed to produce a swirly texture centered
|
||||
// around plrpos. To do it we have to map to polar coordinates
|
||||
|
||||
vec2 x = texCoordRaw-plrpos;
|
||||
vec2 x = flip_native_to_topleft(texCoordRaw) - plrpos;
|
||||
float r = length(x) - 2 * t * (1 + decay *t);
|
||||
float phi = atan(x.y, x.x) / pi * 4;
|
||||
|
||||
// give the angle some juicy r dependent offset to twist the swirl.
|
||||
phi += (1 + r) * t * 5 * decay;
|
||||
|
||||
vec4 texel = texture(tex, vec2(phi,r));
|
||||
vec4 texel = texture(tex, vec2(phi, flip_topleft_to_native(r)));
|
||||
|
||||
float fade = 0.7 * min(1,t) * (1 - t * decay) * 4;
|
||||
fragColor = texel * r_color * fade;
|
||||
|
|
|
@ -12,7 +12,7 @@ float smootherstep(float x, float width) {
|
|||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 r = vec2(texCoord.x - 0.5, 1.0 - texCoord.y);
|
||||
vec2 r = vec2(texCoord.x - 0.5, flip_native_to_bottomleft(texCoord.y));
|
||||
|
||||
// globally distort the coordinate system a little bit for a more interesting/dynamic shape
|
||||
r.x -= 0.005 * sin(r.y * 13.32 - t * 0.53);
|
||||
|
|
|
@ -67,7 +67,7 @@ void main(void) {
|
|||
vec2 uv = texCoord;
|
||||
float ld, dd;
|
||||
|
||||
float yy = yinyang_spin(uv, aspect * zoom, -time, ld, dd);
|
||||
float yy = yinyang_spin(flip_native_to_topleft(uv), aspect * zoom, -time, ld, dd);
|
||||
|
||||
vec2 uv_r = uv;
|
||||
vec2 uv_g = uv;
|
||||
|
@ -115,10 +115,10 @@ void main(void) {
|
|||
vec2 runes_uv = (uv - 0.5) * rot(pi * 0.5) + 0.5;
|
||||
float line = floor(runes_uv.y * rune_lines);
|
||||
runes_uv.x += 0.931223 * line + time * 0.1 * cos(pi * line);
|
||||
runes_uv.y *= -rune_lines;
|
||||
runes_uv.y *= rune_lines;
|
||||
runes_uv = runes_transform_uv(runes_uv);
|
||||
|
||||
float rune_factor = texture(runes, runes_uv).r;
|
||||
float rune_factor = texture(runes, flip_bottomleft_to_native(runes_uv)).r;
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1 + (1 - 2 * rune_factor) * 0.1));
|
||||
// fragColor = mix(fragColor, 0.9 * fragColor + vec4(0.1), rune_factor * r_color);
|
||||
fragColor += r_color * rune_factor * 0.1;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
void main(void) {
|
||||
float n = 10; // rough number of rings of text
|
||||
|
||||
vec2 pos = (vec2(texCoordRaw) - origin * vec2(ratio, 1.0)) * n;
|
||||
vec2 pos = (vec2(flip_native_to_topleft(texCoordRaw)) - origin * vec2(ratio, 1.0)) * n;
|
||||
pos.x /= ratio;
|
||||
|
||||
// Slightly distorted mapping to polar coordinates. I wrote this
|
||||
// shortly after hearing a general relativity lecture...
|
||||
|
||||
pos = vec2(atan(pos.x,pos.y), length(pos) + n * t * 0.1);
|
||||
|
||||
pos = vec2(atan(pos.x, pos.y), length(pos) + n * t * 0.1);
|
||||
|
||||
// The idea is (apart from the aspect factors) to map the
|
||||
// (phi, angle) coordinates to something that loops several
|
||||
|
@ -22,14 +22,15 @@ void main(void) {
|
|||
// Simplified example:
|
||||
// f(x) = x for 0 < x < 2
|
||||
// mod(f(x),1) then goes from 0 to 1 and from 0 to 1 again.
|
||||
//
|
||||
//
|
||||
// If you use it as a texcoord you get two copies of the texture.
|
||||
//
|
||||
// The complicated example I don’t understand either:
|
||||
|
||||
|
||||
pos.x *= h/w;
|
||||
pos.x += t * 0.5 * float(2 * int(mod(pos.y, 2)) - 1);
|
||||
pos = mod(pos, vec2(1 + 0.01 / w, 1));
|
||||
pos = flip_topleft_to_native(pos);
|
||||
pos *= vec2(w,h);
|
||||
|
||||
vec4 texel = texture(tex, pos);
|
||||
|
|
|
@ -7,9 +7,8 @@ UNIFORM(1) vec4 back_color;
|
|||
|
||||
void main(void) {
|
||||
float fill = customParams.r;
|
||||
vec2 tc = texCoord;
|
||||
vec4 texel = texture(tex, tc);
|
||||
tc = texCoordRaw - vec2(0.5);
|
||||
texel *= mix(back_color, color, float(atan(tc.x,-tc.y) < pi*(2.0*fill-1.0)));
|
||||
vec4 texel = texture(tex, texCoord);
|
||||
vec2 tc = flip_native_to_bottomleft(texCoordRaw) - vec2(0.5);
|
||||
texel *= mix(back_color, color, float(atan(tc.x, tc.y) < pi*(2.0*fill-1.0)));
|
||||
fragColor = texel;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#version 330 core
|
||||
|
||||
#include "lib/render_context.glslh"
|
||||
#include "lib/util.glslh"
|
||||
#include "interface/sprite.glslh"
|
||||
|
||||
void main(void) {
|
||||
vec4 texel = texture(tex, texCoord);
|
||||
float gradient = mix(1.0, 0.8, texCoordOverlay.y);
|
||||
float gradient = 0.8 + 0.2 * flip_native_to_bottomleft(texCoordOverlay.y);
|
||||
fragColor = color * texel.r * gradient;
|
||||
fragColor.rgb *= gradient;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ float tc_mask(vec2 tc) {
|
|||
|
||||
void main(void) {
|
||||
float t = customParams.r;
|
||||
vec2 tc = texCoord;
|
||||
vec2 tc = flip_native_to_topleft(texCoord);
|
||||
vec2 tc_overlay = texCoordOverlay;
|
||||
|
||||
tc *= dimensions;
|
||||
|
@ -19,12 +19,12 @@ void main(void) {
|
|||
tc /= dimensions;
|
||||
|
||||
float a = tc_mask(tc);
|
||||
vec4 textfrag = color * texture(tex, uv_to_region(texRegion, tc)).r * a;
|
||||
vec4 textfrag = color * texture(tex, uv_to_region(texRegion, flip_topleft_to_native(tc))).r * a;
|
||||
|
||||
tc -= vec2(1) / dimensions;
|
||||
a = tc_mask(tc);
|
||||
|
||||
vec4 shadowfrag = vec4(vec3(0), color.a) * texture(tex, uv_to_region(texRegion, tc)).r * a;
|
||||
vec4 shadowfrag = vec4(vec3(0), color.a) * texture(tex, uv_to_region(texRegion, flip_topleft_to_native(tc))).r * a;
|
||||
|
||||
fragColor = textfrag;
|
||||
fragColor = mix(shadowfrag, textfrag, sqrt(textfrag.a));
|
||||
|
|
|
@ -22,6 +22,7 @@ typedef enum RendererFeature {
|
|||
RFEAT_DRAW_INSTANCED_BASE_INSTANCE,
|
||||
RFEAT_DEPTH_TEXTURE,
|
||||
RFEAT_FRAMEBUFFER_MULTIPLE_OUTPUTS,
|
||||
RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN,
|
||||
|
||||
NUM_RFEATS,
|
||||
} RendererFeature;
|
||||
|
|
|
@ -26,10 +26,10 @@ void _r_models_init(void) {
|
|||
}, fmt, 0);
|
||||
|
||||
GenericModelVertex quad[4] = {
|
||||
{ { -0.5, -0.5, 0.0 }, { 0, 0, 1 }, { 0, 0 } },
|
||||
{ { -0.5, 0.5, 0.0 }, { 0, 0, 1 }, { 0, 1 } },
|
||||
{ { 0.5, 0.5, 0.0 }, { 0, 0, 1 }, { 1, 1 } },
|
||||
{ { 0.5, -0.5, 0.0 }, { 0, 0, 1 }, { 1, 0 } },
|
||||
{ { -0.5, -0.5, 0.0 }, { 0, 0, 1 }, { 0, 1 } },
|
||||
{ { -0.5, 0.5, 0.0 }, { 0, 0, 1 }, { 0, 0 } },
|
||||
{ { 0.5, 0.5, 0.0 }, { 0, 0, 1 }, { 1, 0 } },
|
||||
{ { 0.5, -0.5, 0.0 }, { 0, 0, 1 }, { 1, 1 } },
|
||||
};
|
||||
|
||||
r_vertex_buffer_create(&_r_models.vbuf, 8192 * sizeof(GenericModelVertex), NULL);
|
||||
|
@ -72,11 +72,6 @@ void r_draw_quad_instanced(uint instances) {
|
|||
void r_draw_model_ptr(Model *model) {
|
||||
VertexArray *varr_saved = r_vertex_array_current();
|
||||
r_vertex_array(&_r_models.varr);
|
||||
r_mat_mode(MM_TEXTURE);
|
||||
r_mat_push();
|
||||
r_mat_scale(1, -1, 1); // XXX: flipped texture workaround. can we get rid of this somehow?
|
||||
r_draw(PRIM_TRIANGLES, 0, model->icount, model->indices, 0, 0);
|
||||
r_mat_pop();
|
||||
r_mat_mode(MM_MODELVIEW);
|
||||
r_vertex_array(varr_saved);
|
||||
}
|
||||
|
|
|
@ -240,6 +240,8 @@ static void gl33_init_context(SDL_Window *window) {
|
|||
if(glext.draw_buffers) {
|
||||
R.features |= r_feature_bit(RFEAT_FRAMEBUFFER_MULTIPLE_OUTPUTS);
|
||||
}
|
||||
|
||||
R.features |= r_feature_bit(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN);
|
||||
}
|
||||
|
||||
static void gl33_apply_capability(RendererCapability cap, bool value) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "font.h"
|
||||
#include "util.h"
|
||||
#include "util/rectpack.h"
|
||||
#include "util/graphics.h"
|
||||
#include "config.h"
|
||||
#include "video.h"
|
||||
#include "events.h"
|
||||
|
@ -375,15 +376,30 @@ static bool add_glyph_to_spritesheet(Font *font, Glyph *glyph, FT_Bitmap bitmap,
|
|||
sprite_pos.bottom_right += ofs;
|
||||
sprite_pos.top_left += ofs;
|
||||
|
||||
r_texture_fill_region(
|
||||
&ss->tex,
|
||||
0,
|
||||
rect_x(sprite_pos),
|
||||
rect_y(sprite_pos),
|
||||
bitmap.width,
|
||||
bitmap.rows,
|
||||
bitmap.buffer
|
||||
);
|
||||
if(r_supports(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN)) {
|
||||
char buffer[bitmap.width * bitmap.rows];
|
||||
flip_bitmap_copy(buffer, (char*)bitmap.buffer, bitmap.rows, bitmap.width);
|
||||
r_texture_fill_region(
|
||||
&ss->tex,
|
||||
0,
|
||||
rect_x(sprite_pos),
|
||||
rect_y(sprite_pos),
|
||||
bitmap.width,
|
||||
bitmap.rows,
|
||||
buffer
|
||||
);
|
||||
} else {
|
||||
r_texture_fill_region(
|
||||
&ss->tex,
|
||||
0,
|
||||
rect_x(sprite_pos),
|
||||
rect_y(sprite_pos),
|
||||
bitmap.width,
|
||||
bitmap.rows,
|
||||
bitmap.buffer
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
glyph->sprite.tex = &ss->tex;
|
||||
glyph->sprite.w = glyph->metrics.width; // bitmap.width / font->scale;
|
||||
|
@ -862,6 +878,15 @@ static double _text_draw(Font *font, const char *text, const TextParams *params)
|
|||
r_mat_scale(1/bbox_w, 1/bbox_h, 1.0);
|
||||
r_mat_translate(-bbox.x.min - (x - x_orig), -bbox.y.min + font->metrics.descent, 0);
|
||||
|
||||
// FIXME: is there a better way?
|
||||
float texmat_offset_sign;
|
||||
|
||||
if(r_supports(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN)) {
|
||||
texmat_offset_sign = -1;
|
||||
} else {
|
||||
texmat_offset_sign = 1;
|
||||
}
|
||||
|
||||
bool keming = FT_HAS_KERNING(font->face);
|
||||
uint prev_glyph_idx = 0;
|
||||
const char *tptr = text;
|
||||
|
@ -899,7 +924,7 @@ static double _text_draw(Font *font, const char *text, const TextParams *params)
|
|||
sp.scale.both = font->metrics.scale;
|
||||
|
||||
r_mat_push();
|
||||
r_mat_translate(sp.pos.x - x_orig, sp.pos.y, 0);
|
||||
r_mat_translate(sp.pos.x - x_orig, sp.pos.y * texmat_offset_sign, 0);
|
||||
r_mat_scale(w_saved, h_saved, 1.0);
|
||||
r_mat_translate(-0.5, -0.5, 0);
|
||||
|
||||
|
@ -981,7 +1006,7 @@ void text_render(const char *text, Font *font, Sprite *out_sprite, BBox *out_bbo
|
|||
|
||||
r_blend(BLEND_PREMUL_ALPHA);
|
||||
r_enable(RCAP_CULL_FACE);
|
||||
r_cull(CULL_FRONT);
|
||||
r_cull(CULL_BACK);
|
||||
r_disable(RCAP_DEPTH_TEST);
|
||||
|
||||
r_mat_mode(MM_MODELVIEW);
|
||||
|
@ -991,8 +1016,7 @@ void text_render(const char *text, Font *font, Sprite *out_sprite, BBox *out_bbo
|
|||
r_mat_mode(MM_PROJECTION);
|
||||
r_mat_push();
|
||||
r_mat_identity();
|
||||
// XXX: y-flipped because that's how our textures are...
|
||||
r_mat_ortho(0, tex->w, 0, tex->h, -100, 100);
|
||||
r_mat_ortho(0, tex->w, tex->h, 0, -100, 100);
|
||||
|
||||
r_mat_mode(MM_TEXTURE);
|
||||
r_mat_push();
|
||||
|
|
|
@ -131,6 +131,11 @@ void* load_sprite_end(void *opaque, const char *path, uint flags) {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: is there a better way?
|
||||
if(r_supports(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN)) {
|
||||
spr->tex_area.y = tex_h_flt - spr->tex_area.y - spr->tex_area.h;
|
||||
}
|
||||
|
||||
free(basename);
|
||||
return spr;
|
||||
}
|
||||
|
|
|
@ -292,6 +292,12 @@ static void* load_texture_begin(const char *path, uint flags) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if(r_supports(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN)) {
|
||||
SDL_LockSurface(converted_surf);
|
||||
flip_bitmap(converted_surf->pixels, converted_surf->h, converted_surf->w * 4);
|
||||
SDL_UnlockSurface(converted_surf);
|
||||
}
|
||||
|
||||
if(ld.params.mipmaps == 0) {
|
||||
ld.params.mipmaps = TEX_MIPMAPS_MAX;
|
||||
}
|
||||
|
@ -334,7 +340,6 @@ static void texture_post_load(Texture *tex) {
|
|||
r_mat_mode(MM_MODELVIEW);
|
||||
r_mat_scale(tex->w, tex->h, 1);
|
||||
r_mat_translate(0.5, 0.5, 0);
|
||||
r_mat_scale(1, -1, 1);
|
||||
r_framebuffer_create(&fb);
|
||||
r_framebuffer_attach(&fb, &fbo_tex, 0, FRAMEBUFFER_ATTACH_COLOR0);
|
||||
r_framebuffer_viewport(&fb, 0, 0, tex->w, tex->h);
|
||||
|
|
|
@ -410,7 +410,11 @@ static void draw_wall_of_text(float f, const char *txt) {
|
|||
Sprite spr;
|
||||
BBox bbox;
|
||||
|
||||
text_render(txt, get_font("standard"), &spr, &bbox);
|
||||
char buf[strlen(txt) + 4];
|
||||
memcpy(buf, txt, sizeof(buf) - 4);
|
||||
memcpy(buf + sizeof(buf) - 4, " ~ ", 4);
|
||||
|
||||
text_render(buf, get_font("standard"), &spr, &bbox);
|
||||
|
||||
// FIXME: The shader currently assumes that the sprite takes up the entire texture.
|
||||
// If it could handle any arbitrary sprite, then text_render wouldn't have to resize // the texture per every new string of text.
|
||||
|
@ -427,7 +431,7 @@ static void draw_wall_of_text(float f, const char *txt) {
|
|||
r_uniform_float("w", spr.tex_area.w/spr.tex->w);
|
||||
r_uniform_float("h", spr.tex_area.h/spr.tex->h);
|
||||
r_uniform_float("ratio", h/w);
|
||||
r_uniform_vec2("origin", creal(global.boss->pos)/h, cimag(global.boss->pos)/w);
|
||||
r_uniform_vec2("origin", creal(global.boss->pos)/h, cimag(global.boss->pos)/w); // what the fuck?
|
||||
r_uniform_float("t", f);
|
||||
r_texture_ptr(0, spr.tex);
|
||||
r_draw_quad();
|
||||
|
|
|
@ -102,13 +102,12 @@ void draw_stars(int x, int y, int numstars, int numfrags, int maxstars, int maxf
|
|||
|
||||
void draw_framebuffer_attachment(Framebuffer *fb, double width, double height, FramebufferAttachment attachment) {
|
||||
CullFaceMode cull_saved = r_cull_current();
|
||||
r_cull(CULL_FRONT);
|
||||
r_cull(CULL_BACK);
|
||||
|
||||
r_mat_push();
|
||||
r_texture_ptr(0, r_framebuffer_get_attachment(fb, attachment));
|
||||
r_mat_scale(width, height, 1);
|
||||
r_mat_translate(0.5, 0.5, 0);
|
||||
r_mat_scale(1, -1, 1);
|
||||
r_draw_quad();
|
||||
r_mat_pop();
|
||||
|
||||
|
@ -163,3 +162,19 @@ void init_blur_shader(ShaderProgram *prog, size_t kernel_size, float sigma) {
|
|||
gaussian_kernel_1d(kernel_size, sigma, kernel);
|
||||
r_uniform_ptr(r_shader_uniform(prog, "blur_kernel[0]"), kernel_size, kernel);
|
||||
}
|
||||
|
||||
void flip_bitmap(char *data, size_t rows, size_t row_length) {
|
||||
char swap_buffer[row_length];
|
||||
|
||||
for(size_t row = 0; row < rows / 2; ++row) {
|
||||
memcpy(swap_buffer, data + row * row_length, row_length);
|
||||
memcpy(data + row * row_length, data + (rows - row - 1) * row_length, row_length);
|
||||
memcpy(data + (rows - row - 1) * row_length, swap_buffer, row_length);
|
||||
}
|
||||
}
|
||||
|
||||
void flip_bitmap_copy(char *dst, const char *src, size_t rows, size_t row_length) {
|
||||
for(size_t row = 0, irow = rows - 1; row < rows; ++row, --irow) {
|
||||
memcpy(dst + irow * row_length, src + row * row_length, row_length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,3 +23,6 @@ void fbutil_destroy_attachments(Framebuffer *fb);
|
|||
void fbutil_resize_attachment(Framebuffer *fb, FramebufferAttachment attachment, uint width, uint height);
|
||||
|
||||
void init_blur_shader(ShaderProgram *prog, size_t kernel_size, float sigma);
|
||||
|
||||
void flip_bitmap(char *data, size_t rows, size_t row_length);
|
||||
void flip_bitmap_copy(char *dst, const char *src, size_t rows, size_t row_length);
|
||||
|
|
Loading…
Reference in a new issue