Skip to content

Commit

Permalink
Merge pull request #254 from stupxd/main
Browse files Browse the repository at this point in the history
SMODS.Shader - optional method for custom external vars
  • Loading branch information
Aurelius7309 committed Sep 6, 2024
2 parents 6003a78 + 51d5771 commit aa464d3
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 3 deletions.
2 changes: 2 additions & 0 deletions core/game_object.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2605,6 +2605,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj.
'path',
},
set = 'Shader',
send_vars = nil, -- function (sprite) - get custom externs to send to shader.
inject = function(self)
self.full_path = (self.mod and self.mod.path or SMODS.path) ..
'assets/shaders/' .. self.path
Expand Down Expand Up @@ -2647,6 +2648,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj.
calculate = nil, -- function (self)
on_apply = nil, -- function (card) - modify card when edition is applied
on_remove = nil, -- function (card) - modify card when edition is removed
on_load = nil, -- function (card) - modify card when it is loaded from the save file
register = function(self)
self.config = self.config or {}
SMODS.Edition.super.register(self)
Expand Down
12 changes: 12 additions & 0 deletions core/overrides.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,18 @@ function Card:should_draw_shadow()
return not next(self.ignore_shadow or {})
end

local smods_card_load = Card.load
--
function Card:load(cardTable, other_card)
local ret = smods_card_load(self, cardTable, other_card)
local on_edition_loaded = self.edition and self.edition.key and G.P_CENTERS[self.edition.key].on_load
if type(on_edition_loaded) == "function" then
on_edition_loaded(self)
end

return ret
end

-- self = pass the card
-- edition =
-- nil (removes edition)
Expand Down
25 changes: 24 additions & 1 deletion example_mods/Mods/EditionExamples/EditionExamples.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
--- MOD_AUTHOR: [Eremel_, stupxd]
--- MOD_DESCRIPTION: Adds editions that demonstrate Edition API.
--- BADGE_COLOUR: 3FC7EB
--- DEPENDENCIES: [Steamodded>=1.0.0~ALPHA-0812d]
--- DEPENDENCIES: [Steamodded>=1.0.0~ALPHA-0905a]

SMODS.Atlas({
key = 'edition_example',
Expand Down Expand Up @@ -122,6 +122,29 @@ SMODS.Back({
unlocked = true
})

---- CUSTOM VARS USAGE EXAMPLE
SMODS.Shader {
key = 'gold',
path = 'gold.fs',
-- card can be nil if sprite.role.major is not Card
send_vars = function (sprite, card)
return {
lines_offset = card and card.edition.example_gold_seed or 0
}
end,
}
SMODS.Edition {
key = "gold",
shader = "gold",
on_apply = function (card)
-- Randomize offset to -1..1
-- Save in card.edition table so it persists after game restart.
card.edition.example_gold_seed = pseudorandom('e_example_gold') * 2 - 1
end,
}
---- CUSTOM VARS USAGE EXAMPLE END


SMODS.Shader({ key = 'anaglyphic', path = 'anaglyphic.fs' })
SMODS.Shader({ key = 'flipped', path = 'flipped.fs' })
SMODS.Shader({ key = 'fluorescent', path = 'fluorescent.fs' })
Expand Down
6 changes: 4 additions & 2 deletions example_mods/Mods/EditionExamples/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Introduction
A Balatro example mod for adding a custom Editions in Steamodded.
A Balatro example mod for adding custom Editions and Shaders.

Feel free to copy and use this for any of projects!
Feel free to copy and use this* for any of projects!

***`anaglyphic`, `fluorescent`, `gilded`, `ionized`, `monochrome`, `greyscale` and `overexposed` shaders are not for public use and are only provided for learning purposes! (as requested by Eremel)**

## Notes in case you can't read
**If you want an Edition to have more than one of the following:**
Expand Down
6 changes: 6 additions & 0 deletions example_mods/Mods/EditionExamples/assets/shaders/flipped.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
#define PRECISION mediump
#endif

//
// Shader made by: stupxd
// You are free to use and modify this shader in your projects,
// as long as you credit me for the original work.
//

// Look ionized.fs for explanation
extern PRECISION vec2 flipped;

Expand Down
121 changes: 121 additions & 0 deletions example_mods/Mods/EditionExamples/assets/shaders/gold.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
#define PRECISION highp
#else
#define PRECISION mediump
#endif

//
// Shader made by: stupxd
// You are free to use and modify this shader in your projects,
// as long as you credit me for the original work.
//

extern PRECISION vec2 gold;

extern PRECISION number dissolve;
extern PRECISION number time;
extern PRECISION vec4 texture_details;
extern PRECISION vec2 image_details;
extern bool shadow;
extern PRECISION vec4 burn_colour_1;
extern PRECISION vec4 burn_colour_2;

// Custom extern from SMODS.Shader
extern PRECISION float lines_offset;

#define TWO_PI 6.28318530718

vec4 gold_color = vec4(231., 164., 25., 0.) / 255.;

vec4 dissolve_mask(vec4 final_pixel, vec2 texture_coords, vec2 uv);

bool line(vec2 uv, float offset, float width) {
uv.x = uv.x * texture_details.z / texture_details.w;

offset = offset + 0.35 * sin(gold.x + TWO_PI * lines_offset);
width = width + 0.005 * sin(gold.x);

float min_y = -uv.x + offset;
float max_y = -uv.x + offset + width;

return uv.y > min_y && uv.y < max_y;
}

vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords )
{
vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.zw)/texture_details.zw;
vec4 pixel = Texel(texture, texture_coords);

vec4 tex = vec4(1., 1., 1., 0.1);

if (
lines_offset > 0 && (line(uv, 0.0, 0.07) || line(uv, 0.4, 0.1) || line(uv, 0.55, 0.1) || line(uv, 1.3, 0.05) || line(uv, 1.8, 0.1)) ||
(line(uv, -0.1, 0.13) || line(uv, 0.3, 0.05) || line(uv, 0.8, 0.1) || line(uv, 1.3, 0.11) || line(uv, 1.7, 0.07))
) {
tex.a = tex.a * 2.;
} else {
tex.a = 0.05;
}

float avg = (pixel.r + pixel.g + pixel.b) / 3.;
pixel = vec4(gold_color.rgb * avg + tex.rgb * tex.a, pixel.a);

return dissolve_mask(pixel, texture_coords, uv);
}

