[RELEASE] u22-v03

This version is submitted to U22 breau.
This commit is contained in:
2020-09-14 00:00:00 +00:00
parent 360595de37
commit 84c3a02b9a
357 changed files with 29223 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
add_library(loshader
backwall.c
bullet.c
character.c
cinescope.c
combat_ring.c
event_line.c
fog.c
ground.c
hud_bar.c
hud_text.c
menu_background.c
menu_stance.c
menu_text.c
pixsort.c
posteffect.c
set.c
uniblock.c
)
target_any_sources(loshader
backwall.vshader
backwall.fshader
bullet.vshader
bullet.fshader
character.vshader
character.fshader
cinescope.vshader
cinescope.fshader
combat_ring.vshader
combat_ring.fshader
event_line.vshader
event_line.fshader
fog.vshader
fog.fshader
ground.vshader
ground.fshader
header.shader
hud_bar.vshader
hud_bar.fshader
hud_text.vshader
hud_text.fshader
menu_background.vshader
menu_background.fshader
menu_stance.vshader
menu_stance.fshader
menu_text.vshader
menu_text.fshader
pixsort.vshader
pixsort.fshader
posteffect.vshader
posteffect.fshader
)
target_link_libraries(loshader
GLEW::GLEW
OpenGL::GL
gleasy
glyphas
math
memory
locommon
)

118
core/loshader/backwall.c Normal file
View File

@@ -0,0 +1,118 @@
#include "./backwall.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/backwall.vshader.h"
#include "anysrc/backwall.fshader.h"
struct loshader_backwall_drawer_t {
const loshader_backwall_program_t* prog;
const loshader_uniblock_t* uniblock;
gleasy_buffer_uniform_t param;
};
#pragma pack(push, 1)
typedef struct {
float type;
float prev_type;
float transition;
} loshader_backwall_drawer_internal_param_t;
_Static_assert(
sizeof(float)*3 ==
sizeof(loshader_backwall_drawer_internal_param_t));
#pragma pack(pop)
#define LOSHADER_BACKWALL_UNIBLOCK_INDEX 0
#define LOSHADER_BACKWALL_PARAM_INDEX 1
#define LOSHADER_BACKWALL_PRIMITIVE_COUNT 6
void loshader_backwall_program_initialize(loshader_backwall_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_backwall_vshader_, sizeof(loshader_backwall_vshader_),
loshader_backwall_fshader_, sizeof(loshader_backwall_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_BACKWALL_UNIBLOCK_INDEX);
const GLuint param = glGetUniformBlockIndex(*prog, "param");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, param, LOSHADER_BACKWALL_PARAM_INDEX);
}
void loshader_backwall_program_deinitialize(loshader_backwall_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_backwall_drawer_t* loshader_backwall_drawer_new(
const loshader_backwall_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_backwall_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glGenBuffers(1, &drawer->param);
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferData(GL_UNIFORM_BUFFER,
sizeof(loshader_backwall_drawer_internal_param_t), NULL, GL_DYNAMIC_DRAW);
return drawer;
}
void loshader_backwall_drawer_delete(loshader_backwall_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->param);
memory_delete(drawer);
}
void loshader_backwall_drawer_set_param(
loshader_backwall_drawer_t* drawer,
const loshader_backwall_drawer_param_t* param) {
assert(drawer != NULL);
assert(param != NULL);
const loshader_backwall_drawer_internal_param_t p = {
.type = param->type,
.prev_type = param->prev_type,
.transition = param->transition,
};
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(p), &p);
}
void loshader_backwall_drawer_draw(const loshader_backwall_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_BACKWALL_UNIBLOCK_INDEX);
glBindBufferBase(GL_UNIFORM_BUFFER,
LOSHADER_BACKWALL_PARAM_INDEX, drawer->param);
glDrawArrays(GL_TRIANGLES, 0, LOSHADER_BACKWALL_PRIMITIVE_COUNT);
}

View File

@@ -0,0 +1,220 @@
layout(std140) uniform param {
float type;
float prev_type;
float transition;
} p;
in vec2 v_uv;
out vec4 o_color;
const float EPSILON = 1e-4;
const float INF = 1e+2;
/* ---- UTILITY FUNCTIONS ---- */
vec3 get_ray_direction(in vec2 p, in vec2 s, float fov) {
return normalize(vec3(p*s/2., s.y/tan(radians(fov)/2.)));
}
mat2 rot(in float theta) {
float c = cos(theta);
float s = sin(theta);
return mat2(c, -s, s, c);
}
#define get_normal(sdf, d, p) \
normalize(d - vec3( \
sdf(p-vec3(EPSILON, 0., 0.)), \
sdf(p-vec3(0., EPSILON, 0.)), \
sdf(p-vec3(0., 0., EPSILON))))
/* ---- SIGNED DISTANCE FUNCTIONS ---- */
/* https://iquilezles.org/www/articles/distfunctions/distfunctions.htm */
float sd_box( vec3 p, vec3 b ) {
vec3 q = abs(p) - b;
return length(max(q,0.)) + min(max(q.x,max(q.y,q.z)),0.);
}
float sd_round_box( vec3 p, vec3 b, float r ) {
vec3 q = abs(p) - b;
return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;
}
/* ---- SCENE: infinite boxes ---- */
float infinite_boxes_sd_scene(in vec3 p) {
p = abs(p);
p = mod(p, 2.) - 1.;
return sd_box(p, vec3(.5));
}
vec3 infinite_boxes_raymarch(in vec2 uv, in vec3 eye) {
vec3 dir = get_ray_direction(uv, uni.resolution, 60.);
float h = 2., d, i;
for (i = 0.; i < 100.; ++i) {
d = infinite_boxes_sd_scene(eye + dir*h);
if (d < EPSILON || h > 100.) break;
h += d;
}
float a = 45./(i+1.)/h;
return mix(vec3(.3, .3, .4), vec3(.6, .8, .7), clamp(a, 0., 1.));
}
vec4 infinite_boxes(void) {
vec2 e2 = vec2(0., 1.) / uni.resolution;
vec3 eye = vec3(0., fract(uni.time/60.)*2., 0.);
eye.xy += fract(uni.pos.xy/2.)*2. + uni.pos.zw - vec2(.5, .5);
vec3 col = infinite_boxes_raymarch(v_uv, eye);
vec3 scol =
infinite_boxes_raymarch(v_uv + e2, eye) +
infinite_boxes_raymarch(v_uv - e2, eye);
scol /= 2.;
return vec4(mix(col, scol, .5), 1.);
}
/* ---- SCENE: HOLLOW MOUNTAINS ---- */
float hollow_mountains_sd_scene(in vec3 p, in vec3 v) {
float s = 8., r;
p = abs(mod(p, 2.) - 1.)*2.;
for (float i = 0.; i < 5.; ++i) {
p = 1. - abs(p-v);
r = 1.4/dot(p, p);
s *= r;
p *= r;
}
return length(p)/s;
}
vec4 hollow_mountains(in vec3 color) {
vec3 dir = get_ray_direction(v_uv, uni.resolution, 60.);
vec3 eye = vec3(0., 0., 0.);
eye.xy = fract(uni.pos.xy/2.)*2. + uni.pos.zw;
float t = abs(fract(uni.time/20.)*2.-1.);
t = t*t*(3.-2.*t);
vec3 v = vec3(.9, 1., .94+t*.1);
float h = 1.3, d, i;
for (i = 0.; i < 60.; ++i) {
d = hollow_mountains_sd_scene(eye + dir*h, v);
if (d < EPSILON || h > 100.) break;
h += d;
}
float a = 200./(i+1.)/h;
return vec4(mix(vec3(.2, .2, .2), color, a), 1.);
}
/* ---- SCENE: JAIL ---- */
float jail_sd_scene(in vec3 p) {
p = mod(p, 2.) - 1.;
float dist = INF;
for (float i = 0.; i < 7.; ++i) {
float t = PI/6.*i*2.;
vec3 p2 = p;
p2.x += cos(t)*.1;
p2.xz *= rot(t);
p2.y += .4*(i-3.);
dist = min(dist, sd_box(p2, vec3(.19)));
}
return dist;
}
vec3 jail_raymarch(in vec2 uv, in vec3 eye) {
vec3 dir = get_ray_direction(uv, uni.resolution.xy, 60.);
float h = 1.6, d, i;
for (i = 0.; i < 20.; ++i) {
d = jail_sd_scene(eye + dir*h);
if (d < EPSILON || h > INF) break;
h += d;
}
vec3 p = eye + dir*h;
vec3 norm = get_normal(jail_sd_scene, d, p);
float diffuse = clamp(dot(vec3(0., 0., 1.), norm), 0., 1.);
float a = 3. + diffuse*.7;
a /= pow(h*.3, 2.) * (i*.2+1.);
a = clamp(a, 0., 1.);
return mix(vec3(.2, .3, .3), vec3(.4, .4, .5), a) + vec3(.7, .4, .4)*a;
}
vec4 jail(void) {
vec2 e1 = vec2(1., 0.)/uni.resolution.xy;
vec2 e2 = vec2(0., 1.)/uni.resolution.xy;
vec3 eye = vec3(0., 0., -4.);
eye.xy += fract(uni.pos.xy/2.)*2. + uni.pos.zw + vec2(.5, .5);
vec3 col = jail_raymarch(v_uv, eye);
vec3 scol =
jail_raymarch(v_uv + e1 + e2, eye) +
jail_raymarch(v_uv + e1 - e2, eye) +
jail_raymarch(v_uv - e1 + e2, eye) +
jail_raymarch(v_uv - e1 - e2, eye);
scol /= 4.;
return vec4(mix(col, scol, .5), 1.);
}
/* ---- SCENE: fabric ---- */
float fabric_sd_rope(in vec3 p) {
p.yz *= rot(PI/8. + p.x*PI);
return sd_round_box(p, vec3(2.5, .2, .2), .03);
}
float fabric_sd_scene(in vec3 p) {
p = mod(p, 4.) - 2.;
vec3 p2 = p/sqrt(2.);
p2.xy *= rot(PI/4.);
p2.y = mod(p2.y, 2.) - 1.;
float dist = fabric_sd_rope(p2);
p2 = p/sqrt(2.);
p2.xy *= rot(-PI/4.);
p2.y = mod(p2.y, 2.) - 1.;
dist = min(dist, fabric_sd_rope(p2));
return dist;
}
vec4 fabric(void) {
vec3 dir = get_ray_direction(v_uv, uni.resolution.xy, 80.);
vec3 eye = vec3(0., 0., -4.);
eye.xy += uni.pos.zw*4.;
float h = 4.5, d, i;
for (i = 0.; i < 50.; ++i) {
d = fabric_sd_scene(eye + dir*h);
if (d < EPSILON || h > INF) break;
h += d;
}
vec3 norm = get_normal(fabric_sd_scene, h, eye + dir*h);
float diffuse = clamp(dot(vec3(0., 0., -1.), norm), .5, 1.);
float a = diffuse*.9 - .3;
a /= pow(h*.08, 2.) * (i*.3+.5);
a = clamp(a, 0., 1.);
vec3 col = mix(vec3(.25, .3, .2), vec3(.4, .6, .7), a) + vec3(1., .0, .0)*a;
return vec4(col, 1.);
}
vec4 scene(in float type) {
return
type == 1.? infinite_boxes():
type == 2.? hollow_mountains(vec3(.1, .4, .1)):
type == 3.? hollow_mountains(vec3(.4, .1, .1)):
type == 4.? jail():
type == 5.? fabric():
vec4(1.);
}
void main(void) {
vec4 prev = vec4(0.), next = vec4(0.);
if (p.transition > 0.) next = clamp(scene(p.type), 0., 1.);
if (p.transition < 1.) prev = clamp(scene(p.prev_type), 0., 1.);
o_color = mix(prev, next, p.transition);
}

60
core/loshader/backwall.h Normal file
View File

@@ -0,0 +1,60 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_backwall_program_t;
struct loshader_backwall_drawer_t;
typedef struct loshader_backwall_drawer_t loshader_backwall_drawer_t;
typedef enum {
LOSHADER_BACKWALL_TYPE_WHITE = 0,
LOSHADER_BACKWALL_TYPE_INFINITE_BOXES = 1,
LOSHADER_BACKWALL_TYPE_HOLLOW_MOUNTAINS = 2,
LOSHADER_BACKWALL_TYPE_HOLLOW_MOUNTAINS_RED = 3,
LOSHADER_BACKWALL_TYPE_JAIL = 4,
LOSHADER_BACKWALL_TYPE_FABRIC = 5,
} loshader_backwall_type_t;
typedef struct {
loshader_backwall_type_t type;
loshader_backwall_type_t prev_type;
float transition;
} loshader_backwall_drawer_param_t;
void
loshader_backwall_program_initialize(
loshader_backwall_program_t* prog
);
void
loshader_backwall_program_deinitialize(
loshader_backwall_program_t* prog
);
loshader_backwall_drawer_t*
loshader_backwall_drawer_new(
const loshader_backwall_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_backwall_drawer_delete(
loshader_backwall_drawer_t* drawer
);
void
loshader_backwall_drawer_set_param(
loshader_backwall_drawer_t* drawer,
const loshader_backwall_drawer_param_t* param
);
void
loshader_backwall_drawer_draw(
const loshader_backwall_drawer_t* drawer
);

View File

@@ -0,0 +1,11 @@
out vec2 v_uv;
void main(void) {
const vec2[] verts = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., -1.),
vec2(-1., 1.), vec2( 1., -1.), vec2( 1., 1.)
);
v_uv = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
gl_Position = vec4(v_uv, 0., 1.);
}

191
core/loshader/bullet.c Normal file
View File

@@ -0,0 +1,191 @@
#include "./bullet.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/bullet.vshader.h"
#include "anysrc/bullet.fshader.h"
#define LOSHADER_BULLET_VSHADER_IN_BULLET_ID 0
#define LOSHADER_BULLET_VSHADER_IN_POS 1
#define LOSHADER_BULLET_VSHADER_IN_SIZE 2
#define LOSHADER_BULLET_VSHADER_IN_THETA 3
#define LOSHADER_BULLET_VSHADER_IN_TIME 4
#define LOSHADER_BULLET_VSHADER_IN_COLOR 5
struct loshader_bullet_drawer_t {
const loshader_bullet_program_t* prog;
const loshader_uniblock_t* uniblock;
GLuint vao;
gleasy_buffer_array_t instances;
size_t instances_reserved;
size_t instances_length;
};
#pragma pack(push, 1)
typedef struct {
uint16_t bullet_id;
vec2_t pos;
vec2_t size;
float theta;
float time;
vec4_t color;
} loshader_bullet_drawer_internal_instance_t;
#pragma pack(pop)
#define LOSHADER_BULLET_UNIBLOCK_INDEX 0
#define LOSHADER_BULLET_PRIMITIVE_COUNT 6
static void loshader_bullet_program_setup_vao_(
gleasy_buffer_array_t instances) {
assert(instances != 0);
glBindBuffer(GL_ARRAY_BUFFER, instances);
# define enable_attrib_(NAME, name, dim, type) do { \
glEnableVertexAttribArray(LOSHADER_BULLET_VSHADER_IN_##NAME); \
glVertexAttribPointer( \
LOSHADER_BULLET_VSHADER_IN_##NAME, dim, type, GL_FALSE, \
sizeof(loshader_bullet_drawer_internal_instance_t), \
NULL + offsetof(loshader_bullet_drawer_internal_instance_t, name)); \
glVertexAttribDivisor(LOSHADER_BULLET_VSHADER_IN_##NAME, 1); \
} while (0)
enable_attrib_(BULLET_ID, bullet_id, 1, GL_UNSIGNED_SHORT);
enable_attrib_(POS, pos, 2, GL_FLOAT);
enable_attrib_(SIZE, size, 2, GL_FLOAT);
enable_attrib_(THETA, theta, 1, GL_FLOAT);
enable_attrib_(TIME, time, 1, GL_FLOAT);
enable_attrib_(COLOR, color, 4, GL_FLOAT);
# undef enable_attrib_
}
void loshader_bullet_program_initialize(loshader_bullet_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_bullet_vshader_, sizeof(loshader_bullet_vshader_),
loshader_bullet_fshader_, sizeof(loshader_bullet_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_BULLET_UNIBLOCK_INDEX);
}
void loshader_bullet_program_deinitialize(loshader_bullet_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_bullet_drawer_t* loshader_bullet_drawer_new(
const loshader_bullet_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_bullet_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glCreateVertexArrays(1, &drawer->vao);
glBindVertexArray(drawer->vao);
glGenBuffers(1, &drawer->instances);
loshader_bullet_program_setup_vao_(drawer->instances);
return drawer;
}
void loshader_bullet_drawer_delete(loshader_bullet_drawer_t* drawer) {
assert(drawer != NULL);
glDeleteBuffers(1, &drawer->instances);
glDeleteVertexArrays(1, &drawer->vao);
memory_delete(drawer);
}
void loshader_bullet_drawer_clear(
loshader_bullet_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
drawer->instances_length = 0;
if (drawer->instances_reserved < reserve) {
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferData(GL_ARRAY_BUFFER,
reserve * sizeof(loshader_bullet_drawer_internal_instance_t),
NULL, GL_DYNAMIC_DRAW);
drawer->instances_reserved = reserve;
}
}
void loshader_bullet_drawer_add_instance(
loshader_bullet_drawer_t* drawer,
const loshader_bullet_drawer_instance_t* instance) {
assert(drawer != NULL);
assert(instance != NULL);
if (drawer->instances_length >= drawer->instances_reserved) {
fprintf(stderr, "bullet drawer instance overflow\n");
abort();
}
const loshader_bullet_drawer_internal_instance_t insta = {
.bullet_id = instance->bullet_id,
.pos = instance->pos,
.size = instance->size,
.theta = instance->theta,
.time = instance->time,
.color = instance->color,
};
const size_t offset = drawer->instances_length * sizeof(insta);
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(insta), &insta);
++drawer->instances_length;
}
void loshader_bullet_drawer_draw(const loshader_bullet_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->instances_length == 0) return;
glUseProgram(*drawer->prog);
glBindVertexArray(drawer->vao);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_BULLET_UNIBLOCK_INDEX);
glDrawArraysInstanced(GL_TRIANGLES,
0, LOSHADER_BULLET_PRIMITIVE_COUNT, drawer->instances_length);
}

View File

@@ -0,0 +1,53 @@
in vec2 v_aa;
in float v_bullet_id;
in vec2 v_uv;
in vec2 v_size;
in float v_time;
in vec4 v_color;
out vec4 o_color;
float dot(in vec2 p, in vec2 q) {
return p.x*q.y - p.y*q.x;
}
vec4 light(void) {
vec4 color = v_color;
color.a *= 1.-pow(length(v_uv), 1.5);
return color;
}
vec4 square(void) {
vec4 color = v_color;
float t = 1.-v_time;
vec2 uv = abs(v_uv);
color.a *= max(step(t-v_aa.x, uv.x), step(t-v_aa.y, uv.y));
return color;
}
vec4 triangle(void) {
const vec2 disp = vec2(-1./12., 0.);
float t = 1. - v_time;
vec2 v1 = vec2( 1., 0.)*t + disp*v_time;
vec2 v2 = vec2(-1., -1.)*t + disp*v_time;
vec2 v3 = vec2(-1., 1.)*t + disp*v_time;
float b1 = dot(v_uv-v2, v1-v2);
float b2 = dot(v_uv-v3, v2-v3);
float b3 = dot(v_uv-v1, v3-v1);
vec4 color = v_color;
color.a *= b1*b2 > 0. && b2*b3 > 0.? 0.: 1.;
return color;
}
void main(void) {
o_color =
v_bullet_id == 0.? light():
v_bullet_id == 1.? square():
v_bullet_id == 2.? triangle():
vec4(0.);
}

