Impl. shader to improve ElectricityEffect
Some checks failed
Build and Publish WASM version of demo / Build-And-Deploy (push) Failing after 15s
Some checks failed
Build and Publish WASM version of demo / Build-And-Deploy (push) Failing after 15s
This commit is contained in:
parent
4755b53deb
commit
2e97bb6a83
3 changed files with 181 additions and 4 deletions
|
@ -1,8 +1,23 @@
|
|||
#include "electricity_effect.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define DEBUG_PRINT_VEC2(v2) \
|
||||
do { \
|
||||
std::cout << "Loading " << #v2 << " with value " << (v2).x << ", " \
|
||||
<< (v2).y << std::endl; \
|
||||
} while (false);
|
||||
#define DEBUG_PRINT_FLOAT(f) \
|
||||
do { \
|
||||
std::cout << "Loading " << #f << " with value " << (f) << std::endl; \
|
||||
} while (false);
|
||||
#endif
|
||||
|
||||
// standard library includes
|
||||
#include <queue>
|
||||
#include <tuple>
|
||||
#ifndef NDEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
// third party includes
|
||||
#include <raylib.h>
|
||||
|
@ -12,6 +27,8 @@
|
|||
#include "3d_helpers.h"
|
||||
#include "ems.h"
|
||||
|
||||
std::optional<Shader> ElectricityEffect::shader = std::nullopt;
|
||||
|
||||
ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
||||
int line_count, float lifetime)
|
||||
: end_points(),
|
||||
|
@ -70,6 +87,11 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
|||
positions.push({coll.point, end_points.size() - 1});
|
||||
}
|
||||
}
|
||||
|
||||
// Update shader height if not initialized.
|
||||
if (!shader.has_value()) {
|
||||
update_shader_height();
|
||||
}
|
||||
}
|
||||
|
||||
bool ElectricityEffect::update(float dt) {
|
||||
|
@ -88,16 +110,154 @@ bool ElectricityEffect::update(float dt) {
|
|||
return timer >= lifetime;
|
||||
}
|
||||
|
||||
void ElectricityEffect::draw(Color color, Vector3 camera_pos) {
|
||||
void ElectricityEffect::draw(Color color, Camera *camera) {
|
||||
float ratio = timer < lifetime ? (1.0F - timer / lifetime) : 0.0F;
|
||||
|
||||
// Update shader values common to all quads.
|
||||
{
|
||||
int colDiffuse = GetShaderLocation(shader.value(), "colDiffuse");
|
||||
Vector4 normalizedColor = ColorNormalize(color);
|
||||
SetShaderValue(shader.value(), colDiffuse, &normalizedColor,
|
||||
SHADER_UNIFORM_VEC4);
|
||||
}
|
||||
|
||||
for (const auto &end_point : end_points) {
|
||||
if (end_point.next_idx >= 0) {
|
||||
std::array<Vector3, 4> quad = get_quad_from_start_end(
|
||||
end_point.point, end_points[end_point.next_idx].point,
|
||||
camera_pos - end_point.point, QUAD_MAX_WIDTH * ratio);
|
||||
camera->position - end_point.point, QUAD_MAX_WIDTH * ratio);
|
||||
Vector2 q0 = GetWorldToScreen(quad[0], *camera);
|
||||
Vector2 q1 = GetWorldToScreen(quad[3], *camera);
|
||||
Vector2 q2 = GetWorldToScreen(quad[1], *camera);
|
||||
Vector2 q3 = GetWorldToScreen(quad[2], *camera);
|
||||
q1 = Vector2Subtract(q0, q1);
|
||||
q3 = Vector2Subtract(q2, q3);
|
||||
|
||||
// Update shader values.
|
||||
update_shader_sides(q0, q1, q2, q3, Vector2Distance(q0, q2));
|
||||
|
||||
// Draw with shader.
|
||||
BeginShaderMode(shader.value());
|
||||
DrawTriangle3D(quad[0], quad[1], quad[2], color);
|
||||
DrawTriangle3D(quad[0], quad[2], quad[3], color);
|
||||
EndShaderMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shader ElectricityEffect::get_shader() {
|
||||
if (!shader.has_value()) {
|
||||
init_shader();
|
||||
}
|
||||
return shader.value();
|
||||
}
|
||||
|
||||
void ElectricityEffect::cleanup_shader() {
|
||||
if (shader.has_value()) {
|
||||
UnloadShader(shader.value());
|
||||
shader.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void ElectricityEffect::update_shader_height() {
|
||||
if (!shader.has_value()) {
|
||||
init_shader();
|
||||
}
|
||||
int uniform_loc = GetShaderLocation(shader.value(), "screen_height");
|
||||
float height = GetScreenHeight();
|
||||
DEBUG_PRINT_FLOAT(height);
|
||||
SetShaderValue(shader.value(), uniform_loc, &height, SHADER_UNIFORM_FLOAT);
|
||||
}
|
||||
|
||||
void ElectricityEffect::update_shader_sides(Vector2 a, Vector2 adir, Vector2 b,
|
||||
Vector2 bdir, float width) {
|
||||
if (!shader.has_value()) {
|
||||
init_shader();
|
||||
}
|
||||
int uniform_loc = GetShaderLocation(shader.value(), "sidePosA");
|
||||
DEBUG_PRINT_VEC2(a);
|
||||
SetShaderValue(shader.value(), uniform_loc, &a, SHADER_UNIFORM_VEC2);
|
||||
uniform_loc = GetShaderLocation(shader.value(), "sideDirA");
|
||||
DEBUG_PRINT_VEC2(adir);
|
||||
SetShaderValue(shader.value(), uniform_loc, &adir, SHADER_UNIFORM_VEC2);
|
||||
uniform_loc = GetShaderLocation(shader.value(), "sidePosB");
|
||||
DEBUG_PRINT_VEC2(b);
|
||||
SetShaderValue(shader.value(), uniform_loc, &b, SHADER_UNIFORM_VEC2);
|
||||
uniform_loc = GetShaderLocation(shader.value(), "sideDirB");
|
||||
DEBUG_PRINT_VEC2(bdir);
|
||||
SetShaderValue(shader.value(), uniform_loc, &bdir, SHADER_UNIFORM_VEC2);
|
||||
uniform_loc = GetShaderLocation(shader.value(), "width");
|
||||
DEBUG_PRINT_FLOAT(width);
|
||||
SetShaderValue(shader.value(), uniform_loc, &width, SHADER_UNIFORM_FLOAT);
|
||||
}
|
||||
|
||||
void ElectricityEffect::init_shader() {
|
||||
// Set up electricity shader.
|
||||
// Vertex shader is exactly the same as Raylib's default vertex shader.
|
||||
shader = LoadShaderFromMemory(
|
||||
// vertex
|
||||
"#version 100 \n"
|
||||
"attribute vec3 vertexPosition; \n"
|
||||
"attribute vec2 vertexTexCoord; \n"
|
||||
"attribute vec4 vertexColor; \n"
|
||||
"varying vec2 fragTexCoord; \n"
|
||||
"varying vec4 fragColor; \n"
|
||||
"uniform mat4 mvp; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" fragTexCoord = vertexTexCoord; \n"
|
||||
" fragColor = vertexColor; \n"
|
||||
" gl_Position = mvp*vec4(vertexPosition, 1.0); \n"
|
||||
"} \n",
|
||||
|
||||
// fragment
|
||||
"#version 100 \n"
|
||||
"precision mediump float; \n"
|
||||
"varying vec2 fragTexCoord; \n"
|
||||
"varying vec4 fragColor; \n"
|
||||
"uniform sampler2D texture0; \n"
|
||||
"uniform vec4 colDiffuse; \n"
|
||||
"uniform float screen_height; \n"
|
||||
"uniform float width; \n"
|
||||
"uniform vec2 sidePosA; \n"
|
||||
"uniform vec2 sideDirA; \n"
|
||||
"uniform vec2 sidePosB; \n"
|
||||
"uniform vec2 sideDirB; \n"
|
||||
"float dot_get_alpha(vec2 pos, vec2 dir, vec2 point) { \n"
|
||||
" return ((dir.x * point.x + dir.y * point.y) \n"
|
||||
" - (dir.x * pos.x + dir.y * pos.y)) \n"
|
||||
" / (dir.x * dir.x + dir.y * dir.y); \n"
|
||||
"} \n"
|
||||
"vec2 closest_point(vec2 pos, vec2 dir, vec2 point) { \n"
|
||||
" return pos + dir * dot_get_alpha(pos, dir, point); \n"
|
||||
"} \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
|
||||
" vec4 color = texelColor*colDiffuse*fragColor; \n"
|
||||
" vec2 pos = gl_FragCoord.xy; \n"
|
||||
" pos.y = screen_height - pos.y; \n"
|
||||
" vec2 closest = closest_point(sidePosA, sideDirA, pos); \n"
|
||||
" float distA = distance(pos, closest); \n"
|
||||
" closest = closest_point(sidePosB, sideDirB, pos); \n"
|
||||
" float distB = distance(pos, closest); \n"
|
||||
" float min_dist = width * 0.3; \n"
|
||||
" if (min_dist < 0.00001) { \n"
|
||||
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
|
||||
" } else if (distA < distB) { \n"
|
||||
" if (distA < min_dist) { \n"
|
||||
" float lerpVal = distA / min_dist; \n"
|
||||
" gl_FragColor = color * (1.0 - lerpVal) \n"
|
||||
" + vec4(1.0, 1.0, 1.0, 1.0) * lerpVal; \n"
|
||||
" } else { \n"
|
||||
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n"
|
||||
" } \n"
|
||||
" } else if (distB < min_dist) { \n"
|
||||
" float lerpVal = distB / min_dist; \n"
|
||||
" gl_FragColor = color * (1.0 - lerpVal) \n"
|
||||
" + vec4(1.0, 1.0, 1.0, 1.0) * lerpVal; \n"
|
||||
" } else { \n"
|
||||
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n"
|
||||
" } \n"
|
||||
"} \n");
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define JUMPARTIFACT_DOT_COM_DEMO_0_ELECTRICITY_EFFECT_H_
|
||||
|
||||
// standard library includes
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
// third party includes
|
||||
|
@ -21,7 +22,13 @@ class ElectricityEffect {
|
|||
/// Returns true if lifetime ended.
|
||||
bool update(float dt);
|
||||
/// Assumes draw mode is active.
|
||||
void draw(Color color, Vector3 camera_pos);
|
||||
void draw(Color color, Camera *camera);
|
||||
|
||||
static Shader get_shader();
|
||||
static void cleanup_shader();
|
||||
static void update_shader_height();
|
||||
static void update_shader_sides(Vector2 a, Vector2 adir, Vector2 b,
|
||||
Vector2 bdir, float width);
|
||||
|
||||
private:
|
||||
struct EndPoint {
|
||||
|
@ -29,11 +36,14 @@ class ElectricityEffect {
|
|||
Vector3 point, mdir;
|
||||
};
|
||||
|
||||
static std::optional<Shader> shader;
|
||||
std::vector<EndPoint> end_points;
|
||||
Vector3 center;
|
||||
float radius;
|
||||
float lifetime;
|
||||
float timer;
|
||||
|
||||
static void init_shader();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -76,12 +76,17 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
|
|||
bgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
fgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
|
||||
// Initialize ElectricityEffect shader.
|
||||
ElectricityEffect::update_shader_height();
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::cout << "Screen finished init.\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
TRunnerScreen::~TRunnerScreen() {
|
||||
ElectricityEffect::cleanup_shader();
|
||||
|
||||
UnloadRenderTexture(fgRenderTexture);
|
||||
UnloadRenderTexture(bgRenderTexture);
|
||||
|
||||
|
@ -96,6 +101,8 @@ bool TRunnerScreen::update(float dt, bool is_resized) {
|
|||
|
||||
bgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
fgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
|
||||
ElectricityEffect::update_shader_height();
|
||||
}
|
||||
|
||||
if (flags.test(1)) {
|
||||
|
@ -365,7 +372,7 @@ bool TRunnerScreen::draw(RenderTexture *render_texture) {
|
|||
}
|
||||
|
||||
for (auto &ee : electricityEffects) {
|
||||
ee.draw(GREEN, camera.position);
|
||||
ee.draw(GREEN, &camera);
|
||||
}
|
||||
|
||||
for (auto &se : sparkEffects) {
|
||||
|
|
Loading…
Reference in a new issue