/* * This software is licensed under the terms of the MIT License. * See COPYING for further information. * --- * Copyright (c) 2011-2024, Lukas Weber . * Copyright (c) 2012-2024, Andrei Alexeyev . */ #include "texture_loader/texture_loader.h" #include "global.h" #include "renderer/api.h" #include "video.h" static bool texture_transfer(void *dst, void *src) { return r_texture_transfer(dst, src); } ResourceHandler texture_res_handler = { .type = RES_TEXTURE, .typename = "texture", .subdir = TEX_PATH_PREFIX, .procs = { .find = texture_loader_path, .check = texture_loader_check_path, .load = texture_loader_stage1, .unload = texture_loader_unload, .transfer = texture_transfer, }, }; static struct draw_texture_state { bool drawing; bool texture_matrix_tainted; } draw_texture_state; void begin_draw_texture(FloatRect dest, FloatRect frag, Texture *tex) { assume(!draw_texture_state.drawing); draw_texture_state.drawing = true; r_uniform_sampler("tex", tex); r_mat_mv_push(); uint tw, th; r_texture_get_size(tex, 0, &tw, &th); float x = dest.x; float y = dest.y; float w = dest.w; float h = dest.h; float s = frag.w/tw; float t = frag.h/th; if(r_supports(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN)) { // FIXME: please somehow abstract this shit away! frag.y = th - frag.y - frag.h; } if(s != 1 || t != 1 || frag.x || frag.y) { draw_texture_state.texture_matrix_tainted = true; r_mat_tex_push(); r_mat_tex_scale(1.0/tw, 1.0/th, 1); if(frag.x || frag.y) { r_mat_tex_translate(frag.x, frag.y, 0); } if(s != 1 || t != 1) { r_mat_tex_scale(frag.w, frag.h, 1); } } if(x || y) { r_mat_mv_translate(x, y, 0); } if(w != 1 || h != 1) { r_mat_mv_scale(w, h, 1); } } void end_draw_texture(void) { assume(draw_texture_state.drawing); if(draw_texture_state.texture_matrix_tainted) { draw_texture_state.texture_matrix_tainted = false; r_mat_tex_pop(); } r_mat_mv_pop(); draw_texture_state.drawing = false; } void fill_viewport(float xoff, float yoff, float ratio, const char *name) { fill_viewport_p(xoff, yoff, ratio, 1, 0, res_texture(name)); } void fill_viewport_p(float xoff, float yoff, float ratio, float aspect, float angle, Texture *tex) { r_uniform_sampler("tex", tex); float rw, rh; if(ratio == 0) { rw = aspect; rh = 1; } else { rw = ratio * aspect; rh = ratio; } if(r_supports(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN)) { // FIXME: we should somehow account for this globally if possible... yoff *= -1; yoff += (1 - ratio); } bool texture_matrix_tainted = false; if(xoff || yoff || rw != 1 || rh != 1 || angle) { texture_matrix_tainted = true; r_mat_tex_push(); if(xoff || yoff) { r_mat_tex_translate(xoff, yoff, 0); } if(rw != 1 || rh != 1) { r_mat_tex_scale(rw, rh, 1); } if(angle) { r_mat_tex_translate(0.5, 0.5, 0); r_mat_tex_rotate(angle * DEG2RAD, 0, 0, 1); r_mat_tex_translate(-0.5, -0.5, 0); } } r_mat_mv_push(); r_mat_mv_translate(VIEWPORT_W*0.5, VIEWPORT_H*0.5, 0); r_mat_mv_scale(VIEWPORT_W, VIEWPORT_H, 1); r_draw_quad(); r_mat_mv_pop(); if(texture_matrix_tainted) { r_mat_tex_pop(); } } void fill_screen(const char *name) { fill_screen_p(res_texture(name)); } void fill_screen_p(Texture *tex) { uint tw, th; r_texture_get_size(tex, 0, &tw, &th); begin_draw_texture((FloatRect){ SCREEN_W*0.5, SCREEN_H*0.5, SCREEN_W, SCREEN_H }, (FloatRect){ 0, 0, tw, th }, tex); r_draw_quad(); end_draw_texture(); } // draws a thin, w-width rectangle from point A to point B with a texture that // moves along the line. // void loop_tex_line_p(cmplx a, cmplx b, float w, float t, Texture *texture) { cmplx d = b-a; cmplx c = (b+a)/2; r_mat_mv_push(); r_mat_mv_translate(re(c), im(c), 0); r_mat_mv_rotate(carg(d), 0, 0, 1); r_mat_mv_scale(cabs(d), w, 1); r_mat_tex_push(); r_mat_tex_translate(t, 0, 0); r_uniform_sampler("tex", texture); r_draw_quad(); r_mat_tex_pop(); r_mat_mv_pop(); } void loop_tex_line(cmplx a, cmplx b, float w, float t, const char *texture) { loop_tex_line_p(a, b, w, t, res_texture(texture)); }