68
core/loshader/bullet.h Normal file
View File

@@ -0,0 +1,68 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_bullet_program_t;
struct loshader_bullet_drawer_t;
typedef struct loshader_bullet_drawer_t loshader_bullet_drawer_t;
typedef enum {
LOSHADER_BULLET_ID_LIGHT = 0,
LOSHADER_BULLET_ID_SQUARE = 1,
LOSHADER_BULLET_ID_TRIANGLE = 2,
} loshader_bullet_id_t;
typedef struct {
loshader_bullet_id_t bullet_id;
vec2_t pos;
vec2_t size;
float theta;
float time;
vec4_t color;
} loshader_bullet_drawer_instance_t;
void
loshader_bullet_program_initialize(
loshader_bullet_program_t* prog
);
void
loshader_bullet_program_deinitialize(
loshader_bullet_program_t* prog
);
loshader_bullet_drawer_t*
loshader_bullet_drawer_new(
const loshader_bullet_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_bullet_drawer_delete(
loshader_bullet_drawer_t* drawer
);
void
loshader_bullet_drawer_clear(
loshader_bullet_drawer_t* drawer,
size_t reserve
);
void
loshader_bullet_drawer_add_instance(
loshader_bullet_drawer_t* drawer,
const loshader_bullet_drawer_instance_t* instance
);
void
loshader_bullet_drawer_draw(
const loshader_bullet_drawer_t* drawer
);

View File

@@ -0,0 +1,52 @@
layout (location = 0) in float i_bullet_id;
layout (location = 1) in vec2 i_pos;
layout (location = 2) in vec2 i_size;
layout (location = 3) in float i_theta;
layout (location = 4) in float i_time;
layout (location = 5) in vec4 i_color;
out vec2 v_aa;
out float v_bullet_id;
out vec2 v_uv;
out vec2 v_size;
out float v_time;
out vec4 v_color;
mat2 rot(in float theta) {
float c = cos(theta);
float s = sin(theta);
return mat2(c, -s, s, c);
}
vec2 square(void) {
const vec2[] verts = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., -1.),
vec2(-1., 1.), vec2( 1., -1.), vec2( 1., 1.)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 triangle(void) {
const vec2[] verts = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., 0.)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
void main(void) {
v_bullet_id = i_bullet_id;
v_time = i_time;
v_color = i_color;
v_aa = uni.aa / (uni.proj * uni.cam * vec4(i_size, 0., 0.)).xy;
v_uv =
i_bullet_id == 0.? square():
i_bullet_id == 1.? square():
i_bullet_id == 2.? triangle():
vec2(0.);
v_size = i_size;
gl_Position = uni.proj * uni.cam *
vec4(rot(-i_theta)*(v_uv*i_size) + i_pos, 0., 1.);
}

205
core/loshader/character.c Normal file
View File

@@ -0,0 +1,205 @@
#include "./character.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/character.vshader.h"
#include "anysrc/character.fshader.h"
#define LOSHADER_CHARACTER_VSHADER_IN_CHARACTER_ID 0
#define LOSHADER_CHARACTER_VSHADER_IN_FROM_MOTION_ID 1
#define LOSHADER_CHARACTER_VSHADER_IN_TO_MOTION_ID 2
#define LOSHADER_CHARACTER_VSHADER_IN_MOTION_TIME 3
#define LOSHADER_CHARACTER_VSHADER_IN_MARKER 4
#define LOSHADER_CHARACTER_VSHADER_IN_MARKER_OFFSET 5
#define LOSHADER_CHARACTER_VSHADER_IN_POS 6
#define LOSHADER_CHARACTER_VSHADER_IN_SIZE 7
#define LOSHADER_CHARACTER_VSHADER_IN_COLOR 8
struct loshader_character_drawer_t {
const loshader_character_program_t* prog;
const loshader_uniblock_t* uniblock;
GLuint vao;
gleasy_buffer_array_t instances;
size_t instances_reserved;
size_t instances_length;
};
#pragma pack(push, 1)
typedef struct {
uint16_t character_id;
uint16_t from_motion_id;
uint16_t to_motion_id;
float motion_time;
float marker;
vec2_t marker_offset;
vec2_t pos;
vec2_t size;
vec4_t color;
} loshader_character_drawer_internal_instance_t;
#pragma pack(pop)
#define LOSHADER_CHARACTER_UNIBLOCK_INDEX 0
#define LOSHADER_CHARACTER_PRIMITIVE_COUNT 54
static void loshader_character_program_setup_vao_(
const loshader_character_program_t* prog, gleasy_buffer_array_t instances) {
assert(prog != NULL);
assert(instances != 0);
glBindBuffer(GL_ARRAY_BUFFER, instances);
# define enable_attrib_(NAME, name, dim, type) do { \
glEnableVertexAttribArray(LOSHADER_CHARACTER_VSHADER_IN_##NAME); \
glVertexAttribPointer( \
LOSHADER_CHARACTER_VSHADER_IN_##NAME, dim, type, GL_FALSE, \
sizeof(loshader_character_drawer_internal_instance_t), \
NULL + offsetof(loshader_character_drawer_internal_instance_t, name)); \
glVertexAttribDivisor(LOSHADER_CHARACTER_VSHADER_IN_##NAME, 1); \
} while (0)
enable_attrib_(CHARACTER_ID, character_id, 1, GL_UNSIGNED_SHORT);
enable_attrib_(FROM_MOTION_ID, from_motion_id, 1, GL_UNSIGNED_SHORT);
enable_attrib_(TO_MOTION_ID, to_motion_id, 1, GL_UNSIGNED_SHORT);
enable_attrib_(MOTION_TIME, motion_time, 1, GL_FLOAT);
enable_attrib_(MARKER, marker, 1, GL_FLOAT);
enable_attrib_(MARKER_OFFSET, marker_offset, 2, GL_FLOAT);
enable_attrib_(POS, pos, 2, GL_FLOAT);
enable_attrib_(SIZE, size, 2, GL_FLOAT);
enable_attrib_(COLOR, color, 4, GL_FLOAT);
# undef enable_attrib_
}
void loshader_character_program_initialize(loshader_character_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_character_vshader_, sizeof(loshader_character_vshader_),
loshader_character_fshader_, sizeof(loshader_character_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_CHARACTER_UNIBLOCK_INDEX);
}
void loshader_character_program_deinitialize(
loshader_character_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_character_drawer_t* loshader_character_drawer_new(
const loshader_character_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_character_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glGenBuffers(1, &drawer->instances);
glCreateVertexArrays(1, &drawer->vao);
glBindVertexArray(drawer->vao);
loshader_character_program_setup_vao_(drawer->prog, drawer->instances);
return drawer;
}
void loshader_character_drawer_delete(loshader_character_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->instances);
glDeleteVertexArrays(1, &drawer->vao);
memory_delete(drawer);
}
void loshader_character_drawer_clear(
loshader_character_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
drawer->instances_length = 0;
if (drawer->instances_reserved < reserve) {
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferData(GL_ARRAY_BUFFER,
reserve * sizeof(loshader_character_drawer_internal_instance_t),
NULL, GL_DYNAMIC_DRAW);
drawer->instances_reserved = reserve;
}
}
void loshader_character_drawer_add_instance(
loshader_character_drawer_t* drawer,
const loshader_character_drawer_instance_t* instance) {
assert(drawer != NULL);
assert(instance != NULL);
if (drawer->instances_length >= drawer->instances_reserved) {
fprintf(stderr, "character drawer instance overflow\n");
abort();
}
const loshader_character_drawer_internal_instance_t insta = {
.character_id = instance->character_id,
.from_motion_id = instance->from_motion_id,
.to_motion_id = instance->to_motion_id,
.motion_time = instance->motion_time,
.marker = instance->marker,
.marker_offset = instance->marker_offset,
.pos = instance->pos,
.size = instance->size,
.color = instance->color,
};
const size_t offset = drawer->instances_length * sizeof(insta);
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(insta), &insta);
++drawer->instances_length;
}
void loshader_character_drawer_draw(const loshader_character_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->instances_length == 0) return;
glUseProgram(*drawer->prog);
glBindVertexArray(drawer->vao);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_CHARACTER_UNIBLOCK_INDEX);
glDrawArraysInstanced(GL_TRIANGLES,
0, LOSHADER_CHARACTER_PRIMITIVE_COUNT, drawer->instances_length);
}

View File

@@ -0,0 +1,7 @@
in vec4 v_color;
out vec4 o_color;
void main(void) {
o_color = v_color;
}

85
core/loshader/character.h Normal file
View File

