Some renderer refactoring (mostly API and GLES preparations) (#144)

* Refacor uniforms API:

    - More complete and consistent
    - Type-safety
    - Usage correctess assertions missing for now, planned

* Redesign texturing API: texunits gone, assign textures to sampler uniforms directly

r_texture_create now allocates memory and returns an opaque Texture
pointer; similar changes to the other renderer APIs will follow.

* Framebuffers: make _create return an opaque pointer, add debug label APIs (unused for now)

* opaque pointers and debug label APIs for vertex arrays and buffers

* fix null renderer

* Refactor glsl preprocessing into an independent module

* Separate shader resource management from renderer backend

This makes it possible to add more shading languages and/or include a
transpiler, which will be useful for the GLES backend.

* refactor r_clear into a stateless API

* add r_texture_clear API; fix gl33_framebuffer_clear

* Replace deprecated glsl_objects with objects in all *.prog files

* fix missing texture_clear implementation in null renderer

* remove some dead code in null renderer

* fix GLES segfault

* GLES 3.0 actually has glVertexAttribDivisor

* Query GL for supported GLSL versions (preparing to add shader transcompilation)
This commit is contained in:
Andrei Alexeyev 2018-09-14 10:37:20 +03:00 committed by GitHub
parent 3cd4ecfceb
commit 9b3779ebb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
137 changed files with 3421 additions and 1860 deletions

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert alpha_depth.frag
objects = standard.vert alpha_depth.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert bloom.frag
objects = standard.vert bloom.frag

View file

@ -1 +1 @@
glsl_objects = blur13.frag standardnotex.vert
objects = blur13.frag standardnotex.vert

View file

@ -1 +1 @@
glsl_objects = blur25.frag standardnotex.vert
objects = blur25.frag standardnotex.vert

View file

@ -1 +1 @@
glsl_objects = blur5.frag standardnotex.vert
objects = blur5.frag standardnotex.vert

View file

@ -1 +1 @@
glsl_objects = blur9.frag standardnotex.vert
objects = blur9.frag standardnotex.vert

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert boss_zoom.frag
objects = standard.vert boss_zoom.frag

View file

@ -1 +1 @@
glsl_objects = copy_depth.frag standardnotex.vert
objects = copy_depth.frag standardnotex.vert

View file

@ -1,2 +1,2 @@
glsl_objects = fxaa.vert fxaa.frag
objects = fxaa.vert fxaa.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert glitch.frag
objects = standard.vert glitch.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert graph.frag
objects = standard.vert graph.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert ingame_menu.frag
objects = standard.vert ingame_menu.frag

View file

@ -35,9 +35,8 @@ OUT(0) vec4 fragColor;
UNIFORM(0) sampler2D tex;
// For why this is 7, see NUM_SPRITE_AUX_TEXTURES api.h.
// This line is here just in case you're grepping for "R_MAX_TEXUNITS".
UNIFORM(64) sampler2D tex_aux[7];
// see NUM_SPRITE_AUX_TEXTURES in api.h.
UNIFORM(64) sampler2D tex_aux[3];
VARYING(0) vec2 texCoordRaw;
VARYING(1) vec2 texCoord;

View file

@ -1 +1 @@
glsl_objects = laser_generic.vert standard.frag
objects = laser_generic.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/accelerated.vert standard.frag
objects = lasers/accelerated.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/circle.vert standard.frag
objects = lasers/circle.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/elly_toe_fermion.vert standard.frag
objects = lasers/elly_toe_fermion.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/elly_toe_gluon.vert standard.frag
objects = lasers/elly_toe_gluon.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/elly_toe_higgs.vert standard.frag
objects = lasers/elly_toe_higgs.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/elly_toe_photon.vert standard.frag
objects = lasers/elly_toe_photon.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/iku_cathode.vert standard.frag
objects = lasers/iku_cathode.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/iku_lightning.vert standard.frag
objects = lasers/iku_lightning.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/linear.vert standard.frag
objects = lasers/linear.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/maxwell.vert standard.frag
objects = lasers/maxwell.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/sine.vert standard.frag
objects = lasers/sine.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/sine_expanding.vert standard.frag
objects = lasers/sine_expanding.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/turning.vert standard.frag
objects = lasers/turning.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = lasers/weird_sine.vert standard.frag
objects = lasers/weird_sine.vert standard.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert marisa_laser.frag
objects = standard.vert marisa_laser.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert maristar_bombbg.frag
objects = standard.vert maristar_bombbg.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert masterspark.frag
objects = standard.vert masterspark.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert max_to_alpha.frag
objects = standard.vert max_to_alpha.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert player_death.frag
objects = standard.vert player_death.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert reimu_bomb_bg.frag
objects = standard.vert reimu_bomb_bg.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert reimu_gap.frag
objects = standard.vert reimu_gap.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert reimu_gap_light.frag
objects = standard.vert reimu_gap_light.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert spellcard_intro.frag
objects = standard.vert spellcard_intro.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert spellcard_outro.frag
objects = standard.vert spellcard_outro.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert spellcard_walloftext.frag
objects = standard.vert spellcard_walloftext.frag

View file

@ -1 +1 @@
glsl_objects = sprite_bullet.vert sprite_bullet.frag
objects = sprite_bullet.vert sprite_bullet.frag

View file

@ -1,2 +1,2 @@
glsl_objects = sprite_circleclipped_indicator.vert sprite_circleclipped_indicator.frag
objects = sprite_circleclipped_indicator.vert sprite_circleclipped_indicator.frag

View file

@ -1 +1 @@
glsl_objects = sprite_default.vert sprite_default.frag
objects = sprite_default.vert sprite_default.frag

View file

@ -1 +1 @@
glsl_objects = sprite_filled_circle.vert sprite_filled_circle.frag
objects = sprite_filled_circle.vert sprite_filled_circle.frag

View file

@ -1 +1 @@
glsl_objects = sprite_hakkero.vert sprite_hakkero.frag
objects = sprite_hakkero.vert sprite_hakkero.frag

View file

@ -1 +1 @@
glsl_objects = sprite_default.vert sprite_negative.frag
objects = sprite_default.vert sprite_negative.frag

View file

@ -1 +1 @@
glsl_objects = sprite_silhouette.vert sprite_silhouette.frag
objects = sprite_silhouette.vert sprite_silhouette.frag

View file

@ -1 +1 @@
glsl_objects = sprite_default.vert sprite_yinyang.frag
objects = sprite_default.vert sprite_yinyang.frag

View file

@ -1 +1 @@
glsl_objects = sprite_youmu_charged_shot.vert sprite_youmu_charged_shot.frag
objects = sprite_youmu_charged_shot.vert sprite_youmu_charged_shot.frag

View file

@ -1 +1 @@
glsl_objects = sprite_bullet.vert sprite_youmu_myon_shot.frag
objects = sprite_bullet.vert sprite_youmu_myon_shot.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert stage1_water.frag
objects = standard.vert stage1_water.frag

View file

@ -1 +1 @@
glsl_objects = stage6_sky.vert stage6_sky.frag
objects = stage6_sky.vert stage6_sky.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert standard.frag
objects = standard.vert standard.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standardnotex.vert standardnotex.frag
objects = standardnotex.vert standardnotex.frag

View file

@ -1 +1 @@
glsl_objects = text_default.vert text_default.frag
objects = text_default.vert text_default.frag

View file

@ -1 +1 @@
glsl_objects = text_example.vert text_example.frag
objects = text_example.vert text_example.frag

View file

@ -1,2 +1,2 @@
glsl_objects = text_default.vert text_hud.frag
objects = text_default.vert text_hud.frag

View file

@ -1,2 +1,2 @@
glsl_objects = text_example.vert text_stagetext.frag
objects = text_example.vert text_stagetext.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert texture_post_load.frag
objects = standard.vert texture_post_load.frag

View file

@ -1 +1 @@
glsl_objects = tower_light.vert tower_light.frag
objects = tower_light.vert tower_light.frag

View file

@ -1 +1 @@
glsl_objects = tower_wall.vert tower_wall.frag
objects = tower_wall.vert tower_wall.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert tunnel.frag
objects = standard.vert tunnel.frag

View file

@ -1 +1 @@
glsl_objects = standard.vert youmua_bomb.frag
objects = standard.vert youmua_bomb.frag

View file

@ -1,2 +1,2 @@
glsl_objects = standard.vert zbuf_fog.frag
objects = standard.vert zbuf_fog.frag

View file

@ -194,9 +194,8 @@ static void credits_add(char *data, int time) {
}
static void credits_towerwall_draw(vec3 pos) {
r_texture(0, "stage6/towerwall");
r_shader("tower_wall");
r_uniform_sampler("tex", "stage6/towerwall");
r_uniform_float("lendiv", 2800.0 + 300.0 * sin(global.frames / 77.7));
r_mat_push();
@ -234,7 +233,7 @@ static double entry_height(CreditsEntry *e, double *head, double *body) {
if(e->lines > 0) {
if(*(e->data[0]) == '*') {
total += *head = get_tex("yukkureimu")->h * CREDITS_YUKKURI_SCALE;
total += *head = r_texture_get_height(get_tex("yukkureimu"), 0) * CREDITS_YUKKURI_SCALE;
} else {
total += *head = font_get_lineskip(get_font("big"));
}
@ -339,8 +338,8 @@ static void credits_draw_entry(CreditsEntry *e) {
}
static void credits_draw(void) {
r_clear(CLEAR_ALL);
colorfill(1, 1, 1, 1); // don't use r_clear_color4 for this, it screws up letterboxing
r_clear(CLEAR_ALL, RGBA(0, 0, 0, 1), 1);
colorfill(1, 1, 1, 1); // don't use r_clear for this, it screws up letterboxing
r_mat_push();
r_mat_translate(-SCREEN_W/2, 0, 0);

View file

@ -187,7 +187,7 @@ static void ending_draw(Ending *e) {
else
s = clamp(d*t2, 0.0, 1.0);
r_clear(CLEAR_ALL);
r_clear(CLEAR_ALL, RGBA(0, 0, 0, 1), 1);
r_color4(s, s, s, s);

View file

@ -165,7 +165,7 @@ begin_frame:
if((!uncapped_rendering && frame_num % get_effective_frameskip()) || global.is_replay_verification) {
rframe_action = RFRAME_DROP;
} else {
r_clear(CLEAR_ALL);
r_framebuffer_clear(NULL, CLEAR_ALL, RGBA(0, 0, 0, 1), 1);
rframe_action = render_frame(arg);
fpscounter_update(&global.fps.render);

View file

@ -15,8 +15,8 @@
#include "renderer/api.h"
static struct {
VertexArray varr;
VertexBuffer vbuf;
VertexArray *varr;
VertexBuffer *vbuf;
ShaderProgram *shader_generic;
} lasers;
@ -48,20 +48,22 @@ void lasers_preload(void) {
#undef VERTEX_OFS
#undef INSTANCE_OFS
r_vertex_buffer_create(&lasers.vbuf, sizeof(LaserInstancedAttribs) * 4096, NULL);
lasers.vbuf = r_vertex_buffer_create(sizeof(LaserInstancedAttribs) * 4096, NULL);
r_vertex_buffer_set_debug_label(lasers.vbuf, "Lasers vertex buffer");
r_vertex_array_create(&lasers.varr);
r_vertex_array_layout(&lasers.varr, sizeof(fmt)/sizeof(VertexAttribFormat), fmt);
r_vertex_array_attach_buffer(&lasers.varr, r_vertex_buffer_static_models(), 0);
r_vertex_array_attach_buffer(&lasers.varr, &lasers.vbuf, 1);
r_vertex_array_layout(&lasers.varr, sizeof(fmt)/sizeof(VertexAttribFormat), fmt);
lasers.varr = r_vertex_array_create();
r_vertex_array_set_debug_label(lasers.varr, "Lasers vertex array");
r_vertex_array_layout(lasers.varr, sizeof(fmt)/sizeof(VertexAttribFormat), fmt);
r_vertex_array_attach_buffer(lasers.varr, r_vertex_buffer_static_models(), 0);
r_vertex_array_attach_buffer(lasers.varr, lasers.vbuf, 1);
r_vertex_array_layout(lasers.varr, sizeof(fmt)/sizeof(VertexAttribFormat), fmt);
lasers.shader_generic = r_shader_get("laser_generic");
}
void lasers_free(void) {
r_vertex_array_destroy(&lasers.varr);
r_vertex_buffer_destroy(&lasers.vbuf);
r_vertex_array_destroy(lasers.varr);
r_vertex_buffer_destroy(lasers.vbuf);
}
static void ent_draw_laser(EntityInterface *ent);
@ -149,8 +151,9 @@ static void draw_laser_curve_specialized(Laser *l) {
}
r_color(&l->color);
r_uniform_complex("origin", l->pos);
r_uniform_complex_array("args[0]", 4, l->args);
r_uniform_sampler("tex", "part/lasercurve");
r_uniform_vec2_complex("origin", l->pos);
r_uniform_vec2_array_complex("args[0]", 0, 4, l->args);
r_uniform_float("timeshift", timeshift);
r_uniform_float("width", l->width);
r_uniform_float("width_exponent", l->width_exponent);
@ -167,13 +170,14 @@ static void draw_laser_curve_generic(Laser *l) {
}
r_color(&l->color);
r_uniform_sampler("tex", "part/lasercurve");
r_uniform_float("timeshift", timeshift);
r_uniform_float("width", l->width);
r_uniform_float("width_exponent", l->width_exponent);
r_uniform_int("span", instances);
LaserInstancedAttribs attrs[instances], *aptr = attrs;
r_vertex_buffer_invalidate(&lasers.vbuf);
r_vertex_buffer_invalidate(lasers.vbuf);
for(uint i = 0; i < instances; ++i, ++aptr) {
complex pos = l->prule(l, i * 0.5 + timeshift);
@ -185,15 +189,13 @@ static void draw_laser_curve_generic(Laser *l) {
aptr->delta[1] = cimag(delta);
}
r_vertex_buffer_append(&lasers.vbuf, sizeof(attrs), &attrs);
r_vertex_buffer_append(lasers.vbuf, sizeof(attrs), &attrs);
r_draw(PRIM_TRIANGLE_FAN, 0, 4, NULL, instances, 0);
}
static void ent_draw_laser(EntityInterface *ent) {
Laser *laser = ENT_CAST(ent, Laser);
r_texture(0, "part/lasercurve");
if(laser->shader) {
// Specialized lasers work with either vertex array,
// provided that the static models buffer is attached to it.
@ -202,14 +204,14 @@ static void ent_draw_laser(EntityInterface *ent) {
VertexArray *va = r_vertex_array_current();
if(va != &lasers.varr && va != r_vertex_array_static_models()) {
r_vertex_array(&lasers.varr);
if(va != lasers.varr && va != r_vertex_array_static_models()) {
r_vertex_array(lasers.varr);
}
r_shader_ptr(laser->shader);
draw_laser_curve_specialized(laser);
} else {
r_vertex_array(&lasers.varr);
r_vertex_array(lasers.varr);
r_shader_ptr(lasers.shader_generic);
draw_laser_curve_generic(laser);
}

View file

@ -444,8 +444,7 @@ void player_realdeath(Player *plr) {
static void player_death_effect_draw_overlay(Projectile *p, int t) {
FBPair *framebuffers = stage_get_fbpair(FBPAIR_FG);
r_framebuffer(framebuffers->front);
r_texture(1, "static");
r_uniform_int("noise", 1);
r_uniform_sampler("noise", "static");
r_uniform_int("frames", global.frames);
r_uniform_float("progress", t / p->timeout);
r_uniform_vec2("origin", creal(p->pos), VIEWPORT_H - cimag(p->pos));

View file

@ -134,8 +134,7 @@ void marisa_common_masterspark_draw(complex origin, complex size, float angle, i
FBPair *aux = stage_get_fbpair(FBPAIR_FG_AUX);
r_framebuffer(aux->back);
r_clear_color4(0, 0, 0, 0);
r_clear(CLEAR_COLOR);
r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
draw_masterspark_beam(origin, size, angle, t, alpha);
@ -145,7 +144,7 @@ void marisa_common_masterspark_draw(complex origin, complex size, float angle, i
fbpair_swap(aux);
r_framebuffer(aux->back);
r_clear(CLEAR_COLOR);
r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
draw_framebuffer_tex(aux->front, VIEWPORT_W, VIEWPORT_H);
r_uniform_vec2("blur_direction", 0, blur);

View file

@ -42,8 +42,8 @@ static void draw_laser_beam(complex src, complex dst, double size, double step,
r_mat_scale(cabs(dir) / step, 1, 1);
r_mat_mode(MM_MODELVIEW);
r_texture_ptr(0, tex);
r_uniform_ptr(u_length, 1, (float[]) { cabs(dir) / step });
r_uniform_sampler("tex", tex);
r_uniform_float(u_length, cabs(dir) / step);
r_draw_quad();
r_mat_mode(MM_TEXTURE);
@ -131,7 +131,7 @@ static void trace_laser(Enemy *e, complex vel, float damage) {
static float set_alpha(Uniform *u_alpha, float a) {
if(a) {
r_uniform_ptr(u_alpha, 1, (float[]) { a });
r_uniform_float(u_alpha, a);
}
return a;
@ -209,13 +209,12 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
r_vertex_array(r_vertex_array_static_models());
r_shader_ptr(shader);
r_uniform_ptr(u_clr0, 1, (float[]) { 0.5, 0.5, 0.5, 0.0 });
r_uniform_ptr(u_clr1, 1, (float[]) { 0.8, 0.8, 0.8, 0.0 });
r_uniform_ptr(u_clr_phase, 1, (float[]) { -1.5 * t/M_PI });
r_uniform_ptr(u_clr_freq, 1, (float[]) { 10.0 });
r_uniform_vec4(u_clr0, 0.5, 0.5, 0.5, 0.0);
r_uniform_vec4(u_clr1, 0.8, 0.8, 0.8, 0.0);
r_uniform_float(u_clr_phase, -1.5 * t/M_PI);
r_uniform_float(u_clr_freq, 10.0);
r_framebuffer(fbp_aux->back);
r_clear_color4(0, 0, 0, 0);
r_clear(CLEAR_COLOR);
r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
r_color4(1, 1, 1, 1);
r_blend(r_blend_compose(
@ -234,9 +233,7 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
fbpair_swap(fbp_aux);
r_framebuffer(fbp_aux->back);
r_clear_color4(0, 0, 0, 0);
r_clear(CLEAR_COLOR);
r_texture_ptr(0, r_framebuffer_get_attachment(fbp_aux->front, FRAMEBUFFER_ATTACH_COLOR0));
r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
r_shader("max_to_alpha");
draw_framebuffer_tex(fbp_aux->front, VIEWPORT_W, VIEWPORT_H);
fbpair_swap(fbp_aux);
@ -247,8 +244,8 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
draw_framebuffer_tex(fbp_aux->front, VIEWPORT_W, VIEWPORT_H);
r_shader_ptr(shader);
r_uniform_ptr(u_clr0, 1, (float[]) { 0.5, 0.0, 0.0, 0.0 });
r_uniform_ptr(u_clr1, 1, (float[]) { 1.0, 0.0, 0.0, 0.0 });
r_uniform_vec4(u_clr0, 0.5, 0.0, 0.0, 0.0);
r_uniform_vec4(u_clr1, 1.0, 0.0, 0.0, 0.0);
FOR_EACH_SLAVE(e) {
if(set_alpha_dimmed(u_alpha, get_laser_alpha(e, a))) {
@ -257,8 +254,8 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
}
}
r_uniform_ptr(u_clr0, 1, (float[]) { 2.0, 1.0, 2.0, 0.0 });
r_uniform_ptr(u_clr1, 1, (float[]) { 0.1, 0.1, 1.0, 0.0 });
r_uniform_vec4(u_clr0, 2.0, 1.0, 2.0, 0.0);
r_uniform_vec4(u_clr1, 0.1, 0.1, 1.0, 0.0);
FOR_EACH_SLAVE(e) {
if(set_alpha_dimmed(u_alpha, get_laser_alpha(e, a))) {
@ -267,7 +264,6 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
}
}
r_clear_color4(0, 0, 0, 1);
r_shader("sprite_default");
r_vertex_array(varr_saved);
}

View file

@ -121,8 +121,7 @@ void reimu_common_bomb_bg(Player *p, float alpha) {
r_color(HSLA_MUL_ALPHA(global.frames / 30.0, 0.2, 0.9, alpha));
r_shader("reimu_bomb_bg");
r_texture(1, "runes");
r_uniform_int("runes", 1);
r_uniform_sampler("runes", "runes");
r_uniform_float("zoom", VIEWPORT_H / sqrt(VIEWPORT_W*VIEWPORT_W + VIEWPORT_H*VIEWPORT_H));
r_uniform_vec2("aspect", VIEWPORT_W / (float)VIEWPORT_H, 1);
r_uniform_float("time", 9000 + 3 * global.frames / 60.0);

View file

@ -164,8 +164,8 @@ static void reimu_dream_gap_draw_lights(int time, double strength) {
return;
}
r_texture(0, "gaplight");
r_shader("reimu_gap_light");
r_uniform_sampler("tex", "gaplight");
r_uniform_float("time", time / 60.0);
r_uniform_float("strength", strength);
@ -214,9 +214,9 @@ static void reimu_dream_gap_renderer_visual(Enemy *e, int t, bool render) {
r_uniform_vec2("viewport", VIEWPORT_W, VIEWPORT_H);
r_uniform_float("time", t / (float)FPS);
r_uniform_vec2("gap_size", GAP_WIDTH/2.0, GAP_LENGTH/2.0);
r_uniform("gaps[0]", NUM_GAPS, gaps);
r_uniform("gap_angles[0]", NUM_GAPS, angles);
r_uniform("gap_links[0]", NUM_GAPS, links);
r_uniform_vec2_array("gaps[0]", 0, NUM_GAPS, gaps);
r_uniform_float_array("gap_angles[0]", 0, NUM_GAPS, angles);
r_uniform_int_array("gap_links[0]", 0, NUM_GAPS, links);
draw_framebuffer_tex(framebuffers->front, VIEWPORT_W, VIEWPORT_H);
FOR_EACH_GAP(gap) {

View file

@ -70,6 +70,13 @@ void r_post_init(void) {
r_shader_ptr(R.progs.standard);
r_color4(1, 1, 1, 1);
r_enable(RCAP_DEPTH_TEST);
r_enable(RCAP_DEPTH_WRITE);
r_enable(RCAP_CULL_FACE);
r_depth_func(DEPTH_LEQUAL);
r_cull(CULL_BACK);
r_blend(BLEND_PREMUL_ALPHA);
r_framebuffer_clear(NULL, CLEAR_ALL, RGBA(0, 0, 0, 1), 1);
log_info("Rendering subsystem initialized (%s)", _r_backend.name);
}
@ -187,7 +194,7 @@ const UniformTypeInfo* r_uniform_type_info(UniformType type) {
[UNIFORM_IVEC2] = { 2, sizeof(int) },
[UNIFORM_IVEC3] = { 3, sizeof(int) },
[UNIFORM_IVEC4] = { 4, sizeof(int) },
[UNIFORM_SAMPLER] = { 1, sizeof(int) },
[UNIFORM_SAMPLER] = { 1, sizeof(void*) },
[UNIFORM_MAT3] = { 9, sizeof(float) },
[UNIFORM_MAT4] = { 16, sizeof(float) },
};
@ -317,6 +324,42 @@ DepthTestFunc r_depth_func_current(void) {
return B.depth_func_current();
}
bool r_shader_language_supported(const ShaderLangInfo *lang, ShaderLangInfo *out_alternative) {
return B.shader_language_supported(lang, out_alternative);
}
ShaderObject* r_shader_object_compile(ShaderSource *source) {
return B.shader_object_compile(source);
}
void r_shader_object_destroy(ShaderObject *shobj) {
B.shader_object_destroy(shobj);
}
void r_shader_object_set_debug_label(ShaderObject *shobj, const char *label) {
B.shader_object_set_debug_label(shobj, label);
}
const char* r_shader_object_get_debug_label(ShaderObject *shobj) {
return B.shader_object_get_debug_label(shobj);
}
ShaderProgram* r_shader_program_link(uint num_objects, ShaderObject *shobjs[num_objects]) {
return B.shader_program_link(num_objects, shobjs);
}
void r_shader_program_destroy(ShaderProgram *prog) {
B.shader_program_destroy(prog);
}
void r_shader_program_set_debug_label(ShaderProgram *prog, const char *label) {
B.shader_program_set_debug_label(prog, label);
}
const char* r_shader_program_get_debug_label(ShaderProgram *prog) {
return B.shader_program_get_debug_label(prog);
}
void r_shader_ptr(ShaderProgram *prog) {
_r_state_touch_shader();
B.shader(prog);
@ -330,11 +373,6 @@ Uniform* r_shader_uniform(ShaderProgram *prog, const char *uniform_name) {
return B.shader_uniform(prog, uniform_name);
}
void r_uniform_ptr(Uniform *uniform, uint count, const void *data) {
_r_state_touch_uniform(uniform);
B.uniform(uniform, count, data);
}
UniformType r_uniform_type(Uniform *uniform) {
return B.uniform_type(uniform);
}
@ -343,14 +381,38 @@ void r_draw(Primitive prim, uint first, uint count, uint32_t *indices, uint inst
B.draw(prim, first, count, indices, instances, base_instance);
}
void r_texture_create(Texture *tex, const TextureParams *params) {
B.texture_create(tex, params);
Texture* r_texture_create(const TextureParams *params) {
return B.texture_create(params);
}
void r_texture_get_size(Texture *tex, uint mipmap, uint *width, uint *height) {
B.texture_get_size(tex, mipmap, width, height);
}
uint r_texture_get_width(Texture *tex, uint mipmap) {
uint w;
B.texture_get_size(tex, mipmap, &w, NULL);
return w;
}
uint r_texture_get_height(Texture *tex, uint mipmap) {
uint h;
B.texture_get_size(tex, mipmap, NULL, &h);
return h;
}
void r_texture_get_params(Texture *tex, TextureParams *params) {
B.texture_get_params(tex, params);
}
const char* r_texture_get_debug_label(Texture *tex) {
return B.texture_get_debug_label(tex);
}
void r_texture_set_debug_label(Texture *tex, const char *label) {
B.texture_set_debug_label(tex, label);
}
void r_texture_set_filter(Texture *tex, TextureFilterMode fmin, TextureFilterMode fmag) {
B.texture_set_filter(tex, fmin, fmag);
}
@ -371,21 +433,24 @@ void r_texture_invalidate(Texture *tex) {
B.texture_invalidate(tex);
}
void r_texture_clear(Texture *tex, const Color *clr) {
B.texture_clear(tex, clr);
}
void r_texture_destroy(Texture *tex) {
B.texture_destroy(tex);
}
void r_texture_ptr(uint unit, Texture *tex) {
_r_state_touch_texunit(unit);
B.texture(unit, tex);
Framebuffer* r_framebuffer_create(void) {
return B.framebuffer_create();
}
Texture* r_texture_current(uint unit) {
return B.texture_current(unit);
const char* r_framebuffer_get_debug_label(Framebuffer *fb) {
return B.framebuffer_get_debug_label(fb);
}
void r_framebuffer_create(Framebuffer *fb) {
B.framebuffer_create(fb);
void r_framebuffer_set_debug_label(Framebuffer *fb, const char *label) {
B.framebuffer_set_debug_label(fb, label);
}
void r_framebuffer_attach(Framebuffer *fb, Texture *tex, uint mipmap, FramebufferAttachment attachment) {
@ -400,6 +465,10 @@ uint r_framebuffer_get_attachment_mipmap(Framebuffer *fb, FramebufferAttachment
return B.framebuffer_get_attachment_mipmap(fb, attachment);
}
void r_framebuffer_clear(Framebuffer *fb, ClearBufferFlags flags, const Color *colorval, float depthval) {
B.framebuffer_clear(fb, flags, colorval, depthval);
}
void r_framebuffer_viewport(Framebuffer *fb, int x, int y, int w, int h) {
r_framebuffer_viewport_rect(fb, (IntRect) { x, y, w, h });
}
@ -427,8 +496,16 @@ Framebuffer * r_framebuffer_current(void) {
return B.framebuffer_current();
}
void r_vertex_buffer_create(VertexBuffer *vbuf, size_t capacity, void *data) {
B.vertex_buffer_create(vbuf, capacity, data);
VertexBuffer* r_vertex_buffer_create(size_t capacity, void *data) {
return B.vertex_buffer_create(capacity, data);
}
const char* r_vertex_buffer_get_debug_label(VertexBuffer *vbuf) {
return B.vertex_buffer_get_debug_label(vbuf);
}
void r_vertex_buffer_set_debug_label(VertexBuffer *vbuf, const char* label) {
B.vertex_buffer_set_debug_label(vbuf, label);
}
void r_vertex_buffer_destroy(VertexBuffer *vbuf) {
@ -447,8 +524,37 @@ void r_vertex_buffer_append(VertexBuffer *vbuf, size_t data_size, void *data) {
B.vertex_buffer_append(vbuf, data_size, data);
}
void r_vertex_array_create(VertexArray *varr) {
B.vertex_array_create(varr);
size_t r_vertex_buffer_get_capacity(VertexBuffer *vbuf) {
return B.vertex_buffer_get_capacity(vbuf);
}
size_t r_vertex_buffer_get_cursor(VertexBuffer *vbuf) {
return B.vertex_buffer_get_cursor(vbuf);
}
void r_vertex_buffer_seek_cursor(VertexBuffer *vbuf, ssize_t offset, int whence) {
size_t pos;
switch(whence) {
case SEEK_CUR: pos = r_vertex_buffer_get_cursor(vbuf) + offset; break;
case SEEK_END: pos = r_vertex_buffer_get_capacity(vbuf) + offset; break;
case SEEK_SET: pos = offset; break;
default: UNREACHABLE;
}
B.vertex_buffer_set_cursor(vbuf, pos);
}
VertexArray* r_vertex_array_create(void) {
return B.vertex_array_create();
}
const char* r_vertex_array_get_debug_label(VertexArray *varr) {
return B.vertex_array_get_debug_label(varr);
}
void r_vertex_array_set_debug_label(VertexArray *varr, const char* label) {
B.vertex_array_set_debug_label(varr, label);
}
void r_vertex_array_destroy(VertexArray *varr) {
@ -476,19 +582,6 @@ VertexArray* r_vertex_array_current(void) {
return B.vertex_array_current();
}
void r_clear(ClearBufferFlags flags) {
B.clear(flags);
}
void r_clear_color4(float r, float g, float b, float a) {
_r_state_touch_clear_color();
B.clear_color4(r, g, b, a);
}
const Color* r_clear_color_current(void) {
return B.clear_color_current();
}
void r_vsync(VsyncMode mode) {
_r_state_touch_vsync();
B.vsync(mode);
@ -506,3 +599,333 @@ void r_swap(SDL_Window *window) {
uint8_t* r_screenshot(uint *out_width, uint *out_height) {
return B.screenshot(out_width, out_height);
}
// uniforms garbage; hope your compiler is smart enough to inline most of this
#define ASSERT_UTYPE(uniform, type) do { if(uniform) assert(r_uniform_type(uniform) == type); } while(0)
void r_uniform_ptr_unsafe(Uniform *uniform, uint offset, uint count, void *data) {
if(uniform) B.uniform(uniform, offset, count, data);
}
void _r_uniform_ptr_float(Uniform *uniform, float value) {
ASSERT_UTYPE(uniform, UNIFORM_FLOAT);
if(uniform) B.uniform(uniform, 0, 1, &value);
}
void _r_uniform_float(const char *uniform, float value) {
_r_uniform_ptr_float(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_float_array(Uniform *uniform, uint offset, uint count, float elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_FLOAT);
if(uniform && count) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_float_array(const char *uniform, uint offset, uint count, float elements[count]) {
_r_uniform_ptr_float_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_vec2(Uniform *uniform, float x, float y) {
_r_uniform_ptr_vec2_vec(uniform, (vec2_noalign) { x, y });
}
void _r_uniform_vec2(const char *uniform, float x, float y) {
_r_uniform_vec2_vec(uniform, (vec2_noalign) { x, y });
}
void _r_uniform_ptr_vec2_vec(Uniform *uniform, vec2_noalign value) {
ASSERT_UTYPE(uniform, UNIFORM_VEC2);
if(uniform) B.uniform(uniform, 0, 1, value);
}
void _r_uniform_vec2_vec(const char *uniform, vec2_noalign value) {
_r_uniform_ptr_vec2_vec(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_vec2_complex(Uniform *uniform, complex value) {
ASSERT_UTYPE(uniform, UNIFORM_VEC2);
if(uniform) B.uniform(uniform, 0, 1, (vec2_noalign) { creal(value), cimag(value) });
}
void _r_uniform_vec2_complex(const char *uniform, complex value) {
_r_uniform_ptr_vec2_complex(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_vec2_array(Uniform *uniform, uint offset, uint count, vec2_noalign elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_VEC2);
if(uniform && count) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_vec2_array(const char *uniform, uint offset, uint count, vec2_noalign elements[count]) {
_r_uniform_ptr_vec2_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_vec2_array_complex(Uniform *uniform, uint offset, uint count, complex elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_VEC2);
if(uniform && count) {
float arr[2 * count];
complex *eptr = elements;
float *aptr = arr, *aend = arr + sizeof(arr)/sizeof(*arr);
do {
*aptr++ = creal(*eptr);
*aptr++ = cimag(*eptr++);
} while(aptr < aend);
B.uniform(uniform, offset, count, arr);
}
}
void _r_uniform_vec2_array_complex(const char *uniform, uint offset, uint count, complex elements[count]) {
_r_uniform_ptr_vec2_array_complex(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_vec3(Uniform *uniform, float x, float y, float z) {
ASSERT_UTYPE(uniform, UNIFORM_VEC3);
if(uniform) B.uniform(uniform, 0, 1, (vec3_noalign) { x, y, z });
}
void _r_uniform_vec3(const char *uniform, float x, float y, float z) {
_r_uniform_ptr_vec3(r_shader_current_uniform(uniform), x, y, z);
}
void _r_uniform_ptr_vec3_vec(Uniform *uniform, vec3_noalign value) {
ASSERT_UTYPE(uniform, UNIFORM_VEC3);
if(uniform) B.uniform(uniform, 0, 1, value);
}
void _r_uniform_vec3_vec(const char *uniform, vec3_noalign value) {
_r_uniform_ptr_vec3_vec(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_vec3_rgb(Uniform *uniform, const Color *rgb) {
_r_uniform_ptr_vec3(uniform, rgb->r, rgb->g, rgb->b);
}
void _r_uniform_vec3_rgb(const char *uniform, const Color *rgb) {
_r_uniform_ptr_vec3_rgb(r_shader_current_uniform(uniform), rgb);
}
void _r_uniform_ptr_vec3_array(Uniform *uniform, uint offset, uint count, vec3_noalign elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_VEC3);
if(uniform) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_vec3_array(const char *uniform, uint offset, uint count, vec3_noalign elements[count]) {
_r_uniform_ptr_vec3_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_vec4(Uniform *uniform, float x, float y, float z, float w) {
ASSERT_UTYPE(uniform, UNIFORM_VEC4);
if(uniform) B.uniform(uniform, 0, 1, (vec4_noalign) { x, y, z, w });
}
void _r_uniform_vec4(const char *uniform, float x, float y, float z, float w) {
_r_uniform_ptr_vec4(r_shader_current_uniform(uniform), x, y, z, w);
}
void _r_uniform_ptr_vec4_vec(Uniform *uniform, vec4_noalign value) {
ASSERT_UTYPE(uniform, UNIFORM_VEC4);
if(uniform) B.uniform(uniform, 0, 1, value);
}
void _r_uniform_vec4_vec(const char *uniform, vec4_noalign value) {
_r_uniform_ptr_vec4_vec(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_vec4_rgba(Uniform *uniform, const Color *rgba) {
_r_uniform_ptr_vec4(uniform, rgba->r, rgba->g, rgba->b, rgba->a);
}
void _r_uniform_vec4_rgba(const char *uniform, const Color *rgba) {
_r_uniform_ptr_vec4_rgba(r_shader_current_uniform(uniform), rgba);
}
void _r_uniform_ptr_vec4_array(Uniform *uniform, uint offset, uint count, vec4_noalign elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_VEC4);
if(uniform) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_vec4_array(const char *uniform, uint offset, uint count, vec4_noalign elements[count]) {
_r_uniform_ptr_vec4_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_mat3(Uniform *uniform, mat3_noalign value) {
ASSERT_UTYPE(uniform, UNIFORM_MAT3);
if(uniform) B.uniform(uniform, 0, 1, value);
}
void _r_uniform_mat3(const char *uniform, mat3_noalign value) {
_r_uniform_ptr_mat3(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_mat3_array(Uniform *uniform, uint offset, uint count, mat3_noalign elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_MAT3);
if(uniform) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_mat3_array(const char *uniform, uint offset, uint count, mat3_noalign elements[count]) {
_r_uniform_ptr_mat3_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_mat4(Uniform *uniform, mat4_noalign value) {
ASSERT_UTYPE(uniform, UNIFORM_MAT4);
if(uniform) B.uniform(uniform, 0, 1, value);
}
void _r_uniform_mat4(const char *uniform, mat4_noalign value) {
_r_uniform_ptr_mat4(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_mat4_array(Uniform *uniform, uint offset, uint count, mat4_noalign elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_MAT4);
if(uniform) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_mat4_array(const char *uniform, uint offset, uint count, mat4_noalign elements[count]) {
_r_uniform_ptr_mat4_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_int(Uniform *uniform, int value) {
ASSERT_UTYPE(uniform, UNIFORM_INT);
if(uniform) B.uniform(uniform, 0, 1, &value);
}
void _r_uniform_int(const char *uniform, int value) {
_r_uniform_ptr_int(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_int_array(Uniform *uniform, uint offset, uint count, int elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_INT);
if(uniform) B.uniform(uniform, offset, count, elements);
}
void _r_uniform_int_array(const char *uniform, uint offset, uint count, int elements[count]) {
_r_uniform_ptr_int_array(r_shader_current_uniform(uniform), offset, count, elements);
}
void _r_uniform_ptr_ivec2(Uniform *uniform, int x, int y) {
_r_uniform_ptr_ivec2_vec(uniform, (ivec2_noalign) { x, y });
}
void _r_uniform_ivec2(const char *uniform, int x, int y) {
_r_uniform_ivec2_vec(uniform, (ivec2_noalign) { x, y });
}
void _r_uniform_ptr_ivec2_vec(Uniform *uniform, ivec2_noalign value) {
ASSERT_UTYPE(uniform, UNIFORM_IVEC2);
if(uniform) B.uniform(uniform, 0, 1, value);
}
void _r_uniform_ivec2_vec(const char *uniform, ivec2_noalign value) {
_r_uniform_ptr_ivec2_vec(r_shader_current_uniform(uniform), value);
}
void _r_uniform_ptr_ivec2_array(Uniform *uniform, uint offset, uint count, ivec2_noalign elements[count]) {
ASSERT_UTYPE(uniform, UNIFORM_IVEC2);
if(uniform && count) B.uniform(uniform, offset, count, elements);
}