[Music]
hi I'm Reverend Craig and I welcome you
to this video in the tutorial series
shaders for Hobby programmers this video
will be a short addendum to the previous
day and night cycle shader videos
because I got several requests on how to
add sprite lights to the shader and I
thought I might as well create a short
video on that I won't explain everything
in detail our chests show and comment
changes I added to this version and in
the links below you'll find the GMs 2
project file to download also if you
come from the video about the day and
night cycle shader version 1.1 rights to
this video you missed a few important
concepts you will at least need to know
how to pass a second texture into a
shader I covered that topic in the
tutorials on luma masks let me explain
the basic idea first we'll get into some
more details later so we got this
mock-up created from assets by Makayla
Kelly a link to his open game our
profile is below the video as well what
I want to do now is add lights like this
the way we're going to do this is we'll
create light objects and let a control
object draw the sprites of each instance
onto a black light surface in additive
blend mode then we'll pass the light
surface into the shader and the shade of
will step 1 take the sample from the
application surface where the game is on
that's the base color
step to calculate the day-night cycle
call it without the lights in version
1.1 we called this out caller and I'll
leave it that way
step 3 take a sample from the light
surface the lights color step 4 multiply
the base color with the normalized
lights call it and the lights factor
step 5 calculated the lights color value
step 6 mix the out collar with the light
and face collar and the mix amount is
the value of the lights color so the
brighter the light sample is the more of
the base collar times the lights collar
will show and the darker the lights
value is the more of the out collar will
show and the final result will look like
this
so this is the project file you can
download by the link below
I added several light sprites similar to
this one and I added two light objects
and apparent light object
parent object is just an invisible empty
shell and the children got one of the
lights rights and are set to be
invisible as well
now those actually wouldn't need any
code at all
if the light is static but if you want
to change the lights attributes
dynamically then you can add code to
them and this one I added a very simple
rotation by changing the image Channel
and I let the light strength pulse by
changing the image alpha over time in
the step event and in this object I
added some more code to add some scale
pulsing and for demo reasons to change
the light sprites with a toll button on
the GUI we are not going through that
code since that's not the topic of this
video but here I also set some variable
definitions to set the maximum scaling
and stir speed or time until the pulse
and direction changes again so we can
change those for each instance
individually in room editor
and here's the controller object it's
based on the version 1.1 is no new
events in here and only the create event
and the drug we begin event have changed
a bit
we'll look into those two events in a
second
in the demo room I created a new layer
for the lights instances
and for each of those instances we can
change attributes like the scale the
rotation and to call it the darker the
call it is less bright the light will be
and that's one of the problems in this
lighting shader a pure red light will be
quite stark it only has a brightness of
1/3 since the blue and the green
channels are a zero so keep that in mind
and don't set pure red green or blue
instead you should lighten them up a bit
and of course we can also change the
variables we prepared in the variable
definitions of the object
and in the GUI I added a second slide
and to toggle groups one group with only
one button this will be used to show the
light surface instead of the final
result and the second toggle group will
change the light sprites
so let's look into the code of the
controller object
the left is version 1.1 as it was at the
end of the last video on the day and
night cycles on the right is version 1.2
with the new light system
title in infrared not just changed info
text nothing important
in the sprite and shader region we'll
only need three new variables for the
light surface as slides is the sampler
index for the light surface text slides
will be the texture ID of the light
surface and surface lights will be the
surface ID of the light surface
the color variables remain unchanged
and the key times remain unchanged as
well and the only thing that changed in
the water reflection section is the
script that's called before the
reflection tile layer is drawn we had to
do that when changing from version 1 to
1.1 and we need to do it here again so
in self calling script set off v11 we
need to call v12 and inside the script
of course I changed V 1 1 to V 1 2 as
well
now the resize region will stay the same
and the new GUI region is for demo
purposes only I'm naming the new slider
and toggle buttons
there's not much in create event that
changed the only important changes were
the sample index texture ID and surface
ID
to the drug we begin event I added a lot
to this but nothing complicated Chris
let's have a look at the part where we
set the shader and draw the application
surface as you can see there's only one
new line here the line to send the
texture ID of the light surface text
lights to the shader sampler index as
lights
at the end I added a small debug feature
to draw the light surface on top of
everything so we can see what light
surface looks like before this we need
to create the light surface and draw the
lights onto the surface this code checks
if the light surface exists and if not
creates one installs the texture ID used
for the shader in this demo the surface
is the same size as the application
surface then we can set the surface and
draw the lights onto it step 1 set up
the surface and GPU we need a black
surface to start with and to add lights
we need to be in blend mode add if the
lights instances in the room editor are
scaled you might want to also turn on
the linear texture filter here like I
did step 2 draw the light sprites to the
light surface with the local variable
light strength we'll set the brightness
of all lights at the same time in this
demo we'll just use a slider returning a
value from 0 to 1 now to determine where
to draw we need to consider that the
surface has its own coordinate system
ranging from 0 0 to 1 1 so we'll need to
get the views room coordinates using the
whiff statement will tell all children
of the parent light objects to draw
their sprites to the surface the objects
were set to be invisible so the
instances won't draw themselves and the
reason why I'm doing it this way is so I
only need to set the surface once and
change the blend mode twice for all
instances instead of for each instance
but there's of course other ways to do
this so we're drawing the instance of
sprites with all its attributes at its
XY position - the views position but we
multiply image alpha with light strength
since we're in blend mode and reusing
the Alpha just reduces to brightness of
the sprite that's why we're using light
strength will reduce the brightness of
the lights
there's a few things to mention here
though if you got many lights instances
and the room larger than the view make
sure only the lights that are in view
are drawn either by checking when
drawing or with some instance deactivate
activate system and if things like view
viewport application surface or the
light surface have different sizes you
maybe need to change the drawing scale
the variable light strength controls the
brightness of all lights at the same
time this is where you could change how
bright those lights should be depending
on in-game daytime or on other factors
instead of a slide like in this demo but
if you want to control the brightness of
each individual line there's two ways
since both the darkness of the image
blend color as well as the alpha value
determined the brightness of the result
for static brightness the easiest way is
to set a darker image blend : d room
editor and for dynamic changes the
easiest way is to change image alpha
since we're multiplying that with the
lights factor
then just the show that text can also be
used as light I added this demo section
here I used to draw text caller to pass
in the lights strength
and the last thing to do here is reset
the GPS texture filter and blend mode
and of course reset the target so this
created the light surface and that
surface will be sent to the shader as
second texture righty
now the fragment shader
in the header we need to declare the new
sample to delights but the rest of the
head estate the same
in the main function I change
named for the sample from the
application surface from outcall to base
coal I still kept alt collate in the
code that will need the original
colleague and further down
the caller calculations remain the same
so up to here bass collar is a sample
from the application surface and out
call is to call it with a day and bite
effect the overlay the saturation
contrast popping lights and brightness
now we need to mix in the light surface
so we need it's samples are to be
next we need to determine at the
brightness of that sample the antici
vector we used a few lines above and the
application surface sample won't give
good results the others are used in even
33% White's distribution
now we need to mix the out color with
the base color multiplied with the light
scholar by the mix amount of gray the
value of the light scholar and this will
look horribly wrong yet and I'm going to
show the fixes in a few steps but for
now let's just run this for the first
time and see what's wrong and why
instead of lighting the game it darkens
even if we increase the strength it
still darkens and if we set the game's
daytime to midnight we can see some
areas get brighter and some get darker
but the light surface looks correct the
reason is simple in the shader we
multiply the base call with the lights
call multiplication with less than one
always means the result gets darker and
when we mix this with the out call the
out call can actually be brighter than
our base call times light call
now my first thought was multiplying
lights call by something larger than one
this might look better at night but it's
still wrong and it's completely off at
noon
so I thought what about adding something
to lights call instead of multiplying
but this doesn't help either first of
all it looks wrong at the edges and
adding just moves everything to its
white and adding less than 0.5 wouldn't
solve the problem either so we need to
find another way
so I thought setting the lights vectors
magnitude by normalizing could fix that
problem but normalize it can reduce
brightness as well white becomes a gray
to compensate and multiply the
normalized vector by 3 but you can
experiment with other constants
now first glance this looks horrible but
if you look at the lighting you'll see
that part actually looks good so what
happened here
wide blacks and the noise the simple two
reasons the first is we can't normalize
black the color vector of black has
magnitude of zero there's no way of
normalizing that to a magnitude of one
this explains the large areas of black
the noise I think is because if we try
to normalize very dark colors we get
some precision problems and that causes
the noise but I'm not sure about that
however the fix to that problem was
adding something to the lights vector
before normalizing number has to be
large enough to get rid of the noise and
small enough to not squeeze the
saturation out of light plus 0.05 worked
nice for me on Windows and even on
Android without increasing the precision
now this looks good to me the light
colors look nice still and black areas
and the noise are gone the strength
slide changes the light strength when
drawn to the light surface
you
we can also change the sprites in this
demo
you
and especially with this right I like
the bluish green light in the lower
right corner
might just be one little detail that
bothers depending on your art style
black stays black and you might not want
that so I came up with a rather quick
and dirty solution if we add a small
amount of light call to the out call the
light surface will brighten up the out
call
now the darks aren't quite as dark
anymore but we lose some saturation and
some contrast personally I like both
styles just use this shader with or
without that line whatever you prefer
now to finish I'd like to repeat the
introduction but now by showing the
images and the code step 1 take the
sample from the application surface
where the game is on that's the base
quality
step to calculate the day-night cycle
collar without delights the out collar
step3 take a sample from the light
surface the lights :
step four multiply the base collet with
the normalized lights collar and the
lights factor
step 5 calculate the light scholar value
step 6
mix the out call it with the light and
base Kahler the mix amount is the value
of the light scholar
so the brighter the light sample is the
more of the base Kahler times the light
scholar will show and the darker the
light's value is the more of the out
color will show and this is a final
result so that's it for this video I
hope it helps you setting up a lighting
system in your game using Tuesday night
shade next time I hope to continue with
some distortions if you followed me on
Twitter recently you might have noticed
my experiments with that the last couple
of weeks there's still some stuff I'd
like to try before creating more videos
on that topic though so until next time
you