@@ -0,0 +1,85 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_character_program_t;
struct loshader_character_drawer_t;
typedef struct loshader_character_drawer_t loshader_character_drawer_t;
typedef enum {
LOSHADER_CHARACTER_ID_PLAYER = 0,
LOSHADER_CHARACTER_ID_ENCEPHALON = 1,
LOSHADER_CHARACTER_ID_CAVIA = 2,
LOSHADER_CHARACTER_ID_SCIENTIST = 3,
LOSHADER_CHARACTER_ID_WARDER = 4,
} loshader_character_id_t;
typedef enum {
LOSHADER_CHARACTER_MOTION_ID_STAND1 = 0,
LOSHADER_CHARACTER_MOTION_ID_STAND2 = 1,
LOSHADER_CHARACTER_MOTION_ID_WALK = 2,
LOSHADER_CHARACTER_MOTION_ID_ATTACK1 = 3,
LOSHADER_CHARACTER_MOTION_ID_ATTACK2 = 4,
LOSHADER_CHARACTER_MOTION_ID_SIT = 5,
LOSHADER_CHARACTER_MOTION_ID_DOWN = 6,
} loshader_character_motion_id_t;
typedef struct {
loshader_character_id_t character_id;
uint32_t from_motion_id;
uint32_t to_motion_id;
float motion_time;
float marker;
vec2_t marker_offset;
vec2_t pos;
vec2_t size;
vec4_t color;
} loshader_character_drawer_instance_t;
void
loshader_character_program_initialize(
loshader_character_program_t* prog
);
void
loshader_character_program_deinitialize(
loshader_character_program_t* prog
);
loshader_character_drawer_t* /* OWNERSHIP */
loshader_character_drawer_new(
const loshader_character_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_character_drawer_delete(
loshader_character_drawer_t* drawer /* OWNERSHIP */
);
void
loshader_character_drawer_clear(
loshader_character_drawer_t* drawer,
size_t reserve
);
void
loshader_character_drawer_add_instance(
loshader_character_drawer_t* drawer,
const loshader_character_drawer_instance_t* instance
);
void
loshader_character_drawer_draw(
const loshader_character_drawer_t* drawer
);

View File

@@ -0,0 +1,375 @@
layout (location = 0) in float i_character_id;
layout (location = 1) in float i_from_motion_id;
layout (location = 2) in float i_to_motion_id;
layout (location = 3) in float i_motion_time;
layout (location = 4) in float i_marker;
layout (location = 5) in vec2 i_marker_offset;
layout (location = 6) in vec2 i_pos;
layout (location = 7) in vec2 i_size;
layout (location = 8) in vec4 i_color;
out vec4 v_color;
const int vertex_count_ = 54;
const vec2[] marker_ = vec2[](
vec2( 0., 1.), vec2(-1., -1.), vec2( 1., -1.)
);
const vec4 marker_color_ = vec4(1., 1., 1., .6);
vec2 player_stand1(void) {
const vec2[] verts = vec2[](
vec2( 0.125, 0.986), vec2(-0.125, 0.957), vec2( 0.250, 0.900),
vec2(-0.125, 0.957), vec2(-0.175, 0.857), vec2( 0.250, 0.900),
vec2(-0.175, 0.857), vec2(-0.275, 0.571), vec2( 0.075, 0.886),
vec2(-0.050, 0.843), vec2(-0.275, 0.571), vec2( 0.000, 0.371),
vec2( 0.150, 0.843), vec2( 0.150, 0.757), vec2( 0.225, 0.843),
vec2( 0.075, 0.871), vec2( 0.125, 0.757), vec2( 0.125, 0.886),
vec2( 0.075, 0.871), vec2( 0.025, 0.814), vec2( 0.125, 0.757),
vec2( 0.000, 0.786), vec2( 0.000, 0.729), vec2( 0.075, 0.771),
vec2( 0.025, 0.714), vec2( 0.025, 0.386), vec2( 0.200, 0.571),
vec2( 0.125, 0.457), vec2( 0.025, 0.371), vec2( 0.200, 0.157),
vec2(-0.025, 0.371), vec2(-0.200, 0.186), vec2( 0.225, 0.086),
vec2(-0.200, 0.157), vec2( 0.150, -0.371), vec2( 0.225, 0.071),
vec2( 0.150, -0.371), vec2(-0.075, -0.571), vec2( 0.100, -0.857),
vec2( 0.100, -0.857), vec2( 0.000, -1.000), vec2( 0.500, -1.000),
vec2(-0.200, 0.157), vec2( 0.150, -0.371), vec2( 0.225, 0.071),
vec2( 0.150, -0.371), vec2(-0.075, -0.571), vec2( 0.100, -0.857),
vec2( 0.100, -0.857), vec2( 0.000, -1.000), vec2( 0.500, -1.000)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
return p*vec2(4./7., 1.);
}
vec2 player_stand2(void) {
return player_stand1()*vec2(1., .95) + vec2(0., -.05);
}
vec2 player_walk(void) {
const vec2[] verts = vec2[](
vec2( 0.125, 0.986), vec2(-0.125, 0.957), vec2( 0.250, 0.900),
vec2(-0.125, 0.957), vec2(-0.175, 0.857), vec2( 0.250, 0.900),
vec2(-0.175, 0.857), vec2(-0.275, 0.571), vec2( 0.075, 0.886),
vec2(-0.050, 0.843), vec2(-0.275, 0.571), vec2( 0.000, 0.371),
vec2( 0.150, 0.843), vec2( 0.150, 0.757), vec2( 0.225, 0.843),
vec2( 0.075, 0.871), vec2( 0.125, 0.757), vec2( 0.125, 0.886),
vec2( 0.075, 0.871), vec2( 0.025, 0.814), vec2( 0.125, 0.757),
vec2( 0.000, 0.786), vec2( 0.000, 0.729), vec2( 0.075, 0.771),
vec2( 0.025, 0.714), vec2( 0.025, 0.386), vec2( 0.200, 0.571),
vec2( 0.125, 0.457), vec2( 0.025, 0.371), vec2( 0.200, 0.157),
vec2(-0.025, 0.371), vec2(-0.200, 0.186), vec2( 0.225, 0.086),
vec2(-0.200, 0.157), vec2( 0.450, -0.371), vec2( 0.225, 0.071),
vec2( 0.450, -0.371), vec2( 0.325, -0.571), vec2( 0.350, -0.857),
vec2( 0.350, -0.857), vec2( 0.275, -1.000), vec2( 0.950, -1.000),
vec2(-0.200, 0.157), vec2(-0.200, -0.371), vec2( 0.225, 0.071),
vec2(-0.200, -0.371), vec2(-0.450, -0.471), vec2(-0.600, -0.857),
vec2(-0.625, -0.857), vec2(-0.625, -1.000), vec2(-0.250, -1.000)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
return p*vec2(4./7., .95) + vec2(0., -.05);
}
vec2 player(in float motion_id) {
return
(motion_id == 0.)? player_stand1():
(motion_id == 1.)? player_stand2():
(motion_id == 2.)? player_walk():
vec2(0.);
}
vec2 encephalon(in float motion_id) {
const vec2[] verts = vec2[](
vec2(-0.833, -0.783), vec2(-1.000, -1.000), vec2( 1.000, -1.000),
vec2(-.8333, -0.783), vec2( 1.000, -1.000), vec2( 0.833, -0.783),
vec2( 0.117, -0.367), vec2( 0.000, -0.750), vec2( 0.300, -0.533),
vec2( 0.117, 0.050), vec2(-0.083, -0.117), vec2( 0.367, -0.517),
vec2(-0.050, 0.283), vec2(-0.133, -0.117), vec2( 0.117, 0.083),
vec2( 0.500, 0.500), vec2(-0.050, 0.333), vec2( 0.150, 0.133),
vec2( 0.250, 0.917), vec2(-0.233, 0.317), vec2( 0.500, 0.533),
vec2( 0.217, 0.917), vec2(-0.300, 0.817), vec2(-0.283, 0.333),
vec2(-0.333, 0.783), vec2(-0.500, 0.567), vec2(-0.333, 0.333)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 cavia_stand1(void) {
const vec2[] verts = vec2[](
vec2( 0.06, 1.00), vec2(-0.16, 0.72), vec2( 0.36, 0.58),
vec2( 0.00, 0.66), vec2(-0.20, 0.46), vec2(-0.04, 0.20),
vec2( 0.02, 0.58), vec2( 0.00, 0.20), vec2( 0.14, 0.42),
vec2(-0.20, 0.40), vec2(-0.20, 0.12), vec2( 0.12, -0.04),
vec2( 0.06, 0.24), vec2( 0.00, 0.16), vec2( 0.06, 0.08),
vec2(-0.18, 0.08), vec2( 0.06, -0.40), vec2( 0.06, -0.04),
vec2( 0.06, -0.44), vec2(-0.06, -0.58), vec2( 0.08, -0.90),
vec2( 0.08, -0.90), vec2( 0.00, -1.00), vec2( 0.30, -1.00),
vec2(-0.18, 0.08), vec2( 0.06, -0.40), vec2( 0.06, -0.04),
vec2( 0.06, -0.44), vec2(-0.06, -0.58), vec2( 0.08, -0.90),
vec2( 0.08, -0.90), vec2( 0.00, -1.00), vec2( 0.30, -1.00)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 cavia_walk(void) {
const vec2[] verts = vec2[](
vec2( 0.06, 1.00), vec2(-0.16, 0.72), vec2( 0.36, 0.58),
vec2( 0.00, 0.66), vec2(-0.20, 0.46), vec2(-0.04, 0.20),
vec2( 0.02, 0.58), vec2( 0.00, 0.20), vec2( 0.14, 0.42),
vec2(-0.20, 0.40), vec2(-0.20, 0.12), vec2( 0.12, -0.04),
vec2( 0.06, 0.24), vec2( 0.00, 0.16), vec2( 0.06, 0.08),
vec2(-0.18, 0.08), vec2(-0.18, -0.40), vec2( 0.06, -0.04),
vec2(-0.20, -0.42), vec2(-0.36, -0.42), vec2(-0.58, -0.90),
vec2(-0.58, -0.90), vec2(-0.62, -1.00), vec2(-0.32, -1.00),
vec2(-0.18, 0.08), vec2( 0.28, -0.40), vec2( 0.06, -0.04),
vec2( 0.28, -0.40), vec2( 0.20, -0.56), vec2( 0.42, -0.90),
vec2( 0.42, -0.90), vec2( 0.40, -1.00), vec2( 0.70, -1.00)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
return p*vec2(1., .95) + vec2(0., -.05);
}
vec2 cavia_attack1(void) {
return cavia_stand1()*vec2(1., 1.05) + vec2(0., .05);
}
vec2 cavia_attack2(void) {
const vec2[] verts = vec2[](
vec2( 0.18, 0.94), vec2(-0.08, 0.70), vec2( 0.34, 0.46),
vec2( 0.06, 0.64), vec2(-0.20, 0.46), vec2(-0.04, 0.20),
vec2( 0.08, 0.56), vec2( 0.00, 0.20), vec2( 0.14, 0.42),
vec2(-0.20, 0.40), vec2(-0.20, 0.12), vec2( 0.12, -0.04),
vec2( 0.06, 0.24), vec2( 0.00, 0.16), vec2( 0.06, 0.08),
vec2(-0.18, 0.08), vec2( 0.06, -0.40), vec2( 0.06, -0.04),
vec2( 0.06, -0.44), vec2(-0.06, -0.58), vec2( 0.08, -0.90),
vec2( 0.08, -0.90), vec2( 0.00, -1.00), vec2( 0.30, -1.00),
vec2(-0.18, 0.08), vec2( 0.06, -0.40), vec2( 0.06, -0.04),
vec2( 0.06, -0.44), vec2(-0.06, -0.58), vec2( 0.08, -0.90),
vec2( 0.08, -0.90), vec2( 0.00, -1.00), vec2( 0.30, -1.00)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 cavia_sit(void) {
const vec2[] verts = vec2[](
vec2( 0.30, 0.40), vec2( 0.00, 0.18), vec2( 0.58, -0.02),
vec2( 0.12, 0.10), vec2(-0.22, -0.08), vec2(-0.10, -0.28),
vec2( 0.10, -0.02), vec2(-0.08, -0.30), vec2( 0.12, -0.20),
vec2(-0.24, -0.10), vec2(-0.28, -0.38), vec2(-0.04, -0.48),
vec2( 0.04, -0.26), vec2(-0.10, -0.32), vec2(-0.04, -0.42),
vec2(-0.26, -0.42), vec2( 0.00, -1.00), vec2(-0.06, -0.50),
vec2( 0.00, -1.00), vec2(-0.08, -0.86), vec2(-0.50, -0.92),
vec2(-0.50, -0.92), vec2(-0.54, -0.80), vec2(-0.76, -1.00),
vec2(-0.26, -0.42), vec2( 0.00, -1.00), vec2(-0.06, -0.50),
vec2( 0.00, -1.00), vec2(-0.08, -0.86), vec2(-0.50, -0.92),
vec2(-0.50, -0.92), vec2(-0.54, -0.80), vec2(-0.76, -1.00)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 cavia_down(void) {
const vec2[] verts = vec2[](
vec2( 0.78, -0.50), vec2( 0.46, -0.44), vec2( 0.66, -1.00),
vec2( 0.50, -0.58), vec2(-0.16, -0.38), vec2(-0.10, -0.54),
vec2( 0.38, -0.60), vec2(-0.02, -0.56), vec2( 0.24, -0.70),
vec2(-0.20, -0.40), vec2(-0.28, -0.60), vec2(-0.14, -0.60),
vec2(-0.02, -0.60), vec2(-0.10, -0.58), vec2(-0.08, -0.60),
vec2(-0.38, -0.62), vec2( 0.00, -1.00), vec2(-0.16, -0.62),
vec2( 0.00, -1.00), vec2(-0.18, -0.86), vec2(-0.50, -0.92),
vec2(-0.50, -0.92), vec2(-0.54, -0.80), vec2(-0.76, -1.00),
vec2(-0.38, -0.62), vec2( 0.00, -1.00), vec2(-0.16, -0.62),
vec2( 0.00, -1.00), vec2(-0.18, -0.86), vec2(-0.50, -0.92),
vec2(-0.50, -0.92), vec2(-0.54, -0.80), vec2(-0.76, -1.00)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 cavia(in float motion_id) {
return
(motion_id == 0.)? cavia_stand1():
(motion_id == 2.)? cavia_walk():
(motion_id == 3.)? cavia_attack1():
(motion_id == 4.)? cavia_attack2():
(motion_id == 5.)? cavia_sit():
(motion_id == 6.)? cavia_down():
vec2(0.);
}
vec2 scientist_stand1(void) {
const vec2[] verts = vec2[](
vec2(-0.050, 0.982), vec2(-0.150, 0.764), vec2( 0.400, 0.655),
vec2(-0.050, 0.727), vec2(-0.475, 0.436), vec2( 0.225, 0.143),
vec2(-0.475, 0.418), vec2(-0.400, -0.709), vec2( 0.225, 0.127),
vec2( 0.225, 0.111), vec2(-0.400, -0.725), vec2( 0.225, -0.709),
vec2( 0.025, 0.673), vec2( 0.200, 0.255), vec2( 0.175, 0.636),
vec2( 0.000, -0.418), vec2(-0.150, -0.509), vec2(-0.075, -0.909),
vec2(-0.075, -0.909), vec2(-0.150, -1.000), vec2( 0.200, -1.000),
vec2( 0.000, -0.418), vec2(-0.150, -0.509), vec2(-0.075, -0.909),
vec2(-0.075, -0.909), vec2(-0.150, -1.000), vec2( 0.200, -1.000)
);
return gl_VertexID < verts.length()?
verts[gl_VertexID]*vec2(.8, 1.): vec2(0.);
}
vec2 scientist_stand2(void) {
return scientist_stand1() + (gl_VertexID < 5*3? vec2(0., -.05): vec2(0.));
}
vec2 scientist_attack1(void) {
const vec2[] verts = vec2[](
vec2(-0.475, 0.982), vec2(-0.400, 0.727), vec2( 0.225, 0.927),
vec2(-0.225, 0.764), vec2(-0.675, 0.455), vec2( 0.225, 0.127),
vec2(-0.700, 0.418), vec2(-0.400, -0.709), vec2( 0.225, 0.127),
vec2( 0.225, 0.127), vec2(-0.400, -0.709), vec2( 0.350, -0.709),
vec2(-0.125, 0.727), vec2( 0.150, 0.309), vec2( 0.050, 0.691),
vec2( 0.000, -0.418), vec2(-0.150, -0.509), vec2(-0.075, -0.909),
vec2(-0.075, -0.909), vec2(-0.150, -1.000), vec2( 0.200, -1.000),
vec2( 0.000, -0.418), vec2(-0.150, -0.509), vec2(-0.075, -0.909),
vec2(-0.075, -0.909), vec2(-0.150, -1.000), vec2( 0.200, -1.000)
);
return gl_VertexID < verts.length()?
verts[gl_VertexID]*vec2(.8, 1.): vec2(0.);
}
vec2 scientist_sit(void) {
const vec2[] verts = vec2[](
vec2(-0.050, 0.782), vec2(-0.150, 0.564), vec2( 0.400, 0.455),
vec2(-0.050, 0.527), vec2(-0.475, 0.236), vec2( 0.225, -0.143),
vec2(-0.475, 0.218), vec2(-0.400, -0.909), vec2( 0.225, -0.127),
vec2( 0.225, -0.111), vec2(-0.400, -0.925), vec2( 0.225, -0.909),
vec2( 0.025, 0.473), vec2( 0.200, 0.055), vec2( 0.175, 0.436),
vec2( 0.000, -0.418), vec2(-0.150, -0.509), vec2(-0.075, -0.909),
vec2(-0.075, -0.909), vec2(-0.150, -1.000), vec2( 0.200, -1.000),
vec2( 0.000, -0.418), vec2(-0.150, -0.509), vec2(-0.075, -0.909),
vec2(-0.075, -0.909), vec2(-0.150, -1.000), vec2( 0.200, -1.000)
);
return gl_VertexID < verts.length()?
verts[gl_VertexID]*vec2(.8, 1.): vec2(0.);
}
vec2 scientist(in float motion_id) {
return
(motion_id == 0.)? scientist_stand1():
(motion_id == 1.)? scientist_stand2():
(motion_id == 3.)? scientist_attack1():
(motion_id == 5.)? scientist_sit():
vec2(0.);
}
vec2 warder_stand1(void) {
const vec2[] verts = vec2[](
vec2(-0.10, 0.96), vec2(-0.24, 0.76), vec2( 0.22, 0.94),
vec2( 0.08, 0.84), vec2(-0.20, 0.70), vec2( 0.04, 0.70),
vec2(-0.10, 0.68), vec2(-0.24, 0.48), vec2(-0.08, 0.10),
vec2(-0.08, 0.60), vec2(-0.04, 0.12), vec2( 0.06, 0.42),
vec2(-0.22, 0.32), vec2(-0.26, 0.16), vec2(-0.06, 0.04),
vec2( 0.02, 0.20), vec2(-0.04, 0.04), vec2( 0.04, 0.00),
vec2(-0.24, 0.12), vec2( 0.00, -0.40), vec2( 0.06, -0.04),
vec2( 0.00, -0.42), vec2(-0.14, -0.54), vec2( 0.00, -0.90),
vec2( 0.00, -0.90), vec2(-0.04, -1.00), vec2( 0.24, -1.00),
vec2(-0.24, 0.12), vec2( 0.00, -0.40), vec2( 0.06, -0.04),
vec2( 0.00, -0.42), vec2(-0.14, -0.54), vec2( 0.00, -0.90),
vec2( 0.00, -0.90), vec2(-0.04, -1.00), vec2( 0.24, -1.00),
vec2(-0.26, -0.04), vec2(-0.24, -0.08), vec2( 0.58, 0.20)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 warder_walk(void) {
const vec2[] verts = vec2[](
vec2(-0.10, 0.96), vec2(-0.24, 0.76), vec2( 0.22, 0.94),
vec2( 0.08, 0.84), vec2(-0.20, 0.70), vec2( 0.04, 0.70),
vec2(-0.10, 0.68), vec2(-0.24, 0.48), vec2(-0.08, 0.10),
vec2(-0.08, 0.60), vec2(-0.04, 0.12), vec2( 0.06, 0.42),
vec2(-0.22, 0.32), vec2(-0.26, 0.16), vec2(-0.06, 0.04),
vec2( 0.02, 0.20), vec2(-0.04, 0.04), vec2( 0.04, 0.00),
vec2(-0.24, 0.12), vec2(-0.34, -0.40), vec2( 0.06, -0.04),
vec2(-0.34, -0.42), vec2(-0.50, -0.46), vec2(-0.62, -0.90),
vec2(-0.62, -0.90), vec2(-0.66, -1.00), vec2(-0.40, -1.00),
vec2(-0.24, 0.12), vec2( 0.30, -0.40), vec2( 0.06, -0.04),
vec2( 0.30, -0.40), vec2( 0.22, -0.56), vec2( 0.44, -0.90),
vec2( 0.44, -0.90), vec2( 0.40, -1.00), vec2( 0.66, -1.00),
vec2(-0.08, -0.08), vec2(-0.06, -0.12), vec2( 0.74, 0.20)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
return p*vec2(1., .95) + vec2(0., -.05);
}
vec2 warder_attack1(void) {
const vec2[] verts = vec2[](
vec2(-0.10, 0.96), vec2(-0.24, 0.76), vec2( 0.22, 0.94),
vec2( 0.08, 0.84), vec2(-0.20, 0.70), vec2( 0.04, 0.70),
vec2(-0.10, 0.68), vec2(-0.24, 0.48), vec2(-0.08, 0.10),
vec2(-0.08, 0.60), vec2(-0.04, 0.12), vec2( 0.06, 0.42),
vec2(-0.22, 0.32), vec2(-0.26, 0.16), vec2(-0.06, 0.04),
vec2( 0.02, 0.20), vec2(-0.04, 0.04), vec2( 0.04, 0.00),
vec2(-0.24, 0.12), vec2(-0.34, -0.40), vec2( 0.06, -0.04),
vec2(-0.34, -0.42), vec2(-0.50, -0.46), vec2(-0.62, -0.90),
vec2(-0.62, -0.90), vec2(-0.66, -1.00), vec2(-0.40, -1.00),
vec2(-0.24, 0.12), vec2( 0.30, -0.40), vec2( 0.06, -0.04),
vec2( 0.30, -0.40), vec2( 0.22, -0.56), vec2( 0.44, -0.90),
vec2( 0.44, -0.90), vec2( 0.40, -1.00), vec2( 0.66, -1.00),
vec2(-0.56, 0.32), vec2(-0.56, 0.28), vec2( 0.30, 0.30)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
return p*vec2(1., .95) + vec2(0., -.05);
}
vec2 warder_attack2(void) {
const vec2[] verts = vec2[](
vec2(-0.10, 0.96), vec2(-0.24, 0.76), vec2( 0.22, 0.94),
vec2( 0.08, 0.84), vec2(-0.20, 0.70), vec2( 0.04, 0.70),
vec2(-0.10, 0.68), vec2(-0.24, 0.48), vec2(-0.08, 0.10),
vec2(-0.08, 0.60), vec2(-0.04, 0.12), vec2( 0.06, 0.42),
vec2(-0.22, 0.32), vec2(-0.26, 0.16), vec2(-0.06, 0.04),
vec2( 0.02, 0.20), vec2(-0.04, 0.04), vec2( 0.04, 0.00),
vec2(-0.24, 0.12), vec2(-0.34, -0.40), vec2( 0.06, -0.04),
vec2(-0.34, -0.42), vec2(-0.50, -0.46), vec2(-0.62, -0.90),
vec2(-0.62, -0.90), vec2(-0.66, -1.00), vec2(-0.40, -1.00),
vec2(-0.24, 0.12), vec2( 0.30, -0.40), vec2( 0.06, -0.04),
vec2( 0.30, -0.40), vec2( 0.22, -0.56), vec2( 0.44, -0.90),
vec2( 0.44, -0.90), vec2( 0.40, -1.00), vec2( 0.66, -1.00),
vec2( 0.12, 0.32), vec2( 0.12, 0.28), vec2( 0.96, 0.30)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 warder_down(void) {
const vec2[] verts = vec2[](
vec2(-0.80, -1.00), vec2(-0.64, -1.00), vec2(-0.86, -0.62),
vec2(-0.76, -0.72), vec2(-0.58, -1.00), vec2(-0.64, -0.72),
vec2(-0.58, -0.86), vec2(-0.44, -0.98), vec2( 0.00, -0.82),
vec2(-0.50, -0.82), vec2( 0.00, -0.80), vec2(-0.36, -0.70),
vec2(-0.18, -0.92), vec2( 0.04, -1.00), vec2( 0.04, -0.82),
vec2(-0.12, -0.72), vec2( 0.04, -0.80), vec2( 0.04, -0.52),
vec2( 0.06, -1.00), vec2( 0.30, -0.46), vec2( 0.06, -0.54),
vec2( 0.30, -0.46), vec2( 0.30, -0.74), vec2( 0.50, -0.90),
vec2( 0.50, -0.90), vec2( 0.46, -1.00), vec2( 0.70, -1.00),
vec2( 0.06, -1.00), vec2( 0.30, -0.46), vec2( 0.06, -0.54),
vec2( 0.30, -0.46), vec2( 0.30, -0.74), vec2( 0.50, -0.90),
vec2( 0.50, -0.90), vec2( 0.46, -1.00), vec2( 0.70, -1.00),
vec2(-0.06, -0.96), vec2(-0.06, -1.00), vec2( 0.80, -1.00)
);
return gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
}
vec2 warder(in float motion_id) {
return
(motion_id == 0.)? warder_stand1():
(motion_id == 2.)? warder_walk():
(motion_id == 3.)? warder_attack1():
(motion_id == 4.)? warder_attack2():
(motion_id == 6.)? warder_down():
vec2(0.);
}
vec2 get_vert(in float motion_id) {
return
(i_character_id == 0.)? player(motion_id):
(i_character_id == 1.)? encephalon(motion_id):
(i_character_id == 2.)? cavia(motion_id):
(i_character_id == 3.)? scientist(motion_id):
(i_character_id == 4.)? warder(motion_id):
vec2(0.);
}
void main(void) {
if (gl_VertexID < vertex_count_-3) {
v_color = i_color;
vec2 p = mix(
get_vert(i_from_motion_id),
get_vert(i_to_motion_id),
i_motion_time);
gl_Position = uni.proj * uni.cam * vec4(p*i_size+i_pos, 0., 1.);
} else {
v_color = marker_color_;
v_color.a *= i_marker;
vec2 p = marker_[gl_VertexID - (vertex_count_-3)];
p *= uni.dpi*.03 / uni.resolution * 2.;
gl_Position = uni.proj * uni.cam * vec4(i_pos+i_marker_offset, 0., 1.);
gl_Position.xy += p;
}
}

116
core/loshader/cinescope.c Normal file
View File

@@ -0,0 +1,116 @@
#include "./cinescope.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/cinescope.vshader.h"
#include "anysrc/cinescope.fshader.h"
struct loshader_cinescope_drawer_t {
const loshader_cinescope_program_t* prog;
const loshader_uniblock_t* uniblock;
gleasy_buffer_uniform_t param;
};
#pragma pack(push, 1)
typedef struct {
vec4_t color;
float size;
} loshader_cinescope_drawer_internal_param_t;
_Static_assert(
sizeof(float)*5 ==
sizeof(loshader_cinescope_drawer_internal_param_t));
#pragma pack(pop)
#define LOSHADER_CINESCOPE_UNIBLOCK_INDEX 0
#define LOSHADER_CINESCOPE_PARAM_INDEX 1
#define LOSHADER_CINESCOPE_PRIMITIVE_COUNT 12
void loshader_cinescope_program_initialize(loshader_cinescope_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_cinescope_vshader_, sizeof(loshader_cinescope_vshader_),
loshader_cinescope_fshader_, sizeof(loshader_cinescope_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_CINESCOPE_UNIBLOCK_INDEX);
const GLuint param = glGetUniformBlockIndex(*prog, "param");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, param, LOSHADER_CINESCOPE_PARAM_INDEX);
}
void loshader_cinescope_program_deinitialize(loshader_cinescope_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_cinescope_drawer_t* loshader_cinescope_drawer_new(
const loshader_cinescope_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_cinescope_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glGenBuffers(1, &drawer->param);
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferData(GL_UNIFORM_BUFFER,
sizeof(loshader_cinescope_drawer_internal_param_t), NULL, GL_DYNAMIC_DRAW);
return drawer;
}
void loshader_cinescope_drawer_delete(loshader_cinescope_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->param);
memory_delete(drawer);
}
void loshader_cinescope_drawer_set_param(
loshader_cinescope_drawer_t* drawer,
const loshader_cinescope_drawer_param_t* param) {
assert(drawer != NULL);
assert(param != NULL);
const loshader_cinescope_drawer_internal_param_t p = {
.size = param->size,
.color = param->color,
};
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(p), &p);
}
void loshader_cinescope_drawer_draw(const loshader_cinescope_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_CINESCOPE_UNIBLOCK_INDEX);
glBindBufferBase(GL_UNIFORM_BUFFER,
LOSHADER_CINESCOPE_PARAM_INDEX, drawer->param);
glDrawArrays(GL_TRIANGLES, 0, LOSHADER_CINESCOPE_PRIMITIVE_COUNT);
}

View File

@@ -0,0 +1,10 @@
layout(std140) uniform param {
vec4 color;
float size;
} p;
out vec4 o_color;
void main(void) {
o_color = p.color;
}

48
core/loshader/cinescope.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_cinescope_program_t;
struct loshader_cinescope_drawer_t;
typedef struct loshader_cinescope_drawer_t loshader_cinescope_drawer_t;
typedef struct {
float size;
vec4_t color;
} loshader_cinescope_drawer_param_t;
void
loshader_cinescope_program_initialize(
loshader_cinescope_program_t* prog
);
void
loshader_cinescope_program_deinitialize(
loshader_cinescope_program_t* prog
);
loshader_cinescope_drawer_t*
loshader_cinescope_drawer_new(
const loshader_cinescope_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_cinescope_drawer_delete(
loshader_cinescope_drawer_t* drawer
);
void
loshader_cinescope_drawer_set_param(
loshader_cinescope_drawer_t* drawer,
const loshader_cinescope_drawer_param_t* param
);
void
loshader_cinescope_drawer_draw(
const loshader_cinescope_drawer_t* drawer
);

View File

@@ -0,0 +1,22 @@
layout(std140) uniform param {
vec4 color;
float size;
} p;
const vec2[6] rect_ = vec2[](
vec2(-1., 1.),
vec2(-1., 0.),
vec2( 1., 0.),
vec2(-1., 1.),
vec2( 1., 0.),
vec2( 1., 1.)
);
void main(void) {
int id = gl_VertexID < 6? gl_VertexID: gl_VertexID-6;
vec2 p = rect_[id]*vec2(1., p.size) + vec2(0., 1.-p.size);
p.y *= (id == gl_VertexID? 1.: -1.);
gl_Position = vec4(p, 0., 1.);
}

183
core/loshader/combat_ring.c Normal file
View File

@@ -0,0 +1,183 @@
#include "./combat_ring.h"
#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/algorithm.h"
#include "util/math/constant.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/combat_ring.vshader.h"
#include "anysrc/combat_ring.fshader.h"
#define LOSHADER_COMBAT_RING_VSHADER_IN_RANGE 0
#define LOSHADER_COMBAT_RING_VSHADER_IN_PERIOD 1
#define LOSHADER_COMBAT_RING_VSHADER_IN_COLOR 2
struct loshader_combat_ring_drawer_t {
const loshader_combat_ring_program_t* prog;
const loshader_uniblock_t* uniblock;
GLuint vao;
gleasy_buffer_array_t instances;
size_t instances_reserved;
size_t instances_length;
};
#pragma pack(push, 1)
typedef struct {
float range;
vec2_t period; /* x~y */
vec4_t color;
} loshader_combat_ring_drawer_internal_instance_t;
#pragma pack(pop)
#define LOSHADER_COMBAT_RING_UNIBLOCK_INDEX 0
#define LOSHADER_COMBAT_RING_PRIMITIVE_COUNT 6
static void loshader_combat_ring_program_setup_vao_(
gleasy_buffer_array_t instances) {
assert(instances != 0);
glBindBuffer(GL_ARRAY_BUFFER, instances);
glEnableVertexAttribArray(LOSHADER_COMBAT_RING_VSHADER_IN_RANGE);
glVertexAttribPointer(
LOSHADER_COMBAT_RING_VSHADER_IN_RANGE, 1, GL_FLOAT, GL_FALSE,
sizeof(loshader_combat_ring_drawer_internal_instance_t),
NULL + offsetof(loshader_combat_ring_drawer_internal_instance_t, range));
glVertexAttribDivisor(LOSHADER_COMBAT_RING_VSHADER_IN_RANGE, 1);
glEnableVertexAttribArray(LOSHADER_COMBAT_RING_VSHADER_IN_PERIOD);
glVertexAttribPointer(
LOSHADER_COMBAT_RING_VSHADER_IN_PERIOD, 2, GL_FLOAT, GL_FALSE,
sizeof(loshader_combat_ring_drawer_internal_instance_t),
NULL + offsetof(loshader_combat_ring_drawer_internal_instance_t, period));
glVertexAttribDivisor(LOSHADER_COMBAT_RING_VSHADER_IN_PERIOD, 1);
glEnableVertexAttribArray(LOSHADER_COMBAT_RING_VSHADER_IN_COLOR);
glVertexAttribPointer(
LOSHADER_COMBAT_RING_VSHADER_IN_COLOR, 4, GL_FLOAT, GL_FALSE,
sizeof(loshader_combat_ring_drawer_internal_instance_t),
NULL + offsetof(loshader_combat_ring_drawer_internal_instance_t, color));
glVertexAttribDivisor(LOSHADER_COMBAT_RING_VSHADER_IN_COLOR, 1);
}
void loshader_combat_ring_program_initialize(
loshader_combat_ring_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_combat_ring_vshader_, sizeof(loshader_combat_ring_vshader_),
loshader_combat_ring_fshader_, sizeof(loshader_combat_ring_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_COMBAT_RING_UNIBLOCK_INDEX);
}
void loshader_combat_ring_program_deinitialize(
loshader_combat_ring_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_combat_ring_drawer_t* loshader_combat_ring_drawer_new(
const loshader_combat_ring_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_combat_ring_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glCreateVertexArrays(1, &drawer->vao);
glBindVertexArray(drawer->vao);
glGenBuffers(1, &drawer->instances);
loshader_combat_ring_program_setup_vao_(drawer->instances);
return drawer;
}
void loshader_combat_ring_drawer_delete(loshader_combat_ring_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->instances);
glDeleteVertexArrays(1, &drawer->vao);
memory_delete(drawer);
}
void loshader_combat_ring_drawer_clear(
loshader_combat_ring_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
drawer->instances_length = 0;
if (drawer->instances_reserved < reserve) {
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferData(GL_ARRAY_BUFFER,
reserve * sizeof(loshader_combat_ring_drawer_internal_instance_t),
NULL, GL_DYNAMIC_DRAW);
drawer->instances_reserved = reserve;
}
}
void loshader_combat_ring_drawer_add_instance(
loshader_combat_ring_drawer_t* drawer,
const loshader_combat_ring_drawer_instance_t* instance) {
assert(drawer != NULL);
assert(instance != NULL);
if (drawer->instances_length >= drawer->instances_reserved) {
fprintf(stderr, "combat ring drawer instance overflow\n");
abort();
}
const size_t offset = drawer->instances_length *
sizeof(loshader_combat_ring_drawer_internal_instance_t);
const loshader_combat_ring_drawer_internal_instance_t i = {
.range = instance->range,
.period = vec2(instance->start, instance->end),
.color = instance->color,
};
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(i), &i);
++drawer->instances_length;
}
void loshader_combat_ring_drawer_draw(
const loshader_combat_ring_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->instances_length == 0) return;
glUseProgram(*drawer->prog);
glBindVertexArray(drawer->vao);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_COMBAT_RING_UNIBLOCK_INDEX);
glDrawArraysInstanced(GL_TRIANGLES,
0, LOSHADER_COMBAT_RING_PRIMITIVE_COUNT, drawer->instances_length);
}

View File

@@ -0,0 +1,91 @@
in vec2 v_uv;
in float v_aa;
in float v_range;
in vec2 v_period;
in vec4 v_color;
out vec4 o_color;
vec2 uv_;
float len_;
float theta_;
float atan2(in vec2 p) {
return p.x == 0.? PI/2.*sign(p.y): atan(p.y, p.x);
}
float thetadist(in vec2 p, in float t) {
float a = tan(t);
float b = 1.;
if (cos(t) == 0.) {
a = 1.;
b = 0.;
}
return abs(b*p.y-a*p.x)/sqrt(a*a+b*b);
}
float grid(in float n, in float ri, in float ro) {
float u = PI/n;
float t = floor(theta_/u)*u;
float d = min(thetadist(uv_, t), thetadist(uv_, t+u));
return
step(ri, len_)*step(len_, ro)*
smoothstep(v_aa, .0, d);
}
float belt(in float t1, in float t2, in float r) {
float t1a = smoothstep(v_aa, 0., thetadist(uv_, t1))*step(abs(theta_-t1), .1);
float t2a = smoothstep(v_aa, 0., thetadist(uv_, t2))*step(abs(theta_-t2), .1);
float a = t1a + t2a + step(t1, theta_)*step(theta_, t2);
a *=
(t1a + t2a)*smoothstep(.4, .45, len_) +
smoothstep(r-v_aa, r, len_)*
(1.-max(len_-r, 0.)/.2) +
smoothstep(v_aa, 0., abs(len_-.7*r));
return clamp(a, 0., 1.);
}
float circle(in float r) {
return
smoothstep(v_aa, 0., abs(len_-r));
}
float clockhand(in float t) {
float r = smoothstep(.25, .3, len_)*smoothstep(1., .85, len_);
float a =
r *
smoothstep(v_aa, 0., thetadist(uv_, t)) *
step(abs(theta_-t), .1);
float b =
r * max(1.-abs(theta_-t)/(PI/12.), 0.)*.7;
return a + b;
}
void main(void) {
uv_ = v_uv.yx;
len_ = length(uv_);
theta_ = atan2(uv_);
theta_ = theta_ < 0.? theta_+2.*PI: theta_;
if (v_range <= -1.) {
o_color = v_color;
float a =
grid( 2., .4, 1.) +
grid(60., .75, .8) +
grid(10., .65, .8) +
grid(8., .5, .55) +
grid( 4., .3, .4) +
circle(.8);
o_color.a *= clamp(a, 0., 1.);
} else if (v_range <= 0.) {
o_color = v_color*clockhand(v_period.x*PI*2.);
o_color.a = pow(o_color.a, 2.);
} else {
o_color = v_color;
o_color.a *= belt(v_period.x*PI*2., v_period.y*PI*2., v_range);
}
}

View File

@@ -0,0 +1,58 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_combat_ring_program_t;
struct loshader_combat_ring_drawer_t;
typedef struct loshader_combat_ring_drawer_t loshader_combat_ring_drawer_t;
typedef struct {
float range;
float start;
float end;
vec4_t color;
} loshader_combat_ring_drawer_instance_t;
void
loshader_combat_ring_program_initialize(
loshader_combat_ring_program_t* prog
);
void
loshader_combat_ring_program_deinitialize(
loshader_combat_ring_program_t* prog
);
loshader_combat_ring_drawer_t* /* OWNERSHIP */
loshader_combat_ring_drawer_new(
const loshader_combat_ring_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_combat_ring_drawer_delete(
loshader_combat_ring_drawer_t* drawer /* OWNERSHIP */
);
void
loshader_combat_ring_drawer_clear(
loshader_combat_ring_drawer_t* drawer,
size_t reserve
);
void
loshader_combat_ring_drawer_add_instance(
loshader_combat_ring_drawer_t* drawer,
const loshader_combat_ring_drawer_instance_t* instance
);
void
loshader_combat_ring_drawer_draw(
const loshader_combat_ring_drawer_t* drawer
);

View File

@@ -0,0 +1,31 @@
layout (location = 0) in float i_range;
layout (location = 1) in vec2 i_period;
layout (location = 2) in vec4 i_color;
out vec2 v_uv;
out float v_aa;
out float v_range;
out vec2 v_period;
out vec4 v_color;
void main() {
v_uv =
(gl_VertexID == 0)? vec2(-1., 1.):
(gl_VertexID == 1)? vec2(-1., -1.):
(gl_VertexID == 2)? vec2( 1., 1.):
(gl_VertexID == 3)? vec2(-1., -1.):
(gl_VertexID == 4)? vec2( 1., -1.):
(gl_VertexID == 5)? vec2( 1., 1.):
vec2(0, 0);
vec2 scale = uni.dpi*5. / uni.resolution;
scale /= max(scale.x, 1.);
scale /= max(scale.y, 1.);
gl_Position = vec4(v_uv*scale, 0., 1.);
v_aa = length(uni.aa / scale)*2.;
v_range = i_range;
v_period = i_period;
v_color = i_color;
}

View File

@@ -0,0 +1,91 @@
#include "./event_line.h"
#include <assert.h>
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/gleasy/texture.h"
#include "util/glyphas/block.h"
#include "util/glyphas/drawer.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/event_line.vshader.h"
#include "anysrc/event_line.fshader.h"
#define LOSHADER_EVENT_LINE_UNIBLOCK_INDEX 0
void loshader_event_line_program_initialize(
loshader_event_line_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_event_line_vshader_, sizeof(loshader_event_line_vshader_),
loshader_event_line_fshader_, sizeof(loshader_event_line_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_EVENT_LINE_UNIBLOCK_INDEX);
}
void loshader_event_line_program_deinitialize(
loshader_event_line_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
void loshader_event_line_drawer_initialize(
loshader_event_line_drawer_t* drawer,
const loshader_event_line_program_t* prog,
const loshader_uniblock_t* uniblock,
gleasy_texture_2d_t tex) {
assert(drawer != NULL);
assert(prog != NULL);
assert(uniblock != NULL);
assert(tex != 0);
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
.tex = tex,
.glyphas = glyphas_drawer_new(),
};
}
void loshader_event_line_drawer_deinitialize(
loshader_event_line_drawer_t* drawer) {
assert(drawer != NULL);
glyphas_drawer_delete(drawer->glyphas);
}
void loshader_event_line_drawer_clear(
loshader_event_line_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
glyphas_drawer_clear(drawer->glyphas, drawer->tex, reserve);
}
void loshader_event_line_drawer_add_block(
loshader_event_line_drawer_t* drawer, const glyphas_block_t* block) {
assert(drawer != NULL);
assert(block != NULL);
glyphas_drawer_add_block(drawer->glyphas, block);
}
void loshader_event_line_drawer_draw(const loshader_event_line_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_EVENT_LINE_UNIBLOCK_INDEX);
glyphas_drawer_draw(drawer->glyphas);
}

View File

@@ -0,0 +1,11 @@
layout (location = 0) uniform sampler2D u_tex;
in vec2 v_uv;
in vec4 v_color;
out vec4 o_color;
void main(void) {
float a = texture(u_tex, v_uv).r;
o_color = vec4(v_color.rgb, v_color.a*a);
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/gleasy/texture.h"
#include "util/glyphas/block.h"
#include "util/glyphas/drawer.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_event_line_program_t;
typedef struct {
/* injected deps */
const loshader_event_line_program_t* prog;
const loshader_uniblock_t* uniblock;
gleasy_texture_2d_t tex;
/* owned objects */
glyphas_drawer_t* glyphas;
} loshader_event_line_drawer_t;
void
loshader_event_line_program_initialize(
loshader_event_line_program_t* prog
);
void
loshader_event_line_program_deinitialize(
loshader_event_line_program_t* prog
);
void
loshader_event_line_drawer_initialize(
loshader_event_line_drawer_t* drawer,
const loshader_event_line_program_t* prog,
const loshader_uniblock_t* uniblock,
gleasy_texture_2d_t tex
);
void
loshader_event_line_drawer_deinitialize(
loshader_event_line_drawer_t* drawer
);
void
loshader_event_line_drawer_clear(
loshader_event_line_drawer_t* drawer,
size_t reserve
);
void
loshader_event_line_drawer_add_block(
loshader_event_line_drawer_t* drawer,
const glyphas_block_t* block
);
void
loshader_event_line_drawer_draw(
const loshader_event_line_drawer_t* drawer
);

View File

@@ -0,0 +1,22 @@
layout (location = 0) in vec2 i_pos;
layout (location = 1) in vec2 i_size;
layout (location = 2) in vec2 i_uv_pos;
layout (location = 3) in vec2 i_uv_size;
layout (location = 4) in vec4 i_color;
out vec2 v_uv;
out vec4 v_color;
void main(void) {
const vec2[] verts = vec2[](
vec2( 0., 0.), vec2( 0., -1.), vec2( 1., -1.),
vec2( 0., 0.), vec2( 1., -1.), vec2( 1., 0.)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
vec2 dp = p*i_size + i_pos;
gl_Position = vec4(dp, 0, 1);
v_uv = p*i_uv_size + i_uv_pos;
v_color = i_color;
}

131
core/loshader/fog.c Normal file
View File

@@ -0,0 +1,131 @@
#include "./fog.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "core/locommon/position.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/fog.vshader.h"
#include "anysrc/fog.fshader.h"
struct loshader_fog_drawer_t {
const loshader_fog_program_t* prog;
const loshader_uniblock_t* uniblock;
gleasy_buffer_uniform_t param;
};
#pragma pack(push, 1)
typedef struct {
float type;
float prev_type;
float transition;
float bounds_fog;
vec4_t bounds_pos;
vec2_t bounds_size;
} loshader_fog_drawer_internal_param_t;
_Static_assert(
sizeof(float)*10 ==
sizeof(loshader_fog_drawer_internal_param_t));
#pragma pack(pop)
#define LOSHADER_FOG_UNIBLOCK_INDEX 0
#define LOSHADER_FOG_PARAM_INDEX 1
#define LOSHADER_FOG_PRIMITIVE_COUNT 6
void loshader_fog_program_initialize(loshader_fog_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_fog_vshader_, sizeof(loshader_fog_vshader_),
loshader_fog_fshader_, sizeof(loshader_fog_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_FOG_UNIBLOCK_INDEX);
const GLuint param = glGetUniformBlockIndex(*prog, "param");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, param, LOSHADER_FOG_PARAM_INDEX);
}
void loshader_fog_program_deinitialize(loshader_fog_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_fog_drawer_t* loshader_fog_drawer_new(
const loshader_fog_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_fog_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glGenBuffers(1, &drawer->param);
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferData(GL_UNIFORM_BUFFER,
sizeof(loshader_fog_drawer_internal_param_t), NULL, GL_DYNAMIC_DRAW);
return drawer;
}
void loshader_fog_drawer_delete(loshader_fog_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->param);
memory_delete(drawer);
}
void loshader_fog_drawer_set_param(
loshader_fog_drawer_t* drawer,
const loshader_fog_drawer_param_t* param) {
assert(drawer != NULL);
assert(param != NULL);
const loshader_fog_drawer_internal_param_t p = {
.type = param->type,
.prev_type = param->prev_type,
.transition = param->transition,
.bounds_fog = param->bounds_fog,
.bounds_pos = vec4(
param->bounds_pos.chunk.x,
param->bounds_pos.chunk.y,
param->bounds_pos.fract.x,
param->bounds_pos.fract.y),
.bounds_size = param->bounds_size,
};
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(p), &p);
}
void loshader_fog_drawer_draw(const loshader_fog_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_FOG_UNIBLOCK_INDEX);
glBindBufferBase(GL_UNIFORM_BUFFER,
LOSHADER_FOG_PARAM_INDEX, drawer->param);
glDrawArrays(GL_TRIANGLES, 0, LOSHADER_FOG_PRIMITIVE_COUNT);
}

104
core/loshader/fog.fshader Normal file
View File

@@ -0,0 +1,104 @@
layout(std140) uniform param {
float type;
float prev_type;
float transition;
float bounds_fog;
vec4 bounds_pos; /* xy: chunk, zw: fract */
vec2 bounds_size;
} p;
in vec2 v_pos;
in vec2 v_uv;
out vec4 o_color;
const float EPSILON = 1e-4;
/* ---- UTILITY FUNCTIONS ---- */
vec3 get_ray_direction(in vec2 p, in vec2 s, float fov) {
return normalize(vec3(p*s/2., s.y/tan(radians(fov)/2.)));
}
float rand(in vec2 p) {
/* https://qiita.com/shimacpyon/items/d15dee44a0b8b3883f76 */
return fract(sin(dot(p ,vec2(12.9898,78.233))) * 43758.5453);
}
float noise(in vec3 p) {
/* https://www.shadertoy.com/view/4dS3Wd */
const vec3 step = vec3(110, 241, 171);
vec3 i = floor(p);
vec3 f = fract(p);
float n = dot(i, step);
vec3 u = f * f * (3.0 - 2.0 * f);
const vec3 e1 = vec3(1., 0., 0.);
const vec3 e2 = vec3(0., 1., 0.);
const vec3 e3 = vec3(0., 0., 1.);
return mix(mix(mix(rand(dot(step, vec3(0.))+vec2(n)), rand(dot(step, e1 )+vec2(n)), u.x),
mix(rand(dot(step, e2)+vec2(n)), rand(dot(step, e1+e2 )+vec2(n)), u.x), u.y),
mix(mix(rand(dot(step, e3)+vec2(n)), rand(dot(step, e1+e3 )+vec2(n)), u.x),
mix(rand(dot(step, e2+e3)+vec2(n)), rand(dot(step, e1+e2+e3)+vec2(n)), u.x), u.y), u.z);
}
float fbm15(in vec3 p) {
float v = 0., a = .5, f = 0.;
for (int i = 0; i < 15; ++i) {
v += a*noise(p);
p *= 2.;
a *= .5;
}
return v;
}
/* ---- SCENE: white cloud ---- */
vec4 white_cloud(void) {
vec3 dir = get_ray_direction(v_uv, uni.resolution, 60.);
vec3 eye = vec3(0.);
eye.xy += uni.pos.xy + uni.pos.zw;
float a = 0.;
for (float i = 1.; i <= 5.; ++i) {
a += fbm15(eye + dir*i/3.) / pow(i, 2.);
}
return vec4(.6, .6, .5, clamp(pow(a, 8.), 0., .8));
}
/* ---- SCENE: bounds fog ---- */
vec4 bounds_fog(void) {
float aa = uni.aa * 100;
vec2 pos;
pos.x = (p.bounds_pos.x - uni.pos.x) + (p.bounds_pos.z - uni.pos.z);
pos.y = (p.bounds_pos.y - uni.pos.y) + (p.bounds_pos.y - uni.pos.y);
pos = (uni.proj * uni.cam * vec4(pos, 0., 1.)).xy;
vec2 size = (uni.proj * uni.cam * vec4(p.bounds_size, 0., 0.)).xy;
vec2 area_pos = v_uv - pos;
float r =
smoothstep(size.x-aa, size.x+aa, abs(area_pos.x)) +
smoothstep(size.y-aa, size.y+aa, abs(area_pos.y));
float a = fbm15(vec3(area_pos, abs(fract(uni.time/60.)*2.-1.)));
return vec4(1.) * a * r * p.bounds_fog;
}
vec4 scene(in float type) {
return
type == 1.? white_cloud():
vec4(0.);
}
void main(void) {
vec4 prev = vec4(0.), next = vec4(0.);
if (p.transition > 0.) next = clamp(scene(p.type), 0., 1.);
if (p.transition < 1.) prev = clamp(scene(p.prev_type), 0., 1.);
o_color = mix(prev, next, p.transition);
o_color += bounds_fog();
}

59
core/loshader/fog.h Normal file
View File

@@ -0,0 +1,59 @@
#pragma once
#include "util/gleasy/program.h"
#include "core/locommon/position.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_fog_program_t;
typedef struct loshader_fog_drawer_t loshader_fog_drawer_t;
typedef enum {
LOSHADER_FOG_TYPE_NONE = 0,
LOSHADER_FOG_TYPE_WHITE_CLOUD = 1,
} loshader_fog_type_t;
typedef struct {
loshader_fog_type_t type;
loshader_fog_type_t prev_type;
float transition;
float bounds_fog;
locommon_position_t bounds_pos;
vec2_t bounds_size;
} loshader_fog_drawer_param_t;
void
loshader_fog_program_initialize(
loshader_fog_program_t* prog
);
void
loshader_fog_program_deinitialize(
loshader_fog_program_t* prog
);
loshader_fog_drawer_t*
loshader_fog_drawer_new(
const loshader_fog_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_fog_drawer_delete(
loshader_fog_drawer_t* drawer
);
void
loshader_fog_drawer_set_param(
loshader_fog_drawer_t* drawer,
const loshader_fog_drawer_param_t* param
);
void
loshader_fog_drawer_draw(
const loshader_fog_drawer_t* drawer
);

15
core/loshader/fog.vshader Normal file
View File

@@ -0,0 +1,15 @@
out vec2 v_uv;
const vec2[6] square_ = vec2[](
vec2(-1., 1.),
vec2(-1., -1.),
vec2( 1., -1.),
vec2(-1., 1.),
vec2( 1., -1.),
vec2( 1., 1.)
);
void main(void) {
v_uv = square_[gl_VertexID];
gl_Position = vec4(v_uv, 0., 1.);
}

174
core/loshader/ground.c Normal file
View File

@@ -0,0 +1,174 @@
#include "./ground.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/math/algorithm.h"
#include "util/math/matrix.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/ground.vshader.h"
#include "anysrc/ground.fshader.h"
#define LOSHADER_GROUND_VSHADER_IN_GROUND_ID 0
#define LOSHADER_GROUND_VSHADER_IN_POS 1
#define LOSHADER_GROUND_VSHADER_IN_SIZE 2
struct loshader_ground_drawer_t {
const loshader_ground_program_t* prog;
const loshader_uniblock_t* uniblock;
GLuint vao;
gleasy_buffer_array_t instances;
size_t instances_reserved;
size_t instances_length;
};
#pragma pack(push, 1)
typedef struct {
uint16_t ground_id;
vec2_t pos;
vec2_t size;
} loshader_ground_drawer_internal_instance_t;
#pragma pack(pop)
#define LOSHADER_GROUND_UNIBLOCK_INDEX 0
#define LOSHADER_GROUND_PRIMITIVE_COUNT 6
static void loshader_ground_program_setup_vao_(
gleasy_buffer_array_t instances) {
assert(instances != 0);
glBindBuffer(GL_ARRAY_BUFFER, instances);
# define enable_attrib_(NAME, name, dim, type) do { \
glEnableVertexAttribArray(LOSHADER_GROUND_VSHADER_IN_##NAME); \
glVertexAttribPointer( \
LOSHADER_GROUND_VSHADER_IN_##NAME, \
dim, type, GL_FALSE, sizeof(loshader_ground_drawer_internal_instance_t), \
NULL + offsetof(loshader_ground_drawer_internal_instance_t, name)); \
glVertexAttribDivisor(LOSHADER_GROUND_VSHADER_IN_##NAME, 1); \
} while (0)
enable_attrib_(GROUND_ID, ground_id, 1, GL_UNSIGNED_SHORT);
enable_attrib_(POS, pos, 2, GL_FLOAT);
enable_attrib_(SIZE, size, 2, GL_FLOAT);
# undef enable_attrib_
}
void loshader_ground_program_initialize(loshader_ground_program_t* prog) {
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_ground_vshader_, sizeof(loshader_ground_vshader_),
loshader_ground_fshader_, sizeof(loshader_ground_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_GROUND_UNIBLOCK_INDEX);
}
void loshader_ground_program_deinitialize(loshader_ground_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_ground_drawer_t* loshader_ground_drawer_new(
const loshader_ground_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_ground_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glCreateVertexArrays(1, &drawer->vao);
glBindVertexArray(drawer->vao);
glGenBuffers(1, &drawer->instances);
loshader_ground_program_setup_vao_(drawer->instances);
return drawer;
}
void loshader_ground_drawer_delete(loshader_ground_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->instances);
glDeleteVertexArrays(1, &drawer->vao);
memory_delete(drawer);
}
void loshader_ground_drawer_clear(
loshader_ground_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
drawer->instances_length = 0;
if (drawer->instances_reserved < reserve) {
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferData(GL_ARRAY_BUFFER,
reserve * sizeof(loshader_ground_drawer_instance_t),
NULL, GL_DYNAMIC_DRAW);
drawer->instances_reserved = reserve;
}
}
void loshader_ground_drawer_add_instance(
loshader_ground_drawer_t* drawer,
const loshader_ground_drawer_instance_t* instance) {
assert(drawer != NULL);
assert(instance != NULL);
if (drawer->instances_length >= drawer->instances_reserved) {
fprintf(stderr, "ground drawer instance overflow\n");
abort();
}
const loshader_ground_drawer_internal_instance_t inst = {
.ground_id = instance->ground_id,
.pos = instance->pos,
.size = instance->size,
};
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferSubData(GL_ARRAY_BUFFER,
drawer->instances_length*sizeof(inst), sizeof(inst), &inst);
++drawer->instances_length;
}
void loshader_ground_drawer_draw(const loshader_ground_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->instances_length == 0) return;
glUseProgram(*drawer->prog);
glBindVertexArray(drawer->vao);
loshader_uniblock_bind(
drawer->uniblock, LOSHADER_GROUND_UNIBLOCK_INDEX);
glDrawArraysInstanced(GL_TRIANGLES,
0, LOSHADER_GROUND_PRIMITIVE_COUNT, drawer->instances_length);
}

View File

@@ -0,0 +1,9 @@
in float v_ground_id;
in vec2 v_size;
in vec2 v_uv;
out vec4 o_color;
void main(void) {
o_color = vec4(0., 0., 0., .6);
}

62
core/loshader/ground.h Normal file
View File

@@ -0,0 +1,62 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_ground_program_t;
struct loshader_ground_drawer_t;
typedef struct loshader_ground_drawer_t loshader_ground_drawer_t;
typedef enum {
LOSHADER_GROUND_ID_ISLAND = 0,
} loshader_ground_id_t;
typedef struct {
loshader_ground_id_t ground_id;
vec2_t pos;
vec2_t size;
} loshader_ground_drawer_instance_t;
void
loshader_ground_program_initialize(
loshader_ground_program_t* prog
);
void
loshader_ground_program_deinitialize(
loshader_ground_program_t* prog
);
loshader_ground_drawer_t*
loshader_ground_drawer_new(
const loshader_ground_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_ground_drawer_delete(
loshader_ground_drawer_t* drawer
);
void
loshader_ground_drawer_clear(
loshader_ground_drawer_t* drawer,
size_t reserve
);
void
loshader_ground_drawer_add_instance(
loshader_ground_drawer_t* drawer,
const loshader_ground_drawer_instance_t* instance
);
void
loshader_ground_drawer_draw(
const loshader_ground_drawer_t* drawer
);

View File

@@ -0,0 +1,20 @@
layout (location = 0) in float i_ground_id;
layout (location = 1) in vec2 i_pos;
layout (location = 2) in vec2 i_size;
out float v_ground_id;
out vec2 v_size;
out vec2 v_uv;
const vec2[] square_ = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., -1.),
vec2(-1., 1.), vec2( 1., -1.), vec2( 1., 1.)
);
void main(void) {
v_ground_id = i_ground_id;
v_size = i_size;
v_uv = square_[gl_VertexID];
gl_Position = uni.proj * uni.cam * vec4(v_uv*i_size+i_pos, 0., 1.);
}

View File

@@ -0,0 +1,22 @@
#version 330
#extension GL_ARB_explicit_uniform_location : enable
#define PI radians(180.)
precision mediump float;
layout(std140) uniform uniblock {
vec2 resolution;
vec2 dpi;
float aa;
mat4 proj;
mat4 cam;
vec4 pos; /* chunk x, chunk y, fract x, fract y*/
float time; /* %60sec */
} uni;
/* To make it explicit which errors happened in header or body,
adds 10000 to body's line number. */
#line 100001

187
core/loshader/hud_bar.c Normal file
View File

@@ -0,0 +1,187 @@
#include "./hud_bar.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/hud_bar.vshader.h"
#include "anysrc/hud_bar.fshader.h"
#define LOSHADER_HUD_BAR_VSHADER_IN_POS 0
#define LOSHADER_HUD_BAR_VSHADER_IN_SIZE 1
#define LOSHADER_HUD_BAR_VSHADER_IN_BGCOLOR 2
#define LOSHADER_HUD_BAR_VSHADER_IN_FGCOLOR 3
#define LOSHADER_HUD_BAR_VSHADER_IN_VALUE 4
#define LOSHADER_HUD_BAR_VSHADER_IN_PREV_VALUE 5
struct loshader_hud_bar_drawer_t {
const loshader_hud_bar_program_t* prog;
const loshader_uniblock_t* uniblock;
GLuint vao;
gleasy_buffer_array_t instances;
size_t instances_reserved;
size_t instances_length;
};
#pragma pack(push, 1)
typedef struct {
vec2_t pos;
vec2_t size;
vec4_t bgcolor;
vec4_t fgcolor;
float value;
float prev_value;
} loshader_hud_bar_drawer_internal_instance_t;
#pragma pack(pop)
#define LOSHADER_HUD_BAR_UNIBLOCK_INDEX 0
#define LOSHADER_HUD_BAR_PRIMITIVE_COUNT 18
static void loshader_hud_bar_program_setup_vao_(
gleasy_buffer_array_t instances) {
assert(instances != 0);
glBindBuffer(GL_ARRAY_BUFFER, instances);
# define enable_attrib_(NAME, name, dim, type) do { \
glEnableVertexAttribArray(LOSHADER_HUD_BAR_VSHADER_IN_##NAME); \
glVertexAttribPointer( \
LOSHADER_HUD_BAR_VSHADER_IN_##NAME, dim, type, GL_FALSE, \
sizeof(loshader_hud_bar_drawer_internal_instance_t), \
NULL + offsetof(loshader_hud_bar_drawer_internal_instance_t, name)); \
glVertexAttribDivisor(LOSHADER_HUD_BAR_VSHADER_IN_##NAME, 1); \
} while (0)
enable_attrib_(POS, pos, 2, GL_FLOAT);
enable_attrib_(SIZE, size, 2, GL_FLOAT);
enable_attrib_(BGCOLOR, bgcolor, 4, GL_FLOAT);
enable_attrib_(FGCOLOR, fgcolor, 4, GL_FLOAT);
enable_attrib_(VALUE, value, 1, GL_FLOAT);
enable_attrib_(PREV_VALUE, prev_value, 1, GL_FLOAT);
# undef enable_attrib_
}
void loshader_hud_bar_program_initialize(loshader_hud_bar_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_hud_bar_vshader_, sizeof(loshader_hud_bar_vshader_),
loshader_hud_bar_fshader_, sizeof(loshader_hud_bar_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_HUD_BAR_UNIBLOCK_INDEX);
}
void loshader_hud_bar_program_deinitialize(loshader_hud_bar_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_hud_bar_drawer_t* loshader_hud_bar_drawer_new(
const loshader_hud_bar_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_hud_bar_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glCreateVertexArrays(1, &drawer->vao);
glBindVertexArray(drawer->vao);
glGenBuffers(1, &drawer->instances);
loshader_hud_bar_program_setup_vao_(drawer->instances);
return drawer;
}
void loshader_hud_bar_drawer_delete(loshader_hud_bar_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->instances);
glDeleteVertexArrays(1, &drawer->vao);
memory_delete(drawer);
}
void loshader_hud_bar_drawer_clear(
loshader_hud_bar_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
drawer->instances_length = 0;
if (drawer->instances_reserved < reserve) {
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferData(GL_ARRAY_BUFFER,
sizeof(loshader_hud_bar_drawer_internal_instance_t) * reserve,
NULL, GL_DYNAMIC_DRAW);
drawer->instances_reserved = reserve;
}
}
void loshader_hud_bar_drawer_add_instance(
loshader_hud_bar_drawer_t* drawer,
const loshader_hud_bar_drawer_instance_t* instance) {
assert(drawer != NULL);
assert(instance != NULL);
if (drawer->instances_length >= drawer->instances_reserved) {
fprintf(stderr, "hud bar drawer instance overflow\n");
abort();
}
const loshader_hud_bar_drawer_internal_instance_t insta = {
.pos = instance->pos,
.size = instance->size,
.bgcolor = instance->bgcolor,
.fgcolor = instance->fgcolor,
.value = instance->value,
.prev_value = instance->prev_value,
};
const size_t offset = drawer->instances_length * sizeof(insta);
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(insta), &insta);
++drawer->instances_length;
}
void loshader_hud_bar_drawer_draw(const loshader_hud_bar_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->instances_length == 0) return;
glUseProgram(*drawer->prog);
glBindVertexArray(drawer->vao);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_HUD_BAR_UNIBLOCK_INDEX);
glDrawArraysInstanced(GL_TRIANGLES,
0, LOSHADER_HUD_BAR_PRIMITIVE_COUNT, drawer->instances_length);
}

View File

@@ -0,0 +1,21 @@
in vec2 v_pos;
in vec2 v_size;
in vec2 v_aa;
in vec2 v_dp;
in vec4 v_color;
out vec4 o_color;
void main() {
vec2 dp = v_dp;
dp *= pow(length(dp), .1);
vec2 diff = abs(dp - v_pos);
float aa = uni.aa * 4.;
float a =
(1.-smoothstep(v_size.x-aa, v_size.x, diff.x)) *
(1.-smoothstep(v_size.y-aa, v_size.y, diff.y));
o_color = v_color;
o_color.a *= a;
}

60
core/loshader/hud_bar.h Normal file
View File

@@ -0,0 +1,60 @@
#pragma once
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_hud_bar_program_t;
struct loshader_hud_bar_drawer_t;
typedef struct loshader_hud_bar_drawer_t loshader_hud_bar_drawer_t;
typedef struct {
vec2_t pos;
vec2_t size;
vec4_t bgcolor;
vec4_t fgcolor;
float value;
float prev_value;
} loshader_hud_bar_drawer_instance_t;
void
loshader_hud_bar_program_initialize(
loshader_hud_bar_program_t* prog
);
void
loshader_hud_bar_program_deinitialize(
loshader_hud_bar_program_t* prog
);
loshader_hud_bar_drawer_t* /* OWNERSHIP */
loshader_hud_bar_drawer_new(
const loshader_hud_bar_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_hud_bar_drawer_delete(
loshader_hud_bar_drawer_t* drawer /* OWNERSHIP */
);
void
loshader_hud_bar_drawer_clear(
loshader_hud_bar_drawer_t* drawer,
size_t reserve
);
void
loshader_hud_bar_drawer_add_instance(
loshader_hud_bar_drawer_t* drawer,
const loshader_hud_bar_drawer_instance_t* instance
);
void
loshader_hud_bar_drawer_draw(
const loshader_hud_bar_drawer_t* drawer
);

View File

@@ -0,0 +1,56 @@
layout (location = 0) in vec2 i_pos;
layout (location = 1) in vec2 i_size;
layout (location = 2) in vec4 i_bgcolor;
layout (location = 3) in vec4 i_fgcolor;
layout (location = 4) in float i_value;
layout (location = 5) in float i_prev_value;
out vec2 v_pos;
out vec2 v_size;
out vec2 v_aa;
out vec2 v_dp;
out vec4 v_color;
void main() {
const vec2[] verts = vec2[](
vec2(-1., 1.),
vec2(-1., -1.),
vec2( 1., -1.),
vec2(-1., 1.),
vec2( 1., -1.),
vec2( 1., 1.)
);
float scale = (uni.cam * vec4(1., 0., 0., 0.)).x;
scale = pow(1.2, scale-1.);
v_pos = i_pos;
v_size = i_size;
int id = 0;
if (gl_VertexID < 6) {
id = gl_VertexID;
v_size += vec2(2.)/uni.resolution;
v_color = i_bgcolor;
} else if (gl_VertexID < 12) {
id = gl_VertexID - 6;
v_pos.x -= v_size.x*(1.-i_prev_value);
v_size.x *= i_prev_value;
v_color = mix(i_bgcolor, i_fgcolor, .5);
} else {
id = gl_VertexID - 12;
v_pos.x -= v_size.x*(1.-i_value);
v_size.x *= i_value;
v_color = i_fgcolor;
}
v_pos *= scale;
v_size *= scale;
v_size = abs(v_size);
v_aa = uni.aa / v_size;
v_dp = verts[id]*1.5*v_size + v_pos;
v_dp /= pow(length(v_dp), .1);
gl_Position = vec4(v_dp, 0., 1.);
}

95
core/loshader/hud_text.c Normal file
View File

@@ -0,0 +1,95 @@
#include "./hud_text.h"
#include <assert.h>
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/gleasy/texture.h"
#include "util/glyphas/block.h"
#include "util/glyphas/drawer.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/hud_text.vshader.h"
#include "anysrc/hud_text.fshader.h"
#define LOSHADER_HUD_TEXT_UNIFORM_ALPHA 1
#define LOSHADER_HUD_TEXT_UNIBLOCK_INDEX 0
void loshader_hud_text_program_initialize(loshader_hud_text_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_hud_text_vshader_, sizeof(loshader_hud_text_vshader_),
loshader_hud_text_fshader_, sizeof(loshader_hud_text_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_HUD_TEXT_UNIBLOCK_INDEX);
}
void loshader_hud_text_program_deinitialize(loshader_hud_text_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
void loshader_hud_text_drawer_initialize(
loshader_hud_text_drawer_t* drawer,
const loshader_hud_text_program_t* prog,
const loshader_uniblock_t* uniblock,
gleasy_texture_2d_t tex) {
assert(drawer != NULL);
assert(prog != NULL);
assert(uniblock != NULL);
assert(tex != 0);
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
.tex = tex,
.glyphas = glyphas_drawer_new(),
.alpha = 1,
};
}
void loshader_hud_text_drawer_deinitialize(
loshader_hud_text_drawer_t* drawer) {
assert(drawer != NULL);
glyphas_drawer_delete(drawer->glyphas);
}
void loshader_hud_text_drawer_clear(
loshader_hud_text_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
glyphas_drawer_clear(drawer->glyphas, drawer->tex, reserve);
}
void loshader_hud_text_drawer_add_block(
loshader_hud_text_drawer_t* drawer, const glyphas_block_t* block) {
assert(drawer != NULL);
assert(block != NULL);
glyphas_drawer_add_block(drawer->glyphas, block);
}
void loshader_hud_text_drawer_draw(const loshader_hud_text_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_HUD_TEXT_UNIBLOCK_INDEX);
glUniform1f(LOSHADER_HUD_TEXT_UNIFORM_ALPHA, drawer->alpha);
glyphas_drawer_draw(drawer->glyphas);
}

View File

@@ -0,0 +1,28 @@
layout (location = 0) uniform sampler2D u_tex;
layout (location = 1) uniform float u_alpha;
in vec2 v_pos;
in vec2 v_size;
in vec2 v_uv_pos;
in vec2 v_uv_size;
in vec2 v_dp;
in vec4 v_color;
out vec4 o_color;
void main(void) {
vec2 dp = v_dp;
dp *= pow(length(dp), .1);
vec2 uvp = (dp - v_pos) / v_size;
vec2 uv = uvp*v_uv_size + v_uv_pos;
uvp = abs(uvp);
float a =
texture(u_tex, uv).r *
step(abs(uvp.x-.5), .5) *
step(abs(uvp.y-.5), .5);
o_color = v_color;
o_color.a *= a*u_alpha;
}

66
core/loshader/hud_text.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/gleasy/texture.h"
#include "util/glyphas/block.h"
#include "util/glyphas/drawer.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_hud_text_program_t;
typedef struct {
/* injected deps */
const loshader_hud_text_program_t* prog;
const loshader_uniblock_t* uniblock;
gleasy_texture_2d_t tex;
/* owned objects */
glyphas_drawer_t* glyphas;
/* public params */
float alpha;
} loshader_hud_text_drawer_t;
void
loshader_hud_text_program_initialize(
loshader_hud_text_program_t* prog
);
void
loshader_hud_text_program_deinitialize(
loshader_hud_text_program_t* prog
);
void
loshader_hud_text_drawer_initialize(
loshader_hud_text_drawer_t* drawer,
const loshader_hud_text_program_t* prog,
const loshader_uniblock_t* uniblock,
gleasy_texture_2d_t tex
);
void
loshader_hud_text_drawer_deinitialize(
loshader_hud_text_drawer_t* drawer
);
void
loshader_hud_text_drawer_clear(
loshader_hud_text_drawer_t* drawer,
size_t reserve
);
void
loshader_hud_text_drawer_add_block(
loshader_hud_text_drawer_t* drawer,
const glyphas_block_t* block
);
void
loshader_hud_text_drawer_draw(
const loshader_hud_text_drawer_t* drawer
);

View File

@@ -0,0 +1,33 @@
layout (location = 0) in vec2 i_pos;
layout (location = 1) in vec2 i_size;
layout (location = 2) in vec2 i_uv_pos;
layout (location = 3) in vec2 i_uv_size;
layout (location = 4) in vec4 i_color;
out vec2 v_pos;
out vec2 v_size;
out vec2 v_uv_pos;
out vec2 v_uv_size;
out vec2 v_dp;
out vec4 v_color;
void main(void) {
const vec2[] verts = vec2[](
vec2( 0., 0.), vec2( 0., -1.), vec2( 1., -1.),
vec2( 0., 0.), vec2( 1., -1.), vec2( 1., 0.)
);
float scale = (uni.cam * vec4(1., 0., 0., 0.)).x;
scale = pow(1.2, scale-1.);
v_pos = i_pos * scale;
v_size = i_size * scale;
v_uv_pos = i_uv_pos;
v_uv_size = i_uv_size;
v_color = i_color;
v_dp = verts[gl_VertexID]*v_size*1.5 + v_pos;
v_dp /= pow(length(v_dp), .1);
gl_Position = vec4(v_dp, 0., 1.);
}

View File

@@ -0,0 +1,97 @@
#include "./menu_background.h"
#include <assert.h>
#include <GL/glew.h>
#include "util/gleasy/program.h"
#include "util/math/algorithm.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/menu_background.vshader.h"
#include "anysrc/menu_background.fshader.h"
#define LOSHADER_MENU_BACKGROUND_UNIFORM_ALPHA 0
struct loshader_menu_background_drawer_t {
const loshader_menu_background_program_t* prog;
const loshader_uniblock_t* uniblock;
float alpha;
};
#define LOSHADER_MENU_BACKGROUND_UNIBLOCK_INDEX 0
void loshader_menu_background_program_initialize(
loshader_menu_background_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_,
sizeof(loshader_header_shader_),
loshader_menu_background_vshader_,
sizeof(loshader_menu_background_vshader_),
loshader_menu_background_fshader_,
sizeof(loshader_menu_background_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(
*prog, uniblock, LOSHADER_MENU_BACKGROUND_UNIBLOCK_INDEX);
}
void loshader_menu_background_program_deinitialize(
loshader_menu_background_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_menu_background_drawer_t* loshader_menu_background_drawer_new(
const loshader_menu_background_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_menu_background_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
return drawer;
}
void loshader_menu_background_drawer_delete(
loshader_menu_background_drawer_t* drawer) {
if (drawer == NULL) return;
memory_delete(drawer);
}
void loshader_menu_background_drawer_set_alpha(
loshader_menu_background_drawer_t* drawer, float alpha) {
assert(drawer != NULL);
assert(MATH_FLOAT_VALID(alpha));
drawer->alpha = alpha;
}
void loshader_menu_background_drawer_draw(
const loshader_menu_background_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->alpha == 0) return;
glUseProgram(*drawer->prog);
loshader_uniblock_bind(
drawer->uniblock, LOSHADER_MENU_BACKGROUND_UNIBLOCK_INDEX);
glUniform1f(LOSHADER_MENU_BACKGROUND_UNIFORM_ALPHA, drawer->alpha);
glDrawArrays(GL_TRIANGLES, 0, 6);
}

View File

@@ -0,0 +1,35 @@
layout (location = 0) uniform float u_alpha;
in vec2 v_uv;
out vec4 o_color;
float atan2(in vec2 p){
return p.x == 0. ? sign(p.y)*PI/2. : atan(p.y, p.x);
}
float map(in vec2 p, in float t) {
if (p.x >= 2.) return 0.;
vec2 v = vec2(.3, .4 + t*.3);
for (float i = 0.; i < 10.; ++i) {
p = abs(p) - v;
v /= dot(p, p);
}
return abs(p.x);
}
void main(void) {
vec2 uv = v_uv * uni.resolution.xy / (4.*uni.dpi);
vec2 polar = vec2(length(uv), atan2(uv));
polar.y = abs(mod(polar.y, PI/3.) - PI/6.);
vec2 p = vec2(cos(polar.y), sin(polar.y))*polar.x;
o_color = vec4(0, 0, 0, .7*u_alpha);
float t = 1.-pow(1.-u_alpha, 8.);
float fractal = step(100.-t*100.+3., map(p*1.8, t)) * polar.x;
o_color = mix(o_color, vec4(.4, .2, .2, .1), fractal);
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "util/gleasy/program.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_menu_background_program_t;
struct loshader_menu_background_drawer_t;
typedef
struct loshader_menu_background_drawer_t
loshader_menu_background_drawer_t;
void
loshader_menu_background_program_initialize(
loshader_menu_background_program_t* prog
);
void
loshader_menu_background_program_deinitialize(
loshader_menu_background_program_t* prog
);
loshader_menu_background_drawer_t*
loshader_menu_background_drawer_new(
const loshader_menu_background_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_menu_background_drawer_delete(
loshader_menu_background_drawer_t* drawer
);
void
loshader_menu_background_drawer_set_alpha(
loshader_menu_background_drawer_t* drawer,
float alpha
);
void
loshader_menu_background_drawer_draw(
const loshader_menu_background_drawer_t* drawer
);

View File

@@ -0,0 +1,11 @@
out vec2 v_uv;
void main(void) {
const vec2[] verts = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., -1.),
vec2(-1., 1.), vec2( 1., -1.), vec2( 1., 1.)
);
v_uv = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
gl_Position = vec4(v_uv, 0., 1.);
}

185
core/loshader/menu_stance.c Normal file
View File

@@ -0,0 +1,185 @@
#include "./menu_stance.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/menu_stance.vshader.h"
#include "anysrc/menu_stance.fshader.h"
#define LOSHADER_MENU_STANCE_VSHADER_IN_ID 0
#define LOSHADER_MENU_STANCE_VSHADER_IN_POS 1
#define LOSHADER_MENU_STANCE_VSHADER_IN_SIZE 2
#define LOSHADER_MENU_STANCE_VSHADER_IN_ALPHA 3
#define LOSHADER_MENU_STANCE_VSHADER_IN_HIGHLIGHT 4
struct loshader_menu_stance_drawer_t {
const loshader_menu_stance_program_t* prog;
const loshader_uniblock_t* uniblock;
GLuint vao;
gleasy_buffer_array_t instances;
size_t instances_length;
size_t instances_reserved;
};
#pragma pack(push, 1)
typedef struct {
uint8_t id;
vec2_t pos;
vec2_t size;
float alpha;
float highlight;
} loshader_menu_stance_drawer_internal_instance_t;
#pragma pack(pop)
#define LOSHADER_MENU_STANCE_UNIBLOCK_INDEX 0
#define LOSHADER_MENU_STANCE_PRIMITIVE_COUNT 60
static void loshader_menu_stance_program_setup_vao_(
gleasy_buffer_array_t instances) {
assert(instances != 0);
glBindBuffer(GL_ARRAY_BUFFER, instances);
# define enable_attrib_(NAME, name, dim, type) do { \
glEnableVertexAttribArray(LOSHADER_MENU_STANCE_VSHADER_IN_##NAME); \
glVertexAttribPointer( \
LOSHADER_MENU_STANCE_VSHADER_IN_##NAME, dim, type, GL_FALSE, \
sizeof(loshader_menu_stance_drawer_internal_instance_t), \
NULL + offsetof(loshader_menu_stance_drawer_internal_instance_t, name)); \
glVertexAttribDivisor(LOSHADER_MENU_STANCE_VSHADER_IN_##NAME, 1); \
} while (0)
enable_attrib_(ID, id, 1, GL_UNSIGNED_BYTE);
enable_attrib_(POS, pos, 2, GL_FLOAT);
enable_attrib_(SIZE, size, 2, GL_FLOAT);
enable_attrib_(ALPHA, alpha, 1, GL_FLOAT);
enable_attrib_(HIGHLIGHT, highlight, 1, GL_FLOAT);
# undef enable_attrib_
}
void loshader_menu_stance_program_initialize(
loshader_menu_stance_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_menu_stance_vshader_, sizeof(loshader_menu_stance_vshader_),
loshader_menu_stance_fshader_, sizeof(loshader_menu_stance_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_MENU_STANCE_UNIBLOCK_INDEX);
}
void loshader_menu_stance_program_deinitialize(
loshader_menu_stance_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_menu_stance_drawer_t* loshader_menu_stance_drawer_new(
const loshader_menu_stance_program_t* prog,
const loshader_uniblock_t* uniblock) {
assert(prog != NULL);
assert(uniblock != NULL);
loshader_menu_stance_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
};
glCreateVertexArrays(1, &drawer->vao);
glBindVertexArray(drawer->vao);
glGenBuffers(1, &drawer->instances);
loshader_menu_stance_program_setup_vao_(drawer->instances);
return drawer;
}
void loshader_menu_stance_drawer_delete(
loshader_menu_stance_drawer_t* drawer) {
assert(drawer != NULL);
glDeleteBuffers(1, &drawer->instances);
glDeleteVertexArrays(1, &drawer->vao);
memory_delete(drawer);
}
void loshader_menu_stance_drawer_clear(
loshader_menu_stance_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
drawer->instances_length = 0;
if (drawer->instances_reserved < reserve) {
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferData(GL_ARRAY_BUFFER,
reserve * sizeof(loshader_menu_stance_drawer_internal_instance_t),
NULL, GL_DYNAMIC_DRAW);
drawer->instances_reserved = reserve;
}
}
void loshader_menu_stance_drawer_add_instance(
loshader_menu_stance_drawer_t* drawer,
const loshader_menu_stance_drawer_instance_t* instance) {
assert(drawer != NULL);
assert(instance != NULL);
if (drawer->instances_length >= drawer->instances_reserved) {
fprintf(stderr, "menu stance drawer instance overflow\n");
abort();
}
const loshader_menu_stance_drawer_internal_instance_t insta = {
.id = instance->id,
.pos = instance->pos,
.size = instance->size,
.alpha = instance->alpha,
.highlight = instance->highlight,
};
const size_t offset = drawer->instances_length * sizeof(insta);
glBindBuffer(GL_ARRAY_BUFFER, drawer->instances);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(insta), &insta);
++drawer->instances_length;
}
void loshader_menu_stance_drawer_draw(
const loshader_menu_stance_drawer_t* drawer) {
assert(drawer != NULL);
if (drawer->instances_length == 0) return;
glUseProgram(*drawer->prog);
glBindVertexArray(drawer->vao);
loshader_uniblock_bind(
drawer->uniblock, LOSHADER_MENU_STANCE_UNIBLOCK_INDEX);
glDrawArraysInstanced(GL_TRIANGLES,
0, LOSHADER_MENU_STANCE_PRIMITIVE_COUNT, drawer->instances_length);
}

View File

@@ -0,0 +1,9 @@
in float v_id;
in vec2 v_uv;
in float v_alpha;
out vec4 o_color;
void main(void) {
o_color = vec4(1., 1., 1., v_alpha*.8);
}

View File

@@ -0,0 +1,68 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_menu_stance_program_t;
struct loshader_menu_stance_drawer_t;
typedef struct loshader_menu_stance_drawer_t loshader_menu_stance_drawer_t;
typedef enum {
LOSHADER_MENU_STANCE_ID_EMPTY = 0,
LOSHADER_MENU_STANCE_ID_MISSIONARY = 1,
LOSHADER_MENU_STANCE_ID_REVOLUTIONER = 2,
LOSHADER_MENU_STANCE_ID_UNFINISHER = 3,
LOSHADER_MENU_STANCE_ID_PHILOSOPHER = 4,
} loshader_menu_stance_id_t;
typedef struct {
loshader_menu_stance_id_t id;
vec2_t pos;
vec2_t size;
float alpha;
float highlight;
} loshader_menu_stance_drawer_instance_t;
void
loshader_menu_stance_program_initialize(
loshader_menu_stance_program_t* prog
);
void
loshader_menu_stance_program_deinitialize(
loshader_menu_stance_program_t* prog
);
loshader_menu_stance_drawer_t*
loshader_menu_stance_drawer_new(
const loshader_menu_stance_program_t* prog,
const loshader_uniblock_t* uniblock
);
void
loshader_menu_stance_drawer_delete(
loshader_menu_stance_drawer_t* drawer
);
void
loshader_menu_stance_drawer_clear(
loshader_menu_stance_drawer_t* drawer,
size_t reserve
);
void
loshader_menu_stance_drawer_add_instance(
loshader_menu_stance_drawer_t* drawer,
const loshader_menu_stance_drawer_instance_t* instance
);
void
loshader_menu_stance_drawer_draw(
const loshader_menu_stance_drawer_t* drawer
);

View File

@@ -0,0 +1,93 @@
layout (location = 0) in float i_id;
layout (location = 1) in vec2 i_pos;
layout (location = 2) in vec2 i_size;
layout (location = 3) in float i_alpha;
layout (location = 4) in float i_highlight;
out float v_id;
out vec2 v_uv;
out float v_alpha;
const vec2[] frame_ = vec2[](
vec2( 0.0, 1.0), vec2(-1.0, 0.0), vec2( 0.0, 0.9),
vec2( 0.0, 0.9), vec2(-1.0, 0.0), vec2(-0.9, 0.0),
vec2(-1.0, 0.0), vec2( 0.0, -1.0), vec2(-0.9, 0.0),
vec2(-0.9, 0.0), vec2( 0.0, -1.0), vec2( 0.0, -0.9),
vec2( 0.9, 0.0), vec2( 0.0, -0.9), vec2( 0.0, -1.0),
vec2( 1.0, 0.0), vec2( 0.9, 0.0), vec2( 0.0, -1.0),
vec2( 0.0, 1.0), vec2( 0.9, 0.0), vec2( 1.0, 0.0),
vec2( 0.0, 1.0), vec2( 0.0, 0.9), vec2( 0.9, 0.0)
);
vec2 empty(in int id) {
const vec2[] verts = vec2[](
vec2( 0., 1.), vec2(-1., 0.), vec2( 0., -1.),
vec2( 0., 1.), vec2( 1., 0.), vec2( 0., -1.)
);
return id < verts.length()? verts[id]: vec2(0.);
}
vec2 missionary(in int id) {
const vec2[] verts = vec2[](
vec2(-0.12, 0.52), vec2(-0.52, 0.24), vec2( 0.04, 0.40),
vec2(-0.52, 0.24), vec2( 0.00, 0.00), vec2( 0.00, 0.12),
vec2(-0.60, 0.08), vec2(-0.68, 0.00), vec2(-0.04, -0.36),
vec2(-0.72, 0.00), vec2(-0.08, -0.52), vec2( 0.00, -0.40),
vec2(-0.76, -0.04), vec2(-0.60, -0.36), vec2(-0.12, -0.56),
vec2(-0.60, -0.40), vec2(-0.04, -0.96), vec2(-0.12, -0.60)
);
return
id < verts.length() ? verts[id]:
id < verts.length()*2? verts[id-verts.length()]*vec2(-1., 1.):
vec2(0.);
}
vec2 revolutioner(in int id) {
const vec2[] verts = vec2[](
vec2(-0.52, 0.24), vec2(-0.60, 0.20), vec2( 0.00, -0.80),
vec2( 0.00, 0.36), vec2(-0.48, 0.08), vec2(-0.24, -0.16),
vec2( 0.08, 0.64), vec2(-0.16, 0.40), vec2( 0.44, 0.36),
vec2( 0.04, 0.24), vec2(-0.16, -0.12), vec2( 0.56, 0.28)
);
return id < verts.length()? verts[id]: vec2(0.);
}
vec2 unfinisher(in int id) {
const vec2[] verts = vec2[](
vec2( 0.00, 1.00), vec2(-0.08, 0.20), vec2( 0.08, 0.20),
vec2(-0.08, 0.20), vec2(-0.40, 0.00), vec2(-0.40, -0.40),
vec2(-0.40, -0.40), vec2( 0.00, -0.60), vec2( 0.40, -0.40),
vec2( 0.08, 0.20), vec2( 0.40, 0.00), vec2( 0.40, -0.40)
);
return id < verts.length()? verts[id]: vec2(0.);
}
vec2 philosopher(in int id) {
const vec2[] verts = vec2[](
vec2( 0.117, -0.367), vec2( 0.000, -0.750), vec2( 0.300, -0.533),
vec2( 0.117, 0.050), vec2(-0.083, -0.117), vec2( 0.367, -0.517),
vec2(-0.050, 0.283), vec2(-0.133, -0.117), vec2( 0.117, 0.083),
vec2( 0.500, 0.500), vec2(-0.050, 0.333), vec2( 0.150, 0.133),
vec2( 0.250, 0.917), vec2(-0.233, 0.317), vec2( 0.500, 0.533),
vec2( 0.217, 0.917), vec2(-0.300, 0.817), vec2(-0.283, 0.333),
vec2(-0.333, 0.783), vec2(-0.500, 0.567), vec2(-0.333, 0.333)
);
return id < verts.length()? verts[id]*vec2(1.1, .9)+vec2(0, -.1): vec2(0.);
}
vec2 get_vertex(in int id) {
return
i_id == 1.? missionary(id):
i_id == 2.? revolutioner(id):
i_id == 3.? unfinisher(id):
i_id == 4.? philosopher(id):
empty(id);
}
void main(void) {
v_uv = gl_VertexID < frame_.length()?
frame_[gl_VertexID]: get_vertex(gl_VertexID - frame_.length())*.8;
v_id = i_id;
v_alpha = i_alpha;
float s = i_highlight*.2 + 1.;
gl_Position = vec4(v_uv*i_size*s + i_pos, 0., 1.);
}

97
core/loshader/menu_text.c Normal file
View File

@@ -0,0 +1,97 @@
#include "./menu_text.h"
#include <assert.h>
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/gleasy/texture.h"
#include "util/glyphas/block.h"
#include "util/glyphas/drawer.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/menu_text.vshader.h"
#include "anysrc/menu_text.fshader.h"
#define LOSHADER_MENU_TEXT_UNIFORM_ALPHA 1
#define LOSHADER_MENU_TEXT_UNIBLOCK_INDEX 0
void loshader_menu_text_program_initialize(
loshader_menu_text_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_menu_text_vshader_, sizeof(loshader_menu_text_vshader_),
loshader_menu_text_fshader_, sizeof(loshader_menu_text_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_MENU_TEXT_UNIBLOCK_INDEX);
}
void loshader_menu_text_program_deinitialize(
loshader_menu_text_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
void loshader_menu_text_drawer_initialize(
loshader_menu_text_drawer_t* drawer,
const loshader_menu_text_program_t* prog,
const loshader_uniblock_t* uniblock,
gleasy_texture_2d_t tex) {
assert(drawer != NULL);
assert(prog != NULL);
assert(uniblock != NULL);
assert(tex != 0);
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
.tex = tex,
.glyphas = glyphas_drawer_new(),
.alpha = 1,
};
}
void loshader_menu_text_drawer_deinitialize(
loshader_menu_text_drawer_t* drawer) {
assert(drawer != NULL);
glyphas_drawer_delete(drawer->glyphas);
}
void loshader_menu_text_drawer_clear(
loshader_menu_text_drawer_t* drawer, size_t reserve) {
assert(drawer != NULL);
assert(reserve > 0);
glyphas_drawer_clear(drawer->glyphas, drawer->tex, reserve);
}
void loshader_menu_text_drawer_add_block(
loshader_menu_text_drawer_t* drawer, const glyphas_block_t* block) {
assert(drawer != NULL);
assert(block != NULL);
glyphas_drawer_add_block(drawer->glyphas, block);
}
void loshader_menu_text_drawer_draw(const loshader_menu_text_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_MENU_TEXT_UNIBLOCK_INDEX);
glUniform1f(LOSHADER_MENU_TEXT_UNIFORM_ALPHA, drawer->alpha);
glyphas_drawer_draw(drawer->glyphas);
}

View File

@@ -0,0 +1,12 @@
layout (location = 0) uniform sampler2D u_tex;
layout (location = 1) uniform float u_alpha;
in vec2 v_uv;
in vec4 v_color;
out vec4 o_color;
void main(void) {
float a = texture(u_tex, v_uv).r;
o_color = vec4(v_color.rgb, v_color.a*a*u_alpha);
}

66
core/loshader/menu_text.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/program.h"
#include "util/gleasy/texture.h"
#include "util/glyphas/block.h"
#include "util/glyphas/drawer.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_menu_text_program_t;
typedef struct {
/* injected deps */
const loshader_menu_text_program_t* prog;
const loshader_uniblock_t* uniblock;
gleasy_texture_2d_t tex;
/* owned objects */
glyphas_drawer_t* glyphas;
/* public params */
float alpha;
} loshader_menu_text_drawer_t;
void
loshader_menu_text_program_initialize(
loshader_menu_text_program_t* prog
);
void
loshader_menu_text_program_deinitialize(
loshader_menu_text_program_t* prog
);
void
loshader_menu_text_drawer_initialize(
loshader_menu_text_drawer_t* drawer,
const loshader_menu_text_program_t* prog,
const loshader_uniblock_t* uniblock,
gleasy_texture_2d_t tex
);
void
loshader_menu_text_drawer_deinitialize(
loshader_menu_text_drawer_t* drawer
);
void
loshader_menu_text_drawer_clear(
loshader_menu_text_drawer_t* drawer,
size_t reserve
);
void
loshader_menu_text_drawer_add_block(
loshader_menu_text_drawer_t* drawer,
const glyphas_block_t* block
);
void
loshader_menu_text_drawer_draw(
const loshader_menu_text_drawer_t* drawer
);

View File

@@ -0,0 +1,24 @@
layout (location = 0) in vec2 i_pos;
layout (location = 1) in vec2 i_size;
layout (location = 2) in vec2 i_uv_pos;
layout (location = 3) in vec2 i_uv_size;
layout (location = 4) in vec4 i_color;
out vec2 v_uv;
out vec4 v_color;
void main(void) {
const vec2[] verts = vec2[](
vec2( 0., 0.), vec2( 0., -1.), vec2( 1., -1.),
vec2( 0., 0.), vec2( 1., -1.), vec2( 1., 0.)
);
vec2 p = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
vec2 dp = p*i_size + i_pos;
gl_Position = vec4(dp, 0, 1);
v_uv = p*i_uv_size + i_uv_pos;
v_color = i_color;
}

109
core/loshader/pixsort.c Normal file
View File

@@ -0,0 +1,109 @@
#include "./pixsort.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/framebuffer.h"
#include "util/gleasy/program.h"
#include "util/math/algorithm.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/pixsort.vshader.h"
#include "anysrc/pixsort.fshader.h"
#define LOSHADER_PIXSORT_UNIFORM_SRC 0
#define LOSHADER_PIXSORT_UNIFORM_INTENSITY 1
#define LOSHADER_PIXSORT_UNIBLOCK_INDEX 0
struct loshader_pixsort_drawer_t {
const loshader_pixsort_program_t* prog;
const loshader_uniblock_t* uniblock;
const gleasy_framebuffer_t* fb;
float intensity;
};
void loshader_pixsort_program_initialize(
loshader_pixsort_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_pixsort_vshader_, sizeof(loshader_pixsort_vshader_),
loshader_pixsort_fshader_, sizeof(loshader_pixsort_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_PIXSORT_UNIBLOCK_INDEX);
}
void loshader_pixsort_program_deinitialize(
loshader_pixsort_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_pixsort_drawer_t* loshader_pixsort_drawer_new(
const loshader_pixsort_program_t* prog,
const loshader_uniblock_t* uniblock,
const gleasy_framebuffer_t* fb) {
assert(prog != NULL);
assert(uniblock != NULL);
assert(fb != NULL);
loshader_pixsort_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
.fb = fb,
};
return drawer;
}
void loshader_pixsort_drawer_delete(loshader_pixsort_drawer_t* drawer) {
if (drawer == NULL) return;
memory_delete(drawer);
}
void loshader_pixsort_drawer_set_intensity(
loshader_pixsort_drawer_t* drawer,
float intensity) {
assert(drawer != NULL);
assert(MATH_FLOAT_VALID(intensity));
drawer->intensity = intensity;
}
void loshader_pixsort_drawer_draw(
const loshader_pixsort_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, drawer->fb->colorbuf);
glUniform1i(LOSHADER_PIXSORT_UNIFORM_SRC, 0);
glUniform1f(LOSHADER_PIXSORT_UNIFORM_INTENSITY, drawer->intensity);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
bool loshader_pixsort_drawer_is_skippable(
const loshader_pixsort_drawer_t* drawer) {
assert(drawer != NULL);
return drawer->intensity == 0;
}

View File

@@ -0,0 +1,71 @@
layout (location = 0) uniform sampler2D u_src;
layout (location = 1) uniform float u_intensity;
in vec2 v_uv;
out vec4 o_color;
const int N = 2;
const int S = 20;
float luminance(in vec4 col) {
return col.r*.3+col.g*.6+col.b*.1;
}
void main(void) {
vec2 uv = (v_uv + 1.)/2.;
vec2 uvi = uv * uni.resolution.y;
float unit = 1.0/uni.resolution.y;
o_color = texture(u_src, uv);
int darkest_y = 0;
float darkest_lum = 1.;
int brightest_y = 0;
float brightest_lum = 0.;
int stride = int(uni.resolution.y/float(S));
for (int i = 0; i < int(uni.resolution.y); i+=stride) {
vec4 col = texture(u_src, vec2(uv.x, unit*float(i)));
float lum = luminance(col);
if (brightest_lum < lum) {
brightest_y = i;
brightest_lum = lum;
}
if (darkest_lum > lum) {
darkest_y = i;
darkest_lum = lum;
}
}
int st = min(darkest_y, brightest_y);
int ed = max(darkest_y, brightest_y);
st = ed-int(float(ed-st)*u_intensity);
if (int(uvi.y) <= st || int(uvi.y) >= ed) {
return;
}
float lum_unit = (brightest_lum-darkest_lum) / float(N);
stride /= 5;
int count = st;
for (int n = 0; n < N; ++n) {
float n2 = float(darkest_y < brightest_y? n: N-n-1);
float low = lum_unit * n2 + darkest_lum;
float high = low + lum_unit;
for (int i = st; i < ed; i+=stride) {
vec4 col = texture(u_src, vec2(uv.x, unit*float(i)));
float lum = luminance(col);
if (low <= lum && lum <= high) {
count += stride;
if (count >= int(uvi.y)) {
o_color = col;
return;
}
}
}
}
}

51
core/loshader/pixsort.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/framebuffer.h"
#include "util/gleasy/program.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_pixsort_program_t;
struct loshader_pixsort_drawer_t;
typedef struct loshader_pixsort_drawer_t loshader_pixsort_drawer_t;
void
loshader_pixsort_program_initialize(
loshader_pixsort_program_t* prog
);
void
loshader_pixsort_program_deinitialize(
loshader_pixsort_program_t* prog
);
loshader_pixsort_drawer_t* /* OWNERSHIP */
loshader_pixsort_drawer_new(
const loshader_pixsort_program_t* prog,
const loshader_uniblock_t* uniblock,
const gleasy_framebuffer_t* fb
);
void
loshader_pixsort_drawer_delete(
loshader_pixsort_drawer_t* drawer /* OWNERSHIP */
);
void
loshader_pixsort_drawer_set_intensity(
loshader_pixsort_drawer_t* drawer,
float intensity
);
void
loshader_pixsort_drawer_draw(
const loshader_pixsort_drawer_t* drawer
);
bool
loshader_pixsort_drawer_is_skippable(
const loshader_pixsort_drawer_t* drawer
);

View File

@@ -0,0 +1,12 @@
out vec2 v_uv;
void main(void) {
const vec2[] verts = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., -1.),
vec2(-1., 1.), vec2( 1., -1.), vec2( 1., 1.)
);
v_uv = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
gl_Position = vec4(v_uv, 0., 1.);
}

144
core/loshader/posteffect.c Normal file
View File

@@ -0,0 +1,144 @@
#include "./posteffect.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/gleasy/framebuffer.h"
#include "util/gleasy/program.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "./uniblock.h"
/* resources */
#include "anysrc/header.shader.h"
#include "anysrc/posteffect.vshader.h"
#include "anysrc/posteffect.fshader.h"
#define LOSHADER_POSTEFFECT_UNIFORM_SRC 0
struct loshader_posteffect_drawer_t {
const loshader_posteffect_program_t* prog;
const loshader_uniblock_t* uniblock;
const gleasy_framebuffer_t* fb;
gleasy_buffer_uniform_t param;
};
#pragma pack(push, 1)
typedef struct {
float whole_blur;
float raster;
float radial_displacement;
float amnesia_displacement;
float radial_fade;
float brightness;
} loshader_posteffect_drawer_param_internal_t;
_Static_assert(
sizeof(float)*6 ==
sizeof(loshader_posteffect_drawer_param_internal_t));
#pragma pack(pop)
#define LOSHADER_POSTEFFECT_UNIBLOCK_INDEX 0
#define LOSHADER_POSTEFFECT_PARAM_INDEX 1
void loshader_posteffect_program_initialize(
loshader_posteffect_program_t* prog) {
assert(prog != NULL);
*prog = gleasy_program_new(
loshader_header_shader_, sizeof(loshader_header_shader_),
loshader_posteffect_vshader_, sizeof(loshader_posteffect_vshader_),
loshader_posteffect_fshader_, sizeof(loshader_posteffect_fshader_));
const GLuint uniblock = glGetUniformBlockIndex(*prog, "uniblock");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, uniblock, LOSHADER_POSTEFFECT_UNIBLOCK_INDEX);
const GLuint param = glGetUniformBlockIndex(*prog, "param");
assert(glGetError() == GL_NO_ERROR);
glUniformBlockBinding(*prog, param, LOSHADER_POSTEFFECT_PARAM_INDEX);
}
void loshader_posteffect_program_deinitialize(
loshader_posteffect_program_t* prog) {
assert(prog != NULL);
glDeleteProgram(*prog);
}
loshader_posteffect_drawer_t* loshader_posteffect_drawer_new(
const loshader_posteffect_program_t* prog,
const loshader_uniblock_t* uniblock,
const gleasy_framebuffer_t* fb) {
assert(prog != NULL);
assert(uniblock != NULL);
assert(fb != NULL);
loshader_posteffect_drawer_t* drawer = memory_new(sizeof(*drawer));
*drawer = (typeof(*drawer)) {
.prog = prog,
.uniblock = uniblock,
.fb = fb,
};
glGenBuffers(1, &drawer->param);
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferData(GL_UNIFORM_BUFFER,
sizeof(loshader_posteffect_drawer_param_internal_t),
NULL,
GL_DYNAMIC_DRAW);
return drawer;
}
void loshader_posteffect_drawer_delete(loshader_posteffect_drawer_t* drawer) {
if (drawer == NULL) return;
glDeleteBuffers(1, &drawer->param);
memory_delete(drawer);
}
void loshader_posteffect_drawer_set_param(
loshader_posteffect_drawer_t* drawer,
const loshader_posteffect_drawer_param_t* param) {
assert(drawer != NULL);
assert(param != NULL);
const loshader_posteffect_drawer_param_internal_t p = {
.whole_blur = param->whole_blur,
.raster = param->raster,
.radial_displacement = param->radial_displacement,
.amnesia_displacement = param->amnesia_displacement,
.radial_fade = param->radial_fade,
.brightness = param->brightness,
};
glBindBuffer(GL_UNIFORM_BUFFER, drawer->param);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(p), &p);
}
void loshader_posteffect_drawer_draw(
const loshader_posteffect_drawer_t* drawer) {
assert(drawer != NULL);
glUseProgram(*drawer->prog);
loshader_uniblock_bind(drawer->uniblock, LOSHADER_POSTEFFECT_UNIBLOCK_INDEX);
glBindBufferBase(GL_UNIFORM_BUFFER,
LOSHADER_POSTEFFECT_PARAM_INDEX, drawer->param);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, drawer->fb->colorbuf);
glUniform1i(LOSHADER_POSTEFFECT_UNIFORM_SRC, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
}

View File

@@ -0,0 +1,139 @@
layout (location = 0) uniform sampler2D u_src;
layout(std140) uniform param {
float whole_blur;
float raster;
float radial_displacement;
float amnesia_displacement;
float radial_fade;
float brightness;
} p;
in vec2 v_uv;
out vec4 o_color;
float atan2(in vec2 p){
return p.x == 0. ? sign(p.y)*PI/2. : atan(p.y, p.x);
}
vec2 to_polar(in vec2 p) {
return vec2(length(p), atan2(p));
}
vec2 to_rectangular(in vec2 p) {
return vec2(cos(p.y)*p.x, sin(p.y)*p.x);
}
float rand(in vec2 p) {
/* https://thebookofshaders.com/13/?lan=jp */
return fract(sin(dot(p.xy, vec2(12.9898, 78.233)))*43758.5453123);
}
float noise (in vec2 _st) {
/* https://thebookofshaders.com/13/?lan=jp*/
vec2 i = floor(_st);
vec2 f = fract(_st);
float a = rand(i);
float b = rand(i + vec2(1.0, 0.0));
float c = rand(i + vec2(0.0, 1.0));
float d = rand(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return
mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
float fbm (in vec2 _st) {
/* https://thebookofshaders.com/13/?lan=jp*/
const float octaves = 5;
float v = 0.0;
float a = 0.5;
vec2 shift = vec2(100.0);
mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50));
for (int i = 0; i < octaves; ++i) {
v += a * noise(_st);
_st = rot * _st * 2.0 + shift;
a *= 0.5;
}
return v;
}
vec2 radial_displacement(in vec2 polar) {
float intensity = p.radial_displacement + 1.;
float r = polar.x;
const float sqrt2 = sqrt(2.);
r = (1. - pow(abs(1. - r/sqrt2), intensity))*sqrt2 / intensity;
return vec2(r, polar.y);
}
vec2 amnesia_displacement(in vec2 uv) {
vec2 auv = abs(uv);
float intensity = p.amnesia_displacement*(1.-pow(max(auv.x, auv.y), 2.));
return uv + fbm(uv)*intensity - intensity/2.;
}
float radial_fade(in float len) {
float intensity = p.radial_fade;
return clamp(1. - intensity * max(len - (1.-intensity), 0.), 0., 1.);
}
vec4 chromatic_aberration(in vec2 uv) {
float a = length(v_uv)/sqrt(2.);
vec2 e = 1./uni.resolution*a;
return vec4(
texture(u_src, uv+e).r,
texture(u_src, uv).g,
texture(u_src, uv-e).b,
1.);
}
vec4 blur(in vec2 uv) {
vec2 e1 = vec2(1./uni.resolution.x, 0.);
vec2 e2 = vec2(0., 1./uni.resolution.y);
vec4 color =
texture(u_src, uv+e1+.0) +
texture(u_src, uv+e1+e2) +
texture(u_src, uv+.0+e2) +
texture(u_src, uv-e1+e2) +
texture(u_src, uv-e1+.0) +
texture(u_src, uv-e1-e2) +
texture(u_src, uv+.0-e2) +
texture(u_src, uv+e1-e2);
return color/8.;
}
void main(void) {
vec2 uv = v_uv;
/* transformation */
vec2 polar = to_polar(uv);
polar = radial_displacement(polar);
uv = to_rectangular(polar);
uv = amnesia_displacement(uv);
uv.x += sin(v_uv.y*PI*2./uni.aa*5.)*.05*p.raster;
/* pixel manipulation */
uv = (uv+1.)/2.;
vec4 color = chromatic_aberration(uv);
if (p.whole_blur > 0.) color = mix(color, blur(uv), p.whole_blur);
/* blending */
float a = radial_fade(polar.x);
o_color = mix(vec4(0., 0., 0., 1), color, a);
/* color manip */
o_color = pow(o_color, vec4(1.4));
o_color = min(o_color, vec4(max(o_color.r, max(o_color.g, o_color.b)))*.95);
o_color *= p.brightness;
}

View File

@@ -0,0 +1,57 @@
#pragma once
#include <stddef.h>
#include "util/gleasy/framebuffer.h"
#include "util/gleasy/program.h"
#include "./uniblock.h"
typedef gleasy_program_t loshader_posteffect_program_t;
struct loshader_posteffect_drawer_t;
typedef struct loshader_posteffect_drawer_t loshader_posteffect_drawer_t;
typedef struct {
float whole_blur;
float raster;
float radial_displacement;
float amnesia_displacement;
float radial_fade;
float brightness;
} loshader_posteffect_drawer_param_t;
void
loshader_posteffect_program_initialize(
loshader_posteffect_program_t* prog
);
void
loshader_posteffect_program_deinitialize(
loshader_posteffect_program_t* prog
);
loshader_posteffect_drawer_t* /* OWNERSHIP */
loshader_posteffect_drawer_new(
const loshader_posteffect_program_t* prog,
const loshader_uniblock_t* uniblock,
const gleasy_framebuffer_t* fb
);
void
loshader_posteffect_drawer_delete(
loshader_posteffect_drawer_t* drawer /* OWNERSHIP */
);
void
loshader_posteffect_drawer_set_param(
loshader_posteffect_drawer_t* drawer,
const loshader_posteffect_drawer_param_t* param
);
void
loshader_posteffect_drawer_draw(
const loshader_posteffect_drawer_t* drawer
);

View File

@@ -0,0 +1,11 @@
out vec2 v_uv;
void main(void) {
const vec2[] verts = vec2[](
vec2(-1., 1.), vec2(-1., -1.), vec2( 1., -1.),
vec2(-1., 1.), vec2( 1., -1.), vec2( 1., 1.)
);
v_uv = gl_VertexID < verts.length()? verts[gl_VertexID]: vec2(0.);
gl_Position = vec4(v_uv, 0., 1.);
}

250
core/loshader/set.c Normal file
View File

@@ -0,0 +1,250 @@
#include "./set.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/gleasy/atlas.h"
#include "util/gleasy/framebuffer.h"
#include "util/math/algorithm.h"
#include "util/math/vector.h"
#include "./backwall.h"
#include "./bullet.h"
#include "./character.h"
#include "./cinescope.h"
#include "./combat_ring.h"
#include "./event_line.h"
#include "./fog.h"
#include "./ground.h"
#include "./hud_bar.h"
#include "./hud_text.h"
#include "./menu_background.h"
#include "./menu_stance.h"
#include "./menu_text.h"
#include "./posteffect.h"
#include "./uniblock.h"
void loshader_set_initialize(
loshader_set_t* set,
int32_t width,
int32_t height,
const vec2_t* dpi,
int32_t max_msaa) {
assert(set != NULL);
assert(width > 0);
assert(height > 0);
assert(vec2_valid(dpi));
assert(max_msaa > 0);
*set = (typeof(*set)) {
.resolution = vec2(width, height),
.dpi = *dpi,
};
set->uniblock = loshader_uniblock_new();
loshader_uniblock_update_display_param(set->uniblock, &set->resolution, dpi);
int max_samples;
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_samples);
gleasy_framebuffer_initialize(
&set->framebuffer, width, height, MATH_MIN(max_samples, max_msaa));
/* TODO(catfoot): atlas size should depend on DPI. */
set->tex = (typeof(set->tex)) {
.hud_text = gleasy_atlas_new(GL_RED, 1024, 1024, true),
.menu_text = gleasy_atlas_new(GL_RED, 1024, 1024, true),
.event_line = gleasy_atlas_new(GL_RED, 1024, 1024, true),
};
loshader_backwall_program_initialize(&set->program.backwall);
loshader_ground_program_initialize(&set->program.ground);
loshader_character_program_initialize(&set->program.character);
loshader_bullet_program_initialize(&set->program.bullet);
loshader_fog_program_initialize(&set->program.fog);
loshader_pixsort_program_initialize(&set->program.pixsort);
loshader_posteffect_program_initialize(&set->program.posteffect);
loshader_hud_bar_program_initialize(&set->program.hud_bar);
loshader_hud_text_program_initialize(&set->program.hud_text);
loshader_menu_background_program_initialize(&set->program.menu_background);
loshader_menu_text_program_initialize(&set->program.menu_text);
loshader_menu_stance_program_initialize(&set->program.menu_stance);
loshader_combat_ring_program_initialize(&set->program.combat_ring);
loshader_cinescope_program_initialize(&set->program.cinescope);
loshader_event_line_program_initialize(&set->program.event_line);
set->drawer = (typeof(set->drawer)) {
.backwall = loshader_backwall_drawer_new(
&set->program.backwall, set->uniblock),
.ground = loshader_ground_drawer_new(
&set->program.ground, set->uniblock),
.character = loshader_character_drawer_new(
&set->program.character, set->uniblock),
.bullet = loshader_bullet_drawer_new(
&set->program.bullet, set->uniblock),
.fog = loshader_fog_drawer_new(
&set->program.fog, set->uniblock),
.pixsort = loshader_pixsort_drawer_new(
&set->program.pixsort, set->uniblock, &set->framebuffer),
.posteffect = loshader_posteffect_drawer_new(
&set->program.posteffect, set->uniblock, &set->framebuffer),
.hud_bar = loshader_hud_bar_drawer_new(
&set->program.hud_bar, set->uniblock),
.menu_background = loshader_menu_background_drawer_new(
&set->program.menu_background, set->uniblock),
.menu_stance = loshader_menu_stance_drawer_new(
&set->program.menu_stance, set->uniblock),
.combat_ring = loshader_combat_ring_drawer_new(
&set->program.combat_ring, set->uniblock),
.cinescope = loshader_cinescope_drawer_new(
&set->program.cinescope, set->uniblock),
};
loshader_hud_text_drawer_initialize(
&set->drawer.hud_text,
&set->program.hud_text,
set->uniblock,
gleasy_atlas_get_texture(set->tex.hud_text));
loshader_menu_text_drawer_initialize(
&set->drawer.menu_text,
&set->program.menu_text,
set->uniblock,
gleasy_atlas_get_texture(set->tex.menu_text));
loshader_event_line_drawer_initialize(
&set->drawer.event_line,
&set->program.event_line,
set->uniblock,
gleasy_atlas_get_texture(set->tex.event_line));
}
void loshader_set_deinitialize(loshader_set_t* set) {
assert(set != NULL);
loshader_backwall_drawer_delete(set->drawer.backwall);
loshader_ground_drawer_delete(set->drawer.ground);
loshader_character_drawer_delete(set->drawer.character);
loshader_bullet_drawer_delete(set->drawer.bullet);
loshader_fog_drawer_delete(set->drawer.fog);
loshader_pixsort_drawer_delete(set->drawer.pixsort);
loshader_posteffect_drawer_delete(set->drawer.posteffect);
loshader_hud_bar_drawer_delete(set->drawer.hud_bar);
loshader_hud_text_drawer_deinitialize(&set->drawer.hud_text);
loshader_menu_background_drawer_delete(set->drawer.menu_background);
loshader_menu_text_drawer_deinitialize(&set->drawer.menu_text);
loshader_menu_stance_drawer_delete(set->drawer.menu_stance);
loshader_combat_ring_drawer_delete(set->drawer.combat_ring);
loshader_cinescope_drawer_delete(set->drawer.cinescope);
loshader_event_line_drawer_deinitialize(&set->drawer.event_line);
loshader_backwall_program_deinitialize(&set->program.backwall);
loshader_ground_program_deinitialize(&set->program.ground);
loshader_character_program_deinitialize(&set->program.character);
loshader_bullet_program_deinitialize(&set->program.bullet);
loshader_fog_program_deinitialize(&set->program.fog);
loshader_pixsort_program_deinitialize(&set->program.pixsort);
loshader_posteffect_program_deinitialize(&set->program.posteffect);
loshader_hud_bar_program_deinitialize(&set->program.hud_bar);
loshader_hud_text_program_deinitialize(&set->program.hud_text);
loshader_menu_background_program_deinitialize(&set->program.menu_background);
loshader_menu_text_program_deinitialize(&set->program.menu_text);
loshader_menu_stance_program_deinitialize(&set->program.menu_stance);
loshader_combat_ring_program_deinitialize(&set->program.combat_ring);
loshader_cinescope_program_deinitialize(&set->program.cinescope);
loshader_event_line_program_deinitialize(&set->program.event_line);
gleasy_atlas_delete(set->tex.hud_text);
gleasy_atlas_delete(set->tex.menu_text);
gleasy_atlas_delete(set->tex.event_line);
loshader_uniblock_delete(set->uniblock);
gleasy_framebuffer_deinitialize(&set->framebuffer);
}
void loshader_set_clear_all(loshader_set_t* set) {
assert(set != NULL);
loshader_ground_drawer_clear(set->drawer.ground, 256);
loshader_character_drawer_clear(set->drawer.character, 256);
loshader_bullet_drawer_clear(set->drawer.bullet, 256);
loshader_hud_bar_drawer_clear(set->drawer.hud_bar, 16);
loshader_hud_text_drawer_clear(&set->drawer.hud_text, 256);
loshader_menu_background_drawer_set_alpha(set->drawer.menu_background, 0);
loshader_menu_text_drawer_clear(&set->drawer.menu_text, 512);
loshader_menu_stance_drawer_clear(set->drawer.menu_stance, 16);
loshader_combat_ring_drawer_clear(set->drawer.combat_ring, 8);
loshader_event_line_drawer_clear(&set->drawer.event_line, 256);
}
void loshader_set_draw_all(const loshader_set_t* set) {
assert(set != NULL);
/* ---- path 1: game ---- */
gleasy_framebuffer_bind(&set->framebuffer);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
loshader_backwall_drawer_draw(set->drawer.backwall);
loshader_ground_drawer_draw(set->drawer.ground);
loshader_character_drawer_draw(set->drawer.character);
loshader_bullet_drawer_draw(set->drawer.bullet);
loshader_fog_drawer_draw(set->drawer.fog);
gleasy_framebuffer_flush(&set->framebuffer);
/* ---- path 2: pixsort ---- */
if (!loshader_pixsort_drawer_is_skippable(set->drawer.pixsort)) {
gleasy_framebuffer_bind(&set->framebuffer);
loshader_pixsort_drawer_draw(set->drawer.pixsort);
gleasy_framebuffer_flush(&set->framebuffer);
}
/* ---- path 2: HUD ---- */
gleasy_framebuffer_bind(&set->framebuffer);
glDisable(GL_BLEND);
glDisable(GL_MULTISAMPLE);
loshader_posteffect_drawer_draw(set->drawer.posteffect);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);
loshader_hud_bar_drawer_draw(set->drawer.hud_bar);
loshader_hud_text_drawer_draw(&set->drawer.hud_text);
loshader_menu_background_drawer_draw(set->drawer.menu_background);
loshader_menu_text_drawer_draw(&set->drawer.menu_text);
loshader_menu_stance_drawer_draw(set->drawer.menu_stance);
loshader_combat_ring_drawer_draw(set->drawer.combat_ring);
loshader_cinescope_drawer_draw(set->drawer.cinescope);
loshader_event_line_drawer_draw(&set->drawer.event_line);
gleasy_framebuffer_flush_to_other(&set->framebuffer, 0);
}
void loshader_set_drop_cache(loshader_set_t* set) {
assert(set != NULL);
gleasy_atlas_clear(set->tex.hud_text);
gleasy_atlas_clear(set->tex.menu_text);
gleasy_atlas_clear(set->tex.event_line);
}

103
core/loshader/set.h Normal file
View File

@@ -0,0 +1,103 @@
#pragma once
#include <stdint.h>
#include "util/gleasy/atlas.h"
#include "util/gleasy/framebuffer.h"
#include "util/math/vector.h"
#include "./backwall.h"
#include "./bullet.h"
#include "./character.h"
#include "./cinescope.h"
#include "./combat_ring.h"
#include "./event_line.h"
#include "./fog.h"
#include "./ground.h"
#include "./hud_bar.h"
#include "./hud_text.h"
#include "./menu_background.h"
#include "./menu_stance.h"
#include "./menu_text.h"
#include "./pixsort.h"
#include "./posteffect.h"
#include "./uniblock.h"
typedef struct {
gleasy_framebuffer_t framebuffer;
loshader_uniblock_t* uniblock;
struct {
gleasy_atlas_t* hud_text;
gleasy_atlas_t* menu_text;
gleasy_atlas_t* event_line;
} tex;
struct {
loshader_backwall_program_t backwall;
loshader_ground_program_t ground;
loshader_character_program_t character;
loshader_bullet_program_t bullet;
loshader_fog_program_t fog;
loshader_pixsort_program_t pixsort;
loshader_posteffect_program_t posteffect;
loshader_hud_bar_program_t hud_bar;
loshader_hud_text_program_t hud_text;
loshader_menu_background_program_t menu_background;
loshader_menu_text_program_t menu_text;
loshader_menu_stance_program_t menu_stance;
loshader_combat_ring_program_t combat_ring;
loshader_cinescope_program_t cinescope;
loshader_event_line_program_t event_line;
} program;
struct {
loshader_backwall_drawer_t* backwall;
loshader_ground_drawer_t* ground;
loshader_character_drawer_t* character;
loshader_bullet_drawer_t* bullet;
loshader_fog_drawer_t* fog;
loshader_pixsort_drawer_t* pixsort;
loshader_posteffect_drawer_t* posteffect;
loshader_hud_bar_drawer_t* hud_bar;
loshader_hud_text_drawer_t hud_text;
loshader_menu_background_drawer_t* menu_background;
loshader_menu_text_drawer_t menu_text;
loshader_menu_stance_drawer_t* menu_stance;
loshader_combat_ring_drawer_t* combat_ring;
loshader_cinescope_drawer_t* cinescope;
loshader_event_line_drawer_t event_line;
} drawer;
vec2_t resolution;
vec2_t dpi;
} loshader_set_t;
void
loshader_set_initialize(
loshader_set_t* set,
int32_t width,
int32_t height,
const vec2_t* dpi,
int32_t max_msaa
);
void
loshader_set_deinitialize(
loshader_set_t* set
);
void
loshader_set_clear_all(
loshader_set_t* set
);
void
loshader_set_draw_all(
const loshader_set_t* set
);
void
loshader_set_drop_cache(
loshader_set_t* set
);

117
core/loshader/uniblock.c Normal file
View File

@@ -0,0 +1,117 @@
#include "./uniblock.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <GL/glew.h>
#include "util/gleasy/buffer.h"
#include "util/math/algorithm.h"
#include "util/math/vector.h"
#include "util/math/matrix.h"
#include "util/memory/memory.h"
#include "core/locommon/position.h"
struct loshader_uniblock_t {
gleasy_buffer_uniform_t buf;
};
#pragma pack(push, 1)
typedef struct {
vec2_t resolution;
vec2_t dpi;
float aa;
int8_t padding[12];
mat4_t proj;
mat4_t camera;
vec4_t pos;
float time;
} loshader_uniblock_internal_t;
_Static_assert(
sizeof(float)*5 + 12 + sizeof(float)*37 ==
sizeof(loshader_uniblock_internal_t));
#pragma pack(pop)
bool loshader_uniblock_param_valid(const loshader_uniblock_param_t* param) {
return
param != NULL &&
mat4_valid(&param->proj) &&
mat4_valid(&param->cam) &&
locommon_position_valid(&param->pos) &&
MATH_FLOAT_VALID(param->time);
}
loshader_uniblock_t* loshader_uniblock_new(void) {
loshader_uniblock_t* uni = memory_new(sizeof(*uni));
*uni = (typeof(*uni)) {0};
glGenBuffers(1, &uni->buf);
glBindBuffer(GL_UNIFORM_BUFFER, uni->buf);
glBufferData(GL_UNIFORM_BUFFER,
sizeof(loshader_uniblock_internal_t), NULL, GL_DYNAMIC_DRAW);
return uni;
}
void loshader_uniblock_delete(loshader_uniblock_t* uni) {
if (uni == NULL) return;
glDeleteBuffers(1, &uni->buf);
memory_delete(uni);
}
void loshader_uniblock_update_display_param(
loshader_uniblock_t* uni, const vec2_t* resolution, const vec2_t* dpi) {
assert(uni != NULL);
assert(vec2_valid(resolution));
assert(vec2_valid(dpi));
const loshader_uniblock_internal_t internal = {
.resolution = *resolution,
.dpi = *dpi,
.aa = MATH_MAX(dpi->x, dpi->y) / 100000,
};
static const size_t size =
offsetof(loshader_uniblock_internal_t, aa) + sizeof(internal.aa);
glBindBuffer(GL_UNIFORM_BUFFER, uni->buf);
glBufferSubData(GL_UNIFORM_BUFFER, 0, size, &internal);
}
void loshader_uniblock_update_param(
loshader_uniblock_t* uni,
const loshader_uniblock_param_t* param) {
assert(uni != NULL);
assert(loshader_uniblock_param_valid(param));
const vec4_t pos = vec4(
param->pos.chunk.x,
param->pos.chunk.y,
param->pos.fract.x,
param->pos.fract.y);
const loshader_uniblock_internal_t internal = {
.proj = param->proj,
.camera = param->cam,
.pos = pos,
.time = param->time,
};
static const size_t offset = offsetof(loshader_uniblock_internal_t, proj);
glBindBuffer(GL_UNIFORM_BUFFER, uni->buf);
glBufferSubData(GL_UNIFORM_BUFFER,
offset, sizeof(internal)-offset, &internal.proj);
}
void loshader_uniblock_bind(const loshader_uniblock_t* uni, GLuint index) {
assert(uni != NULL);
glBindBufferBase(GL_UNIFORM_BUFFER, index, uni->buf);
}

56
core/loshader/uniblock.h Normal file
View File

@@ -0,0 +1,56 @@
#pragma once
#include <stdbool.h>
#include <GL/glew.h>
#include "util/math/vector.h"
#include "util/math/matrix.h"
#include "core/locommon/position.h"
struct loshader_uniblock_t;
typedef struct loshader_uniblock_t loshader_uniblock_t;
typedef struct {
mat4_t proj;
mat4_t cam;
locommon_position_t pos;
float time;
} loshader_uniblock_param_t;
bool
loshader_uniblock_param_valid(
const loshader_uniblock_param_t* param
);
loshader_uniblock_t* /* OWNERSHIP */
loshader_uniblock_new(
void
);
void
loshader_uniblock_delete(
loshader_uniblock_t* uni /* OWNERSHIP */
);
void
loshader_uniblock_update_display_param(
loshader_uniblock_t* uni,
const vec2_t* resolution,
const vec2_t* dpi
);
void
loshader_uniblock_update_param(
loshader_uniblock_t* uni,
const loshader_uniblock_param_t* param
);
void
loshader_uniblock_bind(
const loshader_uniblock_t* uni,
GLuint index
);