#Custom Parallax

229 messages · Page 1 of 1 (latest)

swift sandal
#

A modding tool for easily creating custom parallax backgrounds

https://github.com/alex-3141/noita-parallax

Create backgrounds that have 3D depth, dynamically blend with the day/night and weather cycle, and have animations!

Very simple to configure, with some examples provided.

Free for anyone to use as they want in their own projects.

Version 1.0 allows for multiple mods to use this at the same time without any conflicts!

GitHub

A modding tool for Noita for creating parallax backgrounds - alex-3141/noita-parallax

left axle
#

I'm having some trouble getting this to work, the library works perfectly fine when I run it from the demo mod but upon trying to implement it into another mod I get severe slowdown.

I've checked all textures are registered and their filepaths are correct, all functions related to the Parallax file are where they should be, I've even tried copying the demo mod code verbatim but it still results in immense slowdown.
The only error I get in the console is the game yelling about a static texture being re-uploaded every frame, which is what I assume is the cause for lag.

--Handles Alex's custom parallax backgrounds
Parallax = dofile_once( "mods/Apotheosis/files/scripts/parallax_backgrounds/parallax.lua" )
dofile_once("mods/Apotheosis/files/scripts/parallax_backgrounds/parallax_data.lua")

function OnModInit()
    --Handles Alex's custom parallax backgrounds
    Parallax.registerLayers(10)

    -- All textures need to be registered
    Parallax.registerTextures({
    "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_clounds_01.png",
    "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_clounds_02.png",
    "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_mountains_layer_01.png",
    "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_mountains_02.png",
    "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_mountains_layer_02.png",
    "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/sky_colors_default.png",
    })
end

function OnModPostInit()
    -- Call during OnModPostInit()
    Parallax.postInit()
end

function OnWorldPostUpdate()

    if InputIsKeyJustDown(39) then demo_mountain() end -- Key_0

    -- Call once per frame
    if Parallax ~= nil then Parallax.update()  end
end

I've been trying to pinpoint the source of the slowdown but so far to no success

left axle
#

The re-uploaded error message still appears in console after running Parallax.push(nil, 30), I feel like I'm blind and missing a really obvious function to tell the library to stop uploading textures Hmm

#

I've confirmed it's not a conflict with the other shaders Apoth is running since the demo mod runs perfectly fine with Apoth enabled and removing the existing shader code in the mod doesn't resolve the slow down.

left axle
#

@swift sandal After further trying to debug the issue, the library seems to dislike something about my mods filepath.

Running the library in the demo mod & a 2nd test mod works fine, but trying to run that same previously functioning code with this filepath "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_clounds_01.png" breaks the library for some reason and I'm not sure why.

In other words, with the exact same code, example A works but example B and example C doesn't
A: "mods/noita-parallax_test/files/texture_data/parallax_clounds_01.png"
B: "mods/Apotheosis/files/scripts/parallax_backgrounds/textures/parallax_clounds_01.png"
C: "mods/Apotheosis/debug/textures/parallax_clounds_01.png"

I've tried setting the test mods folder name to use a capital letter which doesn't seem to cause the slowdown and I'm not sure what else could be the reason.
Would you know anything about the library which may be the cause for conflict?

quaint prairie
#

parallax should be local in the readme

#

as should a lot of the stuff

left axle
#

I've nailed it down to be something to do with folder names

quaint prairie
#

yeah its not your issue

#

but the demo is wrong

left axle
#

I think it's something to do with capital letters in the folder path

#

Yeah

#

Whenever I load the mod with only lower case letters as the folderpath it works perfectly fine; but if I run the mod with capital letters in the folderpath it freaks out

#

Yep, that's the bug

#

mods/noita-parallax_test/files/texture_data/ is fine but mods/noita-parallax_test/files/Texture_data/ isn't

quaint prairie
#

is the file actually at Texture_data?

#

paths are (meant to be) case sensitive

left axle
#

yes

#

I've tested it

#

Actually, it's strange this issue is happening on windows; I thought windows was indifferent to capitalisation on folderpaths

quaint prairie
#

its meant to be

#

im not sure if noita is

left axle
#

huh

quaint prairie
#

id guess its a noita issue