vec4 dissolve_mask(vec4 final_pixel, vec2 texture_coords, vec2 uv)
{
if (dissolve < 0.001) {
return vec4(shadow ? vec3(0.,0.,0.) : final_pixel.xyz, shadow ? final_pixel.a*0.3: final_pixel.a);
}

float adjusted_dissolve = (dissolve*dissolve*(3.-2.*dissolve))*1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values

float t = time * 10.0 + 2003.;
vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a);
vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a);

vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324));
vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532));
vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000));

float field = (1.+ (
cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) +
cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.;
vec2 borders = vec2(0.2, 0.8);

float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14))
- (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
- (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
- (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve)
- (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve);

if (final_pixel.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
final_pixel.rgba = burn_colour_1.rgba;
} else if (burn_colour_2.a > 0.01) {
final_pixel.rgba = burn_colour_2.rgba;
}
}

return vec4(shadow ? vec3(0.,0.,0.) : final_pixel.xyz, res > adjusted_dissolve ? (shadow ? final_pixel.a*0.3: final_pixel.a) : .0);
}

extern PRECISION vec2 mouse_screen_pos;
extern PRECISION float hovering;
extern PRECISION float screen_scale;

#ifdef VERTEX
vec4 position( mat4 transform_projection, vec4 vertex_position )
{
if (hovering <= 0.){
return transform_projection * vertex_position;
}
float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy);
vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale;
float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist))
*hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist);

return transform_projection * vertex_position + vec4(0,0,0,scale);
}
#endif
22 changes: 22 additions & 0 deletions lovely/edition.toml
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,28 @@ payload = """
elseif self.edition.type == 'negative' and (self.ability.set == 'Enhanced' or self.ability.set == 'Default') then
badges[#badges + 1] = 'negative_playing_card'"""
match_indent = true

[[patches]]
[patches.pattern]
target = "engine/sprite.lua"
pattern = "love.graphics.setShader( G.SHADERS[_shader or 'dissolve'], G.SHADERS[_shader or 'dissolve'])"
position = "before"
payload = '''
local p_shader = SMODS.Shader.obj_table[_shader or 'dissolve']
if p_shader and type(p_shader.send_vars) == "function" then
local sh = G.SHADERS[_shader or 'dissolve']
local parent_card = self.role.major and self.role.major:is(Card) and self.role.major
local send_vars = p_shader.send_vars(self, parent_card)
if type(send_vars) == "table" then
for key, value in pairs(send_vars) do
sh:send(key, value)
end
end
end
'''
match_indent = true

[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
Expand Down

0 comments on commit aa464d3

Please sign in to comment.