Skip to content
Permalink
Browse files

OpenGL ES 2.0 support (#187)

* WIP gles2 compat

* More gles2 compat. Playable with ANGLE now, with some rendering bugs.

* fix matrix mult. order in generic laser shader

* gles20: fix indexed rendering

* Update docs about gles20 status

* fix formatting
  • Loading branch information
Akaricchi committed Feb 15, 2020
1 parent 44bd09b commit 7474ff3a2594ecefc58cce5b681ab7ad619b8455
Showing with 304 additions and 94 deletions.
  1. +12 −3 README.rst
  2. +2 −1 doc/ENVIRON.rst
  3. +18 −15 resources/00-taisei.pkgdir/shader/boss_death.frag.glsl
  4. +11 −6 resources/00-taisei.pkgdir/shader/fxaa.frag.glsl
  5. +11 −4 resources/00-taisei.pkgdir/shader/fxaa.vert.glsl
  6. +29 −0 resources/00-taisei.pkgdir/shader/interface/fxaa.glslh
  7. +3 −2 resources/00-taisei.pkgdir/shader/laser_generic.vert.glsl
  8. +6 −1 resources/00-taisei.pkgdir/shader/lasers/common.vert.glslh
  9. +2 −5 resources/00-taisei.pkgdir/shader/lasers/vertex_pos.glslh
  10. +4 −0 resources/00-taisei.pkgdir/shader/lib/defs.glslh
  11. +33 −15 resources/00-taisei.pkgdir/shader/lib/fxaa.glslh
  12. +17 −0 resources/00-taisei.pkgdir/shader/lib/legacy_compat.glslh
  13. +19 −16 resources/00-taisei.pkgdir/shader/player_death.frag.glsl
  14. +1 −0 src/boss.c
  15. +11 −2 src/laser.c
  16. +1 −0 src/player.c
  17. +4 −0 src/renderer/api.c
  18. +2 −7 src/renderer/api.h
  19. +1 −1 src/renderer/common/shaderlib/cache.c
  20. +10 −1 src/renderer/common/shaderlib/lang_spirv.c
  21. +1 −1 src/renderer/common/shaderlib/lang_spirv_aux.c
  22. +48 −5 src/renderer/gl33/shader_program.c
  23. +5 −2 src/renderer/gl33/shader_program.h
  24. +5 −0 src/renderer/glcommon/debug.c
  25. +7 −0 src/renderer/glcommon/texture.c
  26. +7 −3 src/renderer/gles20/gles20.c
  27. +5 −1 src/renderer/glescommon/texture.c
  28. +14 −0 src/resource/shader_object.c
  29. +3 −1 src/stages/stage1.c
  30. +2 −0 src/stages/stage2.c
  31. +2 −0 src/stages/stage3.c
  32. +2 −0 src/stages/stage4.c
  33. +2 −0 src/stages/stage5.c
  34. +4 −2 src/stages/stage6.c
@@ -15,7 +15,7 @@ Installation
Dependencies
^^^^^^^^^^^^

- OpenGL >= 3.3 or OpenGL ES >= 3.0
- OpenGL >= 3.3 or OpenGL ES >= 3.0 or OpenGL ES >= 2.0 (with some extensions)
- SDL2 >= 2.0.6
- SDL2_mixer >= 2.0.4
- freetype2
@@ -108,8 +108,17 @@ Alternatively, do this to make GLES 3.0 the default backend:

meson configure -Dr_default=gles30

Note that while it's also possible to enable a GLES 2.0 backend, it's currently
not functional.
The OpenGL ES 2.0 backend can be enabled similarly, using ``gles20`` instead of
``gles30``. However, it requires a few extensions to function correctly, most
notably:

- ``OES_depth_texture`` or ``GL_ANGLE_depth_texture``
- ``OES_standard_derivatives``
- ``OES_vertex_array_object``
- ``EXT_frag_depth``
- ``EXT_instanced_arrays`` or ``ANGLE_instanced_arrays`` or
``NV_instanced_arrays``


Where are my replays, screenshots and settings?
-----------------------------------------------
@@ -117,10 +117,11 @@ Video and OpenGL

- ``gl33``: the OpenGL 3.3 Core renderer
- ``gles30``: the OpenGL ES 3.0 renderer
- ``gles20``: the OpenGL ES 2.0 renderer
- ``null``: the no-op renderer (nothing is displayed)

Note that the actual subset of usable backends, as well as the default
choice, can be controlled by build options. The ``gles30`` backend is not
choice, can be controlled by build options. The ``gles`` backends are not
built by default.

**TAISEI_LIBGL**
@@ -10,10 +10,14 @@ UNIFORM(3) vec2 clear_origin;
UNIFORM(4) int frames;
UNIFORM(5) float progress;
UNIFORM(6) sampler2D noise_tex;
UNIFORM(7) float size;

ivec3 in_circle(vec2 pos, vec2 ofs, float a, vec2 origin, vec3 radius) {
mat2 m = mat2(cos(a), -sin(a), sin(a), cos(a));
return ivec3(lessThan(vec3(length(pos + m * ofs - origin)), radius));
vec3 xor(vec3 a, vec3 b) {
return abs(a - b);
}

vec3 in_circle(vec2 pos, vec2 ofs, float a, vec2 origin, vec3 radius) {
return step(vec3(length(pos + rot(a) * ofs - origin)), radius);
}

vec3 f(float x, vec3 s) {
@@ -40,25 +44,24 @@ void main(void) {
nclr.rgb = max(colormod * vec3(0.1, 0.1, 0.3), nclr.rgb);

vec2 p = texCoord * viewport;
float s = sqrt(pow(viewport.x, 2) + pow(viewport.y, 2));
float o = 32 * (1 + progress);
ivec3 mask = ivec3(0);
vec3 mask = vec3(0);
float a = frames / 30.0;

ivec3 i = ivec3(1,2,3);
vec3 q = 1.0 + 0.01 * i * progress;

mask = mask ^ in_circle(p, vec2(0, 0), 1*a, origin, s * f(pow(progress * 1.5, 1.5), 1.0*q));
mask = mask ^ in_circle(p, vec2(o, 0), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = mask ^ in_circle(p, vec2(0, o), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = mask ^ in_circle(p, -vec2(o, 0), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = mask ^ in_circle(p, -vec2(0, o), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = xor(mask, in_circle(p, vec2(0, 0), 1*a, origin, size * f(pow(progress * 1.5, 1.5), 1.0*q)));
mask = xor(mask, in_circle(p, vec2(o, 0), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));
mask = xor(mask, in_circle(p, vec2(0, o), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));
mask = xor(mask, in_circle(p, -vec2(o, 0), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));
mask = xor(mask, in_circle(p, -vec2(0, o), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));

mask = mask ^ in_circle(p, vec2(0, 0), -2*a, origin, s * f(pow(progress * 1.5, 1.5/1.5), 1.0*q));
mask = mask ^ in_circle(p, vec2(o, 0), -2*a, origin, s * f(pow(progress * 1.5, 1.5/2.0), 1.0*q));
mask = mask ^ in_circle(p, vec2(0, o), -2*a, origin, s * f(pow(progress * 1.5, 1.5/2.0), 1.0*q));
mask = mask ^ in_circle(p, -vec2(o, 0), -2*a, origin, s * f(pow(progress * 1.5, 1.5/2.0), 1.0*q));
mask = mask ^ in_circle(p, -vec2(0, o), -2*a, origin, s * f(pow(progress * 1.5, 1.5/2.0), 1.0*q));
mask = xor(mask, in_circle(p, vec2(0, 0), -2*a, origin, size * f(pow(progress * 1.5, 1.5/1.5), 1.0*q)));
mask = xor(mask, in_circle(p, vec2(o, 0), -2*a, origin, size * f(pow(progress * 1.5, 1.5/2.0), 1.0*q)));
mask = xor(mask, in_circle(p, vec2(0, o), -2*a, origin, size * f(pow(progress * 1.5, 1.5/2.0), 1.0*q)));
mask = xor(mask, in_circle(p, -vec2(o, 0), -2*a, origin, size * f(pow(progress * 1.5, 1.5/2.0), 1.0*q)));
mask = xor(mask, in_circle(p, -vec2(0, o), -2*a, origin, size * f(pow(progress * 1.5, 1.5/2.0), 1.0*q)));

fragColor = mix(pclr, nclr, vec4(mask, 0));
}
@@ -1,12 +1,17 @@
#version 330 core

#include "lib/fxaa.glslh"
#include "interface/standard.glslh"

UNIFORM(1) sampler2D depth;
VARYING(3) vec4 fxaa_tc;
#include "interface/fxaa.glslh"

void main(void) {
fragColor = vec4(fxaa(tex, fxaa_tc), 1);
gl_FragDepth = texture(depth, fxaa_tc.xy).r;
fragColor = vec4(fxaa(
tex,
v_rcpFrame,
v_coordNW,
v_coordNE,
v_coordSW,
v_coordSE,
v_coordM
), 1);
gl_FragDepth = texture(depth, v_coordM).r;
}
@@ -1,12 +1,19 @@
#version 330 core

#include "lib/fxaa.glslh"
#include "interface/standard.glslh"
#include "interface/fxaa.glslh"
#include "lib/render_context.glslh"

VARYING(3) vec4 fxaa_tc;

void main(void) {
gl_Position = r_projectionMatrix * r_modelViewMatrix * vec4(position, 1.0);
fxaa_tc = fxaaCoords(tex, texCoordRawIn);
v_rcpFrame = 1.0 / tex_SIZE;
fxaaCoords(
texCoordRawIn,
v_rcpFrame,
v_coordNW,
v_coordNE,
v_coordSW,
v_coordSE,
v_coordM
);
}
@@ -0,0 +1,29 @@

#ifndef I_FXAA_H
#define I_FXAA_H

#include "../lib/defs.glslh"

#ifdef VERT_STAGE
ATTRIBUTE(0) vec3 position;
// ATTRIBUTE(1) vec3 normalIn;
ATTRIBUTE(2) vec2 texCoordRawIn;
#endif

#ifdef FRAG_STAGE
OUT(0) vec4 fragColor;
#endif

UNIFORM(0) sampler2D tex;
UNIFORM(1) vec2 tex_SIZE;
UNIFORM(2) sampler2D depth;

VARYING(0) vec2 v_coordNW;
VARYING(1) vec2 v_coordNE;
VARYING(2) vec2 v_coordSW;
VARYING(3) vec2 v_coordSE;
VARYING(4) vec2 v_coordM;
VARYING(5) vec2 v_coordRaw;
VARYING(6) vec2 v_rcpFrame;

#endif
@@ -5,6 +5,7 @@
#include "interface/standard.glslh"

ATTRIBUTE(3) vec4 instance_pos_delta;
ATTRIBUTE(4) float instance_width;

UNIFORM(1) float timeshift;
UNIFORM(2) float width;
@@ -14,8 +15,8 @@ UNIFORM(4) int span;
#include "lasers/vertex_pos.glslh"

void main(void) {
vec2 pos = laser_vertex_pos(instance_pos_delta.xy, instance_pos_delta.zw);
gl_Position = r_modelViewMatrix * r_projectionMatrix * vec4(pos, 0.0, 1.0);
vec2 pos = laser_vertex_pos(instance_pos_delta.xy, instance_pos_delta.zw, instance_width);
gl_Position = r_projectionMatrix * r_modelViewMatrix * vec4(pos, 0.0, 1.0);
texCoord = (r_textureMatrix * vec4(texCoordRawIn, 0.0, 1.0)).xy;
texCoordRaw = texCoordRawIn;
}
@@ -18,7 +18,12 @@ void main(void) {
vec2 p = pos_rule(gl_InstanceID * 0.5 + timeshift);
vec2 d = p - pos_rule(gl_InstanceID * 0.5 + timeshift - 0.1);

vec2 pos = laser_vertex_pos(p, d);
float t1 = gl_InstanceID - span / 2;
float tail = span / 1.9;
float s = -0.75 / pow(tail, 2) * (t1 - tail) * (t1 + tail);
s = pow(s, width_exponent);

vec2 pos = laser_vertex_pos(p, d, s);
gl_Position = r_projectionMatrix * r_modelViewMatrix * vec4(pos, 0.0, 1.0);
texCoord = (r_textureMatrix * vec4(texCoordRawIn, 0.0, 1.0)).xy;
texCoordRaw = texCoordRawIn;
@@ -1,14 +1,11 @@

vec2 laser_vertex_pos(vec2 origin, vec2 delta) {
vec2 laser_vertex_pos(vec2 origin, vec2 delta, float fragment_width) {
vec2 v = position.xy;
float t1 = gl_InstanceID - span / 2;
float tail = span / 1.9;
float s = -0.75 / pow(tail, 2) * (t1 - tail) * (t1 + tail);
float a = -angle(delta);
mat2 m = mat2(cos(a), -sin(a), sin(a), cos(a));

v.x *= width * 1.5 * length(delta);
v.y *= width * pow(s, width_exponent);
v.y *= width * fragment_width;;

return m * v + origin;
}
@@ -37,4 +37,8 @@
#define NATIVE_ORIGIN_BOTTOMLEFT
#endif

#if defined(BACKEND_GLES20)
#include "legacy_compat.glslh"
#endif

#endif
@@ -24,14 +24,20 @@

#ifdef FRAG_STAGE

vec3 fxaa(sampler2D tex, vec4 posPos) {
vec2 rcpFrame = vec2(1.0) / textureSize(tex, 0);

vec3 rgbNW = textureLod(tex, posPos.zw, 0).rgb;
vec3 rgbNE = textureLodOffset(tex, posPos.zw, 0, ivec2(1, 0)).rgb;
vec3 rgbSW = textureLodOffset(tex, posPos.zw, 0, ivec2(0, 1)).rgb;
vec3 rgbSE = textureLodOffset(tex, posPos.zw, 0, ivec2(1, 1)).rgb;
vec3 rgbM = textureLod(tex, posPos.xy, 0).rgb;
vec3 fxaa(
sampler2D tex,
vec2 rcpFrame,
vec2 coordNW,
vec2 coordNE,
vec2 coordSW,
vec2 coordSE,
vec2 coordM
) {
vec3 rgbNW = textureLod(tex, coordNW, 0).rgb;
vec3 rgbNE = textureLod(tex, coordNE, 0).rgb;
vec3 rgbSW = textureLod(tex, coordSW, 0).rgb;
vec3 rgbSE = textureLod(tex, coordSE, 0).rgb;
vec3 rgbM = textureLod(tex, coordM, 0).rgb;

vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
@@ -56,13 +62,13 @@ vec3 fxaa(sampler2D tex, vec4 posPos) {
dir = min(vec2(FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX), dir * rcpDirMin)) * rcpFrame.xy;

vec3 rgbA = 0.5 * (
textureLod(tex, posPos.xy + dir * (1.0/3.0 - 0.5), 0).rgb +
textureLod(tex, posPos.xy + dir * (2.0/3.0 - 0.5), 0).rgb
textureLod(tex, coordM + dir * (1.0/3.0 - 0.5), 0).rgb +
textureLod(tex, coordM + dir * (2.0/3.0 - 0.5), 0).rgb
);

vec3 rgbB = rgbA * 0.5 + 0.25 * (
textureLod(tex, posPos.xy + dir * (0.0/3.0 - 0.5), 0).rgb +
textureLod(tex, posPos.xy + dir * (3.0/3.0 - 0.5), 0).rgb
textureLod(tex, coordM + dir * (0.0/3.0 - 0.5), 0).rgb +
textureLod(tex, coordM + dir * (3.0/3.0 - 0.5), 0).rgb
);

float lumaB = dot(rgbB, luma);
@@ -78,9 +84,21 @@ vec3 fxaa(sampler2D tex, vec4 posPos) {

#ifdef VERT_STAGE

vec4 fxaaCoords(sampler2D tex, vec2 tc) {
vec2 rcpFrame = vec2(1.0) / textureSize(tex, 0);
return vec4(tc, tc - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT)));
void fxaaCoords(
in vec2 texCoord,
in vec2 rcpFrame,
out vec2 o_coordNW,
out vec2 o_coordNE,
out vec2 o_coordSW,
out vec2 o_coordSE,
out vec2 o_coordM
) {
vec2 texCoordShifted = texCoord - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT));
o_coordNW = texCoordShifted + vec2( 0.0, 0.0) * rcpFrame;
o_coordNE = texCoordShifted + vec2( 1.0, 0.0) * rcpFrame;
o_coordSW = texCoordShifted + vec2( 0.0, 1.0) * rcpFrame;
o_coordSE = texCoordShifted + vec2( 1.0, 1.0) * rcpFrame;
o_coordM = texCoord;
}

#endif
@@ -0,0 +1,17 @@

#ifndef LEGACY_COMPAT_H
#define LEGACY_COMPAT_H

#define LEGACY

#define textureLod(sampler, uv, lod) texture(sampler, uv)
// #define textureLodOffset(sampler, uv, lod) texture(sampler, uv)
#define textureGrad(sampler, uv, dx, dy) texture(sampler, uv)

#define tanh _tanh_compat
float tanh(float x) {
float e2x = exp(2.0 * x);
return (e2x - 1.0) / (e2x + 1.0);
}

#endif
@@ -10,10 +10,14 @@ UNIFORM(3) vec2 clear_origin;
UNIFORM(4) int frames;
UNIFORM(5) float progress;
UNIFORM(6) sampler2D noise_tex;
UNIFORM(7) float size;

ivec3 in_circle(vec2 pos, vec2 ofs, float a, vec2 origin, vec3 radius) {
mat2 m = mat2(cos(a), -sin(a), sin(a), cos(a));
return ivec3(lessThan(vec3(length(pos + m * ofs - origin)), radius));
vec3 xor(vec3 a, vec3 b) {
return abs(a - b);
}

vec3 in_circle(vec2 pos, vec2 ofs, float a, vec2 origin, vec3 radius) {
return step(vec3(length(pos + rot(a) * ofs - origin)), radius);
}

vec3 f(float x, vec3 s) {
@@ -40,25 +44,24 @@ void main(void) {
nclr.rgb = max(colormod * vec3(0.1, 0.1, 0.3), nclr.rgb);

vec2 p = texCoord * viewport;
float s = sqrt(pow(viewport.x, 2) + pow(viewport.y, 2));
float o = 32 * (1 + progress);
ivec3 mask = ivec3(0);
vec3 mask = vec3(0);
float a = frames / 30.0;

vec3 i = vec3(1, 2, 3);
vec3 q = 1.0 + 0.01 * i * progress;

mask = mask ^ in_circle(p, vec2(0, 0), 1*a, origin, s * f(pow(progress * 1.5, 1.5), 1.0*q));
mask = mask ^ in_circle(p, vec2(o, 0), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = mask ^ in_circle(p, vec2(0, o), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = mask ^ in_circle(p, -vec2(o, 0), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = mask ^ in_circle(p, -vec2(0, o), 1*a, origin, s * f(pow(progress * 1.5, 2.0), 1.0*q));
mask = xor(mask, in_circle(p, vec2(0, 0), 1*a, origin, size * f(pow(progress * 1.5, 1.5), 1.0*q)));
mask = xor(mask, in_circle(p, vec2(o, 0), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));
mask = xor(mask, in_circle(p, vec2(0, o), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));
mask = xor(mask, in_circle(p, -vec2(o, 0), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));
mask = xor(mask, in_circle(p, -vec2(0, o), 1*a, origin, size * f(pow(progress * 1.5, 2.0), 1.0*q)));

mask = xor(mask, in_circle(p, vec2(0, 0), -2*a, clear_origin, size * (1 - pow(vec3(2 - 2 * progress), 4+0.10*i))));
mask = xor(mask, in_circle(p, vec2(o, 0), -2*a, clear_origin, size * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i))));
mask = xor(mask, in_circle(p, -vec2(o, 0), -2*a, clear_origin, size * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i))));
mask = xor(mask, in_circle(p, vec2(0, o), -2*a, clear_origin, size * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i))));
mask = xor(mask, in_circle(p, -vec2(0, o), -2*a, clear_origin, size * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i))));

mask = mask ^ in_circle(p, vec2(0, 0), -2*a, clear_origin, s * (1 - pow(vec3(2 - 2 * progress), 4+0.10*i)));
mask = mask ^ in_circle(p, vec2(o, 0), -2*a, clear_origin, s * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i)));
mask = mask ^ in_circle(p, -vec2(o, 0), -2*a, clear_origin, s * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i)));
mask = mask ^ in_circle(p, vec2(0, o), -2*a, clear_origin, s * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i)));
mask = mask ^ in_circle(p, -vec2(0, o), -2*a, clear_origin, s * (1 - pow(vec3(2 - 2 * progress), 2+0.05*i)));

fragColor = mix(pclr, nclr, vec4(mask, 0));
}
@@ -1221,6 +1221,7 @@ static void boss_death_effect_draw_overlay(Projectile *p, int t) {
r_uniform_vec2("origin", creal(p->pos), VIEWPORT_H - cimag(p->pos));
r_uniform_vec2("clear_origin", creal(p->pos), VIEWPORT_H - cimag(p->pos));
r_uniform_vec2("viewport", VIEWPORT_W, VIEWPORT_H);
r_uniform_float("size", hypotf(VIEWPORT_W, VIEWPORT_H));
draw_framebuffer_tex(framebuffers->back, VIEWPORT_W, VIEWPORT_H);
fbpair_swap(framebuffers);

0 comments on commit 7474ff3

Please sign in to comment.
You can’t perform that action at this time.