left axle
#

@swift sandal There's a bug with the parallax library where having any capital letters in the filepath for images the parallax uses causes the library to break and cause severe slowdown by attempting to reload the images every frame.

Edit: Apologises for the ping, this seems to actually be a noita API issue; not an issue from your library

quaint prairie
#

the error is from noita

#

its not an issue in the library i dont think

#

im pretty sure its noita

#

does it happen if you use the correct case?

left axle
#

No

#

Or

#

What do you mean by that?

quaint prairie
#

use the actual casing that the file has

left axle
#

if string="/texture_data/" and foldername="/texture_data/" then it works
if string="/Texture_data/" and foldername="/Texture_data/" then it doesnt' work

quaint prairie
#

weird

#

so its a noita bug

#

and not just windows doing files incorrectly

left axle
#

I'm not sure if it is, more specifically every mod I've used with capital letters in its folder name before has worked fine

#

This is the only instance I've seen capital letters be an issue

quaint prairie
#

yeah presumably its just the upload function being broken

left axle
#

ah

#

That may be it

#

fuuuucck I really hope it isn't a lua api bug

#

I just tried the string using upper case and the actual foldername being lower case

quaint prairie
#

it probably is

left axle
#

It causes the same issue

#

Yeah, I think you're right

#

There's no case manipulation in the library itself and the filepath is sent directly to GameSetPostFxTextureParamete

#

I'm guessing something about that function breaks if it reads a capital letter

#

I'm trying to think now if it'd be possible to change the github & steam foldername for Apoth to use lower case

quaint prairie
#

maybe vaguely useful:

      switch(wrapping_mode) {
      case 0:
         wrapping_mode_bits? = 0b0010100100000000;
         break;
      case 1:
         wrapping_mode_bits? = 0b1000000100101111;
         break;
      case 2:
         wrapping_mode_bits? = 0b1000000100101101;
         break;
      case 3:
         wrapping_mode_bits? = 0b0010100100000001;
         break;
      case 4:
         wrapping_mode_bits? = 0b1000001101110000;
         break;
#

presumably these correspond to some data passed to the actual graphics api

#

no idea what

left axle
#

The good news is steam seems indifferent to folder capitalisation, so renaming Apotheosis to apotheosis will retain workshop data

#

@quaint prairie Sorry for bothering you again, but do you know if it's possible to rename a github repo?
Essentially just changing the Apoth github to use a lowercase a

quaint prairie
#

yes

#

go to repo settings

#

name is at the top

left axle
#

Ah, I found it, thankyou

#

I was looking at the wrong settings cog

#

Alright, perfect

swift sandal
#

This library is a little rough around the edges though, I wouldn't be surprised if there were other subtle bugs

quaint prairie
#

make all your things local

#

its healthy

#

also surely submodule the actual library so it can be included without including the demo

left axle
#

@swift sandal Would it be possible to make images repeat on the y-axis like they do on the x-axis?

swift sandal
#

That should wrap it on both x and y, let me know if it's not doing that for some reason

#

Or maybe I'm misunderstanding what you mean...

left axle
#

It turns into line spaghetti halfway through the image I posted

swift sandal
#

That looks like clamping behaviour, let me have a deeper look into things

left axle
#

Alrighty

swift sandal
#

Actually, It's manually doing the texture repeat, see inject.lua line 98

#

you can change it to uv.y = fract(uv.y); to make it repeat, but that will apply to all textures

left axle
#

Ah

#

Yeah, that works specifically for my nebula use-case but breaks all other parallaxs visually

swift sandal
#

It shouldn't be too hard to make it configurable per texture, I'll make an update for it

left axle
#

Thankyou ❤️

left axle
#

@swift sandal Another issue I just encountered is that the library doesn't take the data/ path into account, attempting to install the library into the data directory results in the library failing to load since it expects to be in a mods/modname/files/ directory.

swift sandal
left axle
#

@swift sandal Another bug I've encountered but I can't consistently replicate, is sometimes the ModSettings the mod uses gets "jammed" and the library stops functioning entirely.
It is fixable by deleting my mod settings and having them be restored to their default values, so perhaps setting the ModSettings to their default values during setup would be a good backup to ensure the settings can't get jammed, if applicable

left axle
#

An inaccuracy in the documentation;
The documentation says 0.0 depth is infinitely distant and 1.0 is in the foreground; but in practice it seems to be the other way around.
Low depth is something being up close to the character and high depth is something being far away

#

To give some good news, I am having a lot of fun seeing what looks good and what doesn't nanora

#

I think I'd like to redo the coloured gas clouds next, I need to find a good cloud-like brush for them

#

Perfect

swift sandal
#

That looks incredible! This gives me motivation to improve the mod

#

Im setting aside the rest of the day to work on this

quaint prairie
swift sandal
#

I'm thinking of allowing a transformation matrix to be passed instead of providing individual values for x, y, scroll, etc.

#

And then you supply your own callback function that updates it each frame

#

That would help reduce the number of uniforms used, which is a limiting performance factor in this mod

#

(I love making more work for myself)

left axle
#

Hahahaha

#

Oh yeah, I'm assuming Spoop already told you, but would it be possible to have foreground parallaxs?
It's not an important feature request but if it'd be easy to implement it'd be a nice tool to have

left axle
swift sandal
#

every bit is sacred

#

Theres also a limit to the number of textures that can be used, so some form of texture aliasing may be useful. But that would massively complicate things so Ill not try that

left axle
swift sandal
#

Not a problem for anyone using dedicated GPUs

left axle
#

Ah, huh

#

Is the limit a small number I should be weary about, or is it high enough that I could make 4-5 backgrounds without needing to worry about hitting it?
I know the exact amount would vary depending on if the user is using a CPU graphics, or a dedicated GPU, what kind and so on; but in general would an averageish user need to worry about it?

quaint prairie
#

why not do bgs as sprites with low z

#

that way you dont have to worry about gpu

swift sandal
quaint prairie
#

what if you want different textures in different areas?

#

can this handle that

left axle
#

Huh

swift sandal
left axle
#

I'm at 15 currently, I might be able to cut 4 textures away by compressing the sun flares but there's still 3 more backgrounds I want to do

quaint prairie
#

also is this library designed to be used in multiple mods?

#

is it submoduleable and does the negotiation itself or is it a standalone dep

swift sandal
# quaint prairie can this handle that

Textures can be replaced on the fly, but I don't expose this in the mod yet. Ill add it to the TODO.
Otherwise, switching between banks can already achieve this.

swift sandal
#

this includes any other existing textures and other mods using the shader too

swift sandal
quaint prairie
#

standalone or submodule?

swift sandal
#

I think just standalone, I didn't have a great understanding of how Lua libraries should operate when I wrote this

left axle
#

Alright

#

I'll pay attention to texture count then, cheers

swift sandal
#

The shader uniforms are shared state across the entire engine

quaint prairie
#

you have to decide if you should do git submodule add your_library_repo lib/something or require that mod users install it from the workshop

#

if you do submodules you have to figure out how you are versioning it and making sure that only one copy of it actually runs

#

workshop is easier but less convenient for end users

swift sandal
#

Oh as in git submodules? No, this is just a lua file you place and then run entity_hamis

quaint prairie
#

😱

#

what if updates

swift sandal
#

Ill have to figure that out...

quaint prairie
#

the basic idea is you set globals based on the version of the library, and one of them ends up winning

#

whoever the winner is is the only one that runs

swift sandal
#

Right, maximum dependency versions

quaint prairie
#

its not too bad, but getting the sequencing correct with the globals is a bit of a pain

#

because you cant immediately use globals, they only start working in later callbacks

#

if you need to modify the shaders early you can do it pre negotiation if the modifications are going to stay the same across all versions, otherwise you probably need to do workshop

#

like i just set the credits to blank immediately, because they get parsed quite early

#

and so if i did it after deciding who had the latest version it wouldnt work

#

actually a better approach might be get the enabled mods and include a version file in every one of them 🤔

#

that could work well

#

actually that approach is definitely better

#

forgot we could get active mods now

swift sandal
#

Ill need to change the shadercode, which needs to be static and compile during init. I was thinking of putting a version identifier comment in the shadercode, and then looking for that to check for other mods that have applied these changes beforehand

#

but Ill then need to make the changes I make reverseable...

#

enough code boundary comments should suffice

#

one missing semicolon and the game no longer launches...

#

I love it

quaint prairie
#

i think the best approach is do

mods
- modid
- - lib
- - - parallax_bgs
- - - - version.txt
- - - - init.lua
- - init.lua

the the mods init.lua calls your init.lua, and your init.lua does

local path = "data/parallax_bg/temp.txt"
ModTextFileSetContent(path, "empty")
local whoami = ModTextFileWhoSetContent(path)

local function get_path_name(modname)
    return ("mods/%s/lib/parallax_bg/%s"):format(whoami, modname)
end

local _require = require
---@param modname string
---@return any
function require(modname)
    return dofile_once(get_path_name(modname:gsub("%.", "/")) .. ".lua")
end

local my_version = tonumber(ModTextFileGetContent(get_path_name("version.txt")))
local won = true
local seen_me = false

for _, v in ipairs(ModGetActiveModIDs()) do
    local other_path = ("mods/%s/lib/parallax_bg/version.txt"):format(v)
    if not ModDoesFileExist(other_path) then goto continue end
    if v == whoami then seen_me = true end
    local version = tonumber(ModTextFileGetContent(other_path))
    if version > my_version or (version == my_version and not seen_me) then
        won = false
        break
    end
    ::continue::
end

if won then
    do_stuff(...)
end

require = _require
#

so that you win if your version is the highest, or if you are the first with your version

#

you ofc have to make sure you dont make any breaking changes

swift sandal
#

hmmhmm, thanks!

quaint prairie
#

note that was written in discord, so odds of being bug free are low

swift sandal
#

Ill push it directly to main without review 👍

quaint prairie
#

indeed, 2 of the api functions dont exist

left axle
#

Is there a proper way to implement stars into a background?
ie similar to the ones you'd see during vanilla night time noita

swift sandal
#

I know the ones on the title screen are dynamic, but im not sure of in-game. The game has a star opacity texture which it uses but im not sure if the actual stars are dynamic or a texture

#

for dynamic stars that twinkle separately, custom shader code may be needed

left axle
#

Staring at vanilla stars for a while, it looks like the stars are grouped;
For example:
group 1 will always be bright
group 2 will pulse in & out
group 3 will also pulse in & out, but out of sync with group 2

quaint prairie
#

if you could control alpha for each bg layer thatd be easy

left axle
#

So it may be feasible to replicate with just the parallax library

#

The library does support that but that leads to my next problem, which is I'm having some trouble understanding how it works

quaint prairie
#

im not convinced that doing this is in a shader is a good idea

swift sandal
#

Yep should be easy with transparency

quaint prairie
#

rather than bg sprites

#

i suppose there are the awesome lightning fx

swift sandal
#

thats a good point too

quaint prairie
#

but those could be handled

#

what advantages are you getting from shader?

swift sandal
quaint prairie
#

its just sprite with z below world

swift sandal
#

The shader allows for effects to be applied like warping, which I don't think bg sprites could do

quaint prairie
#

yes

left axle
# swift sandal what part specifically?

I was trying to use the desert antennae as an example since they blink on & off but I only managed to get a missing texture to appear when I tried doing something similar using dynamic colours to making stars fade in & out on a cycle.

I don't think I'm understanding the system fundamentally

#

My current understanding of the system is the way it works is you give an RGB colour input, a time of day as a keyframe and how the colour should be transitioned into (ie Parallax.INTERP.LINEAR for a linear transition).

From there the data can be read by some bank layers to tweak their colouring & opacity? (I'm assuming opacity since the blinkers on the desert temple disappear from view, but given there's no alpha input I acknowledge this is likely just be it being "invisible" due to it being black on a blackish background)

#

I then tried updating the alpha value directly similar to how the MoveCloud function does it, but had trouble getting any impact in-game

swift sandal
#

The comment at the bottom of parallax.lua is a good reference for the settings

-- sky_index        | Index of the sky color to use
-- sky_source       | Where to get the sky color from. 0 = texture, 1 = dynamic. Can be a mix, eg. 0.5. Dynamic colors can be set via Parallax.sky.dynamic_colors
-- alpha_index      | Index of the alpha color to use. Pulls from the same list as sky_index
-- alpha_source     | Where to get the alpha color from. 0 = texture, 1 = dynamic. Can be a mix, eg. 0.5
-- alpha_blend      | How much the alpha color should blend with the layer. 0 = no blending, 1 = full blending. Dynamic colors can be set via Parallax.sky.dynamic_colors
#

In the desert demo, I set alpha_source of the antennas to use the dynamic color:

    {id = "temple-antennas", path = "mods/noita-parallax/files/tex/demo/temple-antennas.png",
    offset_y = 0.3, offset_x = -0.4, depth = 0.85, sky_blend = 0.0, alpha_blend = 1.0,
    alpha_source = Parallax.SKY_SOURCE.DYNAMIC, alpha_index = 1, alpha = 0.5,
    },
#

it's a bit messy, I know

left axle
#

How does the alpha_source read RGB data for alpha purposes?

swift sandal
#

it's a simple multiplication, so 0 which is black will be completely transparent (ie multiply the color by zero), and 255 is full opacity

#

and the colors are multiplied component wise

#

Let me verify this is how it actually works, Its been a while since I looked at this code

left axle
#

Alrighty

#

I think I got it

#

Let me remove the cloud layer for a better look

swift sandal
#

There's multiple layers of color blending:

  1. Sky color, which colors all layers to match the time of day. This can come from either a texture or a dynamic value (or a mix)
  2. Overall layer alpha from layer.alpha
  3. The alpha values in the original texture itself
left axle
left axle
#

Sorry for bothering you constantly the past few days

swift sandal
#

No worries, this is helping me make this mod more usable so it's a good thing

quaint prairie
#

you probably want fg sprites too

#

for the clouds

#

can this do fg?

#

surely other than emissive

left axle
#

I thought of adding foreground clouds, but the clouds aren't meant to be the main focus of the background I'm currently working on

swift sandal
#

No, but another thing I can add

left axle
#

I'm still trying to find the right look for it, but it's essentially meant to be a dreamy somewhat surreal sky, like the sort of sky you'd see in a dream

swift sandal
#

If you get a bunch of large background sprites with transparrency, and update their positions each frame, can you replicate the effect that this mod provides?

#

Moving things out of the shader is always good where possible

swift sandal
#

I'm figuring out a mechanism to allow multiple versions of the library to operate at the same time. The main issue is that each version of the library will change how it communicates with the shader, meaning that the version of the shadercode must match the same version of the library.

Having some kind of abstraction layer where each version of the library can push it's desired settings, and then the abstraction layer can ensure the shadercode is on the latest available version and upgrade older configs to work with it would be good. But I'm not sure something like that is possible with Noita modding...

#

The shadercode is annoyingly global, and expects data in an exact format

#

I have a terrible idea of putting a copy of the library into a global setting which each mod can then update to the latest version available during init, and then read it back during post init and execute it to effectively upgrade to that version. Then that version will be able to handle any previous versions of the config that may be used

#

What I really need is a way to run a single copy of the library which can be accessed by multiple different mods, across Lua contexts

swift sandal
#

During mod init and then post-init I can determine which mod has the most recent version of the library, and that mod can become the leader that makes the shadercode changes.

Then during gameplay, a controller entity can be placed in the world by the leader and I'm hoping all mods can then interface with that entity to push changes

quaint prairie
#

get the enabled mods, then check a version file for each of them

swift sandal
quaint prairie
#

why wouldnt you be able to?

#

they are part of the filesystem

swift sandal
#

I had the idea that mods are pretty much isolated from eachother

quaint prairie
#

different init lua contexts but other thant there is no difference between mods

swift sandal
#

As for my idea of having a controller entity that multiple mods can interface with, would that be a viable approach? I don't know if there's a way to call a function on an entity that has a LuaComponent

quaint prairie
#

think about the contexts

#

nothing can really interact across contexts

#

just have a list of scripts and dofile each of them

swift sandal
#

hmm, I see

swift sandal
#

communication between lua contexts using damage messages, including some numbers and a string 👍

#

just like using $ kill, in a literal way

swift sandal
#

Not particularly useful for my case, but fun