HomeVideos

Godot 4.5 Tutorial: VHS Camcorder Shader & Atmosphere (Backrooms Part 3)

Now Playing

Godot 4.5 Tutorial: VHS Camcorder Shader & Atmosphere (Backrooms Part 3)

Transcript

1113 segments

0:03

Right now, our game looks a little bit

0:05

scary, but it also looks too clean. It

0:08

looks like a 3D render. Now, to make it

0:10

feel real, we need to degrade it a bit.

0:13

We're going to shove this pristine 3D

0:14

world through a lens of the cheap 1990s

0:17

camcorder. Today, we're adding the VHS

0:20

effect. Welcome back to GDO Dev

0:23

Checkpoint. We have the maze and the

0:25

lighting. Today, we're going to focus on

0:26

post-processing. Think of it like

0:28

putting a filter over your camera lens.

0:31

We're going to add a camcorder UI

0:33

overlay and write a custom shader to

0:35

create that tape grain look. I'm

0:37

Spaghetti Syntax. Let's get building.

0:40

Before we mess with the video feed,

0:42

let's add the camcorder interface. We

0:44

need UI elements that stay stuck to the

0:47

screen no matter where we look. Now,

0:49

back in our project here, let's go to

0:50

the player scene here.

0:54

Turn on my highlighter. You can see

0:56

better.

0:58

Then we need to add a canvas layer node

1:01

as a player of the child. So we can

1:04

right click the child, add canvas layer

1:07

node, which is right there. Enter down

1:12

and rename it to camcorder UI. Camcorder

1:16

UI.

1:18

Now a canvas layer draws on top of a 3D

1:21

world like a sticker on your monitor.

1:23

You actually go to our 2D section here

1:25

and be able to see it better. The first

1:27

thing we'll do is add the record label.

1:30

Right click our camcorder UI. I'm going

1:32

to add a child node. It's going to be an

1:34

Hbox container.

1:37

Now, just organize things horizontally

1:39

for us. Create. And as a child of this

1:43

HBOX container, we're going to add child

1:45

node. We're going to use a label

1:49

right here.

1:51

We're going to name this to record

1:54

label.

1:57

And then with this record label

1:58

selected, we can rightclick, duplicate,

2:00

or press Ctrl D.

2:03

Perfect. Now we have two of them. Now in

2:05

the first record label, we're going to

2:07

use a dot. Now, not a period, but is a

2:11

dot with a space in front of it. Now I'm

2:14

going to include this down in the

2:15

description, so you can just copy it

2:17

from there. And then I'm going to paste

2:19

it into this text section. It looks just

2:23

Now, if you want to find it yourself,

2:25

you can actually find it in the

2:27

character map. If you go to your search

2:29

icon in your taskbar, if you're on

2:32

Windows, you can search for character

2:34

map. Just type in character map right

2:38

there.

2:41

Then

2:44

if you don't have advanced view up here,

2:48

you must go to Unicode,

2:51

search for Unicode 25 CF.

2:55

And that's the unic code for the dark

2:57

circle. Perfect. Now you can actually

3:00

select that, then copy it here.

3:05

Copy. And then you can paste it into

3:08

your window.

3:10

Since we already have it on there, I'm

3:11

gonna actually make a space here. V. And

3:15

now I have my dot. Great. Now I have

3:18

that. And we add the space in front of

3:19

it so it doesn't hug the wall too much.

3:22

And then on our second record label

3:24

here, we're going to add just the

3:25

letters rec.

3:28

Perfect. And for this record, we're

3:32

going to do here is we're going to go

3:35

down to theme overrides colors or change

3:40

the font color to red. I'll just go in

3:43

my linear, pull these all the way back.

3:46

And now I have it red. So the record

3:49

label should be red and the dot should

3:51

be white. Great. Now we're going to for

3:53

our camcorder UI, we're going to add

3:55

another child. With that selected, add

3:58

child node label.

4:02

I'm going to rename this one to time

4:04

stamp

4:06

label.

4:08

We're going to change the anchor to this

4:10

one to the bottom right.

4:13

That'll be down here. We get rid of this

4:16

output window.

4:18

And for this text we're going to use is

4:21

2701

4:23

1894.

4:25

And we're going to use the time of 10

4:29

32. Doesn't really matter what time you

4:32

use as long as we have the hour and the

4:36

minutes and the seconds. That's we're

4:39

going to access through script later.

4:42

Then we use an empty line here for

4:43

spacing on the bottom. We're going to

4:46

change our horizontal alignment to

4:48

right.

4:50

Then this little grabby thing here, I'm

4:52

going pull it over.

4:57

a little bit from the wall. It's not

4:59

hugging the wall so much

5:03

just as so it's not right on the the

5:05

line here. We kind of want it over a

5:07

little bit so it matches what it used to

5:08

look like on the camcorders.

5:11

All right. Now, we're going to go to our

5:15

assets folder. We're going to rightclick

5:17

and create a new folder.

5:20

We're going to call this fonts.

5:24

We need that old VHS fonts. Now, if you

5:28

downloaded it from my tutorial assets

5:31

Google Drive, you already have this

5:32

font. If you didn't do that and you want

5:34

to do it separately, it's this font here

5:37

on ddefont.com.

5:42

It's the VACR-OSD-mono.font.

5:46

And that's the one that the old

5:48

camcorders used to use. It is 100% free,

5:52

which is why I'm able to include it in

5:53

this assets pack that you can download.

5:56

But if you want to do it individually,

5:58

you can just download it from here. I'll

6:00

include all the links in the

6:01

description. And however way you decide

6:04

to get it, once you do have it, with the

6:06

font folder selected, after you get that

6:10

zip file extracted, we're going to drag

6:12

in the VCR OSD model font and import it.

6:17

There we go. You should have this folder

6:20

with the attribution text and the VCR

6:23

text. If you don't have the attribution,

6:24

that's the one I made in the Google

6:26

Drive folder. All it is saying is where

6:31

this font came from so it can be

6:34

properly credited. All right. All right.

6:36

And back in our time stamp label here,

6:39

what we can do

6:41

now that we have that, if we go to our

6:44

timestamp label,

6:46

we need to make a new label settings

6:48

here with a new label settings created.

6:51

Go into the resource and go into the

6:54

font. And in the font section, we're

6:56

going to drag and drop

6:59

our font that we have here.

7:02

And then we just need to go back up to

7:03

our record and our dot

7:07

and then do the same label settings.

7:10

Open label settings font. Drag and drop

7:13

the thought into there. And same with

7:16

the record label.

7:18

Scroll back up to label settings. Label

7:21

settings. Open that up. Font and the

7:25

VCR. Drop it in. Perfect. Nope. We

7:29

changed our record back to white. So we

7:32

change our color here now and pull these

7:36

down back to red. Perfect.

7:40

And we also want to make these bigger.

7:43

So with I'm going highlight all three of

7:46

these. I'm going to change the label

7:49

settings

7:52

of the font to 50.

7:54

That's only going to do the one. So

7:56

we'll do the record label. Change that

7:58

to 50 individually.

8:01

Then the time stamp label also 50.

8:05

Great. Now those are very legible just

8:07

like it would be on a old school camera

8:09

recorder.

8:11

So now we have our timestamp label here.

8:14

A static picture of a clock is not going

8:16

to cut it. If the player survives for 20

8:19

minutes, the clock needs to read 20

8:21

minutes later. And if they play through

8:23

midnight, well, we need this date to

8:26

change.

8:27

Now, we need to add a script to it. A

8:30

script that took me back to my college

8:33

days of writing scripts. We just need a

8:36

timer. Basically, a date time clock. So,

8:41

with our timestamp label node selected,

8:44

we're going to rightclick and we're

8:46

going to add a script. Not in the seeds

8:49

folder. We want to put it in a scripts

8:51

folder. Back up to our root scripts.

8:55

Next to the player JD GD script, we're

8:58

going to rename it to not timestamp

9:00

label. We're just going to rename it to

9:03

timestamp.gd.

9:07

Open and create.

9:11

All right. Now that open, go and save

9:13

the scene real quick and make this

9:15

bigger.

9:17

Now, as Habit says, I'm going to get rid

9:19

of this boilerplate code and start from

9:21

scratch.

9:22

with our extends label here. The first

9:24

thing we need is the start date settings

9:29

so they can be editable in the

9:31

inspector. So we want them editable in

9:34

inspector

9:37

and we need everything from the year,

9:39

month, day, hour, minute, and second. If

9:41

we want to change them, we need to have

9:43

access to them. So with the export var

9:46

year is going to be not year is going to

9:49

be an int and default we'll do just the

9:53

1994.

9:56

Oh let's actually change the year

9:59

rolling over. We'll do an 89 and then we

10:03

can do the export bar. Month is also

10:07

going to be an int. It's going to be the

10:09

12th month. Then at export var day it's

10:14

going to be another int and it'll be the

10:17

31st. So New Year's Eve at export var

10:22

hour our

10:24

he uses military time so it's easier

10:28

that way. We'll do var int is going to

10:31

be 23. said it's 11 p.m. So then export

10:36

var minute is going to be another int

10:40

that's going to be 59. So right before

10:44

it turns over to midnight. This way we

10:45

can change the month. We can test the

10:47

month and the year rollover.

10:50

So at export

10:53

bar for the uh second there's also going

10:57

to be an int. And we're going to have it

10:59

at 55 seconds. We have to wait five

11:02

seconds to be able to see if the

11:03

rollovers are working properly.

11:06

Then we also need a timer in the script

11:09

as well. So it's going to be our

11:10

internal timer

11:12

and our time is going to be it's going

11:15

to be bar time accumulator.

11:19

So that way we can

11:22

properly judge how long it's been. We'll

11:25

set that float to 0 0. And then we need

11:28

to actually check the days in the each

11:31

month because each month has a different

11:33

set of days. So how we do that days in

11:36

each month? Well, the first we're going

11:38

to do by index. So the index zero is

11:40

going to be January.

11:42

So you're going to be an array here.

11:45

And then we're just going to make an

11:47

array with days in months.

11:51

And then the array is going to contain

11:52

each month's day. So zero is January and

11:56

there's 31 days in January. February has

11:59

28. March 31st or 31 and then 30 days in

12:06

April and then we have May which is 31st

12:11

or 31. June is 30, July 31, August 31,

12:17

September 30. And then we have October

12:21

which is 31 but Halloween and November

12:24

is 30 and then December is 31. So these

12:27

are all 12 months in a row.

12:31

Now that we have those, we have our time

12:34

and we have our timer in the

12:38

script. So we could track the seconds

12:41

and then we have the days in each month

12:42

that's going to be appropriate.

12:44

We need to have a ready function. The

12:46

ready function is going to track

12:49

things like if you put your own in dates

12:52

in here because you can we'll be able to

12:53

actually do our dates in the inspector.

12:56

It's going to make sure the date you

12:58

entered is valid because we can't have

13:00

the user putting in a date that's not

13:02

valid. You could make it so you can't

13:06

edit this in the script. But even then,

13:08

if we want to if we edit it in the

13:11

script only, we still need to make sure

13:12

these dates are actually dates. If

13:15

they're not, it can break things like

13:17

our days in the month. So it's like a

13:20

safety check. So in the ready right in

13:24

the beginning, we need to do the safety

13:25

check

13:27

to verify the inspector input

13:32

before starting or even the script

13:34

input.

13:36

And we need to check if not

13:40

we're going to do a a function that

13:42

we're going to write in a second.

13:44

Is input valid?

13:48

Okay. Now after we have that we can go

13:51

into our if statement here. We need to

13:53

check for if this input is not valid

13:57

after we write that function. Well if

13:59

it's not then we need to throw an error.

14:01

So we use a thing called a push error.

14:03

Now, it's basically a custom error that

14:05

GDScript can use to push errors, custom

14:09

errors to the debugger console. Helps

14:11

track where the error comes from. So,

14:13

the error we're going to throw is called

14:15

invalid. We're going to have it say

14:17

invalid date entered.

14:19

It's going to show what the actual

14:23

date was that was entered. So, colon and

14:25

then quotation and concatenate to a

14:29

string. We're going to do the day and

14:32

then we're going to plus

14:35

there

14:37

I'm going to separate the day with the

14:39

month. So we're also going to use the

14:41

month and contain that string month.

14:44

Then this gets pretty long. So we can do

14:46

here is do the backspace

14:50

end for a new line. Enter down.

14:54

And then

14:57

we can enter over. And then what we need

14:59

now is the other string there. And we're

15:04

concatenate with that.

15:06

And we need a plus sign here.

15:09

Plus

15:12

there.

15:18

Great. Oh. Oh, it's just the backspace.

15:21

Sorry, not the backspace. N

15:24

the back slash. There we go.

15:27

Then after that we have the day month

15:29

and we need the year. So we'll do the

15:31

string. Turn the year into a string.

15:34

There we go. Now we have the date

15:36

entered string day string month. Then

15:40

the backslash no end. That's only within

15:43

use the backslash n like this inside of

15:46

a string here. But we don't use that

15:48

outside of the string. We just use the

15:50

backslash.

15:51

Great. But now that we know that we have

15:53

an invalid date, well, we need to set it

15:55

to a valid date. So our normal print

15:59

statement, we can say resetting

16:03

the clock.

16:05

Resetting clock

16:08

resetting clock to default. I like that.

16:11

Which is going to be December

16:15

December 31st,

16:18

1989.

16:22

But then we need to tell the year and

16:23

the date and the minute and the second

16:24

all that what that actually is. So our

16:27

default values are going to be default

16:29

back to safe values.

16:34

Okay. And we do that by saying the year

16:38

1989

16:40

and then the month is the one or not the

16:43

one 12 and then the day is 31

16:48

and then the hour is zero. No not zero

16:51

23

16:54

and the minute is going to be the 59. We

16:57

spell it right.

17:00

Then the second

17:02

55.

17:05

Then we're going to write this input

17:07

valid function.

17:09

We're also going to write after we've

17:11

checked that the date is correct. We

17:14

don't have to go into there. We're going

17:16

to if the date is correct, well, we're

17:18

just going to go straight into this new

17:21

label function that we're going to write

17:22

called update label.

17:26

Just like that. Now, let's write these

17:28

two functions. Now, we go out of the

17:30

ready function. Just enter down a couple

17:31

times. backspace to the wall.

17:35

Now, the first one, the update label

17:38

here, we're going to do some string

17:40

formatting.

17:43

We've never done that. I'll explain in a

17:45

second. So, you want to format

17:48

the label of the time stamp. It's going

17:50

to be day, month, year. So, two digits

17:54

for the day, two for the month, four for

17:57

the year.

17:59

And then after we have that, well, we

18:00

need the new line, which is going to be

18:02

the backspace n. And it's going to be

18:04

the hour, minutes, and seconds. So two,

18:09

two, and two. So how do we do that?

18:11

We're going to take the text.

18:14

The text is going to be the

18:16

is going to be the timestamp label text.

18:19

We only have to say text because it is

18:21

attached or should be attached attached.

18:24

Make this smaller to your timestamp

18:26

label. So we can just use text. Then

18:30

it'll access the inspector text right

18:33

here. I'll make this bigger again. And

18:37

since we're accessing the text here

18:40

directly

18:42

and equal that to a string format that

18:45

lets us change it dynamically. So with

18:47

the quotation marks we use a my modulo

18:49

which is also a percentage

18:52

sign we call modulo in programming. Now,

18:55

these act as placeholders for where we

18:57

want to dynamically put in strings. Like

19:01

for this one, this front one's going to

19:02

be the date here. That's where this

19:04

placeholder is going to be. And then

19:06

we're going to put in a zero to D. Now,

19:11

the D on the end acts as an integer. So,

19:14

it's going to be an integer placement.

19:16

And the zero means there should be zero

19:18

padding. There's fewer digits than the

19:20

specified width, which is two. because

19:23

the two sets the minimum field width to

19:26

two characters that keep it nice and

19:29

tidy. So we're going do that exact same

19:31

thing for the year or not the year, the

19:32

month. So we're just going to space over

19:35

do another modulo

19:38

right here and 0 2D. So that'll be our

19:41

month. And then for the year it's going

19:43

to be four digits. So we're just going

19:44

to use the placeholder modulo and then

19:47

the D. So we know it's integer but we're

19:49

not going to limit it to two.

19:52

And we don't have to limit it this way

19:53

at all. It'll just be four. And then we

19:56

need to do the new line. So it's a

19:58

backspace N. So that'll create a new

20:00

line. So it'll be down. If you remember

20:03

here, I'll make this smaller in our 2D.

20:07

We're going to do a new line right here.

20:09

And then it's going to be the time.

20:11

That's what we're going for. That's the

20:12

look visually. And we'll go back to the

20:15

script. Make this bigger.

20:18

Now that we have our date, we're going

20:20

to use our time. So after our new line,

20:23

we're going to do is well the same thing

20:25

all across the modulo zero 2d because

20:29

there's going to be two digits integers

20:32

all the way across. We need to make sure

20:34

they add these colons in here. So it' be

20:36

colon then modulo 0 to d. Great. Then

20:41

another colon modulo 0 tod. Great.

20:47

Then we need to add the modulo on the

20:48

end here. It's going to say, "Hey,

20:52

what are these things you want to put in

20:54

there?" And then this little bracket box

20:57

here like an array. Well, these this

20:59

first one here is going to be the day,

21:03

not the dar, the day. And the second one

21:05

is going to be the month. Third one is

21:08

going to be the year.

21:10

Then we can actually backspace down.

21:14

Then I'll enter. I'll bring it over and

21:17

then we can do the so it looks just like

21:20

it will on the screen is the hour, the

21:23

minute and the seconds

21:27

and a second.

21:29

No, I forgot my comma right there. There

21:32

we go. So, day, month here, hour,

21:34

minute, second. So, this day is going to

21:36

go into this section.

21:38

Month there, year there, hour, minute,

21:43

so on and so forth.

21:45

Great. Now that we have the update label

21:47

set up, let's do the make sure the input

21:49

is valid. So, we'll enter down a couple

21:52

times out of this one. Go back to the

21:54

wall. There we go. The function is going

21:56

to be called is input valid.

21:59

Make sure spelled just like we did up

22:01

here. And then we're going to go into

22:03

this one. Was it going to be a return?

22:06

Because this is checking yes or no. Is

22:09

this valid or is it not? So, it's a

22:10

bool. So it's going to be a arrow over.

22:14

So a dash and then the angle bracket

22:18

forward

22:19

enter bool. Okay, this is going to say

22:23

we need to return a bool. The first

22:26

thing we do, we'll just do return

22:30

uh true. There we go. That'll throw get

22:33

rid of all the errors. Now you know

22:35

we're on the right path.

22:38

But first go and save that. First thing

22:41

we need to do is check for simple

22:43

ranges. Check simple ranges.

22:46

So we need to check if the month is less

22:49

than one

22:51

or the month is greater than 12. Well,

22:54

we know that the months are wrong. So we

22:57

need to return false. So return false

23:00

right there. Now you can do it on a

23:02

single line like this or you can enter

23:04

down and make it like a normal statement

23:07

here. Since we're going to check some

23:08

pretty small stuff individually, we can

23:11

do is just keep it on the same line and

23:13

the syntax will read just the same.

23:16

It'll be a little bit cleaner. The next

23:18

thing we do is if the hour

23:22

is less than zero, well, that's wrong.

23:24

Or the hour is greater than 23. Well,

23:28

that's also wrong. So, military time 23

23:31

is the 11 p.m. Zero is the 12 a.m. So

23:35

then if that's not this or that, return

23:37

false.

23:39

And we're just doing some safety checks

23:41

is all these are. So just take your

23:43

minutes and then we need to know if

23:44

that's less than zero or the minute is

23:46

greater than 59.

23:49

This is also false.

23:52

Return false.

23:54

And then you want to check the

23:58

second. Yeah, we got hour, we got month,

24:01

hour, minute, second, month, hour,

24:03

minute, second. So if second is less

24:05

than zero or the second is greater than

24:09

59,

24:11

return false. So those are the easy

24:14

ones. Now the harder ones is check for

24:18

specific days

24:20

in a month. So we're going to check

24:24

for specific

24:26

days in a month or in any month. So the

24:31

var store variable for the max days it

24:34

can be is the days in the month

24:40

of the current not days and months days

24:42

and months width. There we go. This is

24:44

an array. We need to check which month

24:47

it is. So we're going to take the month

24:50

and then minus one because remember our

24:53

months are 1 through 12 but in the index

24:57

and array it'll be 0 through 11. So the

25:00

current month is actually the month

25:02

minus one because if it's month here

25:05

it's going to be month 10, right? But

25:09

it's going to be index 9 in the array.

25:13

And next we check well is it a leap

25:16

year? Now leap years are the ones every

25:19

four years which makes the days change

25:21

to make it even more complicated but

25:24

it's pretty straightforward. So var is

25:26

leap. So if it is a leap year well we

25:29

need to do the year. So whatever year it

25:32

is and we use the modulo operator which

25:34

is four because every four years is that

25:38

equal to zero.

25:40

And this is a standard formula for

25:42

finding a leap year. You can really find

25:44

this formula anywhere. So the way you do

25:46

that is check the year and then we're

25:48

going to do the modulo again get the

25:49

remainder divided by 100 then does not

25:53

equal zero.

25:55

So we know it's not a leap year with

25:57

that formula. The other one we use is or

26:00

the year

26:02

the modulo 400

26:05

there's no remainder equal to zero. So

26:08

it's saying there's no remainder on any

26:10

of those equations. So these are return

26:12

the true or false either or. So how do

26:16

we check for that? Well, we're just

26:17

going to do an if statement. So if the

26:19

month and the affected day affected

26:23

month is February for leap year.

26:26

So there's 28 days of normal ones and 29

26:29

on leap years. So if the month is

26:31

February, so it would be two.

26:34

And this leap we got from this formula

26:38

to check for a leap here

26:41

is leap. So I'll check if is leap is

26:43

true. Well, we need to change the max

26:46

days of the current month which is two

26:50

to 29 instead of 28. So just checking if

26:54

it's February

26:57

change the mac days max days to 29 but

27:00

only if it's a leap year. And next we

27:03

need to check again if we did change the

27:05

max days we're going to include that in

27:07

our day check. So if the day is less

27:11

than one like we did up here with the

27:14

hours and the months and now we're

27:15

checking for the day the day is less

27:17

than one or the day is greater than the

27:20

max days.

27:22

And now we have max days. Now if it's a

27:24

leap year change February to 29. So this

27:28

way if you just check the month here you

27:31

don't change the the days and remember

27:33

up here our 28 is the all the days we

27:36

put into February because 90% of the

27:39

time it will be 28 but the other 10% is

27:43

going to be a leap year. So to account

27:46

for that so we can use whatever date you

27:48

want. If the day is greater than max

27:51

days well that's also false. So we need

27:54

to return false.

27:57

Great. Now we have accounted for months

27:59

being wrong, hours being wrong, minutes,

28:01

seconds, then we accounted for leap

28:03

years in our days. Now the last thing we

28:05

need to check for is the year. And

28:08

actually, let's put the year on top. If

28:11

that's wrong, well, they're all wrong,

28:13

right? So if year is less than let's

28:18

just you can put it whatever you want

28:19

but we'll just do 1900 to make like a

28:23

camcorder goes into 1900s or wherever

28:27

you want to put it we can also then we

28:29

want to do the future too right so we'll

28:32

just do greater than 2100 for now so if

28:35

it is then we'll return false

28:38

great count for the year month second

28:41

days and a leap year the month is we'll

28:44

change the days. The month is a leap

28:46

year, we'll change the days. If it's the

28:49

days less than or greater than the max

28:51

days, return false. So, this should

28:53

account for everything.

28:56

Great. Now that we have all that, what

28:58

we can do here is need to

29:02

now that we're updating and we're

29:03

checking if it's valid. Well, we need to

29:05

make this time move. We do that in the

29:09

process function. down a couple times

29:13

underneath the ready and a couple above

29:15

the update label. We're going to use a

29:17

function process

29:19

and also run on the delta

29:24

which will

29:26

help us keep track of the time. We go

29:29

into that. We're use our time

29:30

accumulator

29:32

and we're going to use that to plus

29:33

equal delta. So that's going to keep

29:35

track of our seconds based on our frame

29:38

rate. So we do that for what this means

29:42

is every 1 second

29:45

every real time second we'll do that

29:47

every one real time second I'm going to

29:50

tick the clock

29:52

so if time accumulator

29:56

time accumulator there is

30:01

greater than one

30:04

greater than equal to one we know it's

30:06

been a second so our time accumulator

30:10

is going to go back down to zero by

30:14

minus to one there. There we go. That

30:17

way we know it's been a second. Then

30:18

we're going to reset it back to another

30:19

second. We're going to do call the

30:22

function. We're going to call this one

30:24

tick second. So now we know that it's

30:27

been a second. So we need to write a

30:28

function called ticksec. So once it's

30:31

been a second, we're going to enter down

30:32

a couple times and write this function

30:34

called tick second. Okay. Going to go

30:38

into that and say second plus one plus

30:43

equals one. So we're going to up our our

30:45

second label.

30:48

So then we handle the rollovers between

30:51

all of our seconds and our minutes and

30:54

our hours. So first one we're going to

30:56

do is handle time rollovers.

31:00

So when the time gets to where it needs

31:03

to be changed, first one is the second

31:05

of course. So the second is greater than

31:07

or equal to 60.

31:10

Well then we need to make the second

31:12

back to zero.

31:15

Then we need to actually after the

31:17

second is at 60 of them we need to up

31:20

the minute by one.

31:24

So then we need to check our minutes. If

31:26

the minute is greater than equal to how

31:29

many minutes in an hour? 60. Well we

31:32

need to set that back to zero. And then

31:35

we change the hour by one. There's that.

31:39

So then we check our hours. If the hour

31:42

hours in a day is 24, so if it's greater

31:45

than equal to 24, well that's going to

31:48

be zero. So back to the hour zero. So

31:52

that would be midnight. And then we need

31:54

to write a function after this to

31:57

actually take over the whole day. It's

31:59

going to be called tick day. Perfect.

32:04

Okay. And then we go into

32:06

Well, after we do that,

32:10

before we go into tick day, let's update

32:11

the label.

32:14

Perfect.

32:16

That'll update the label after we call

32:18

the tick day function. But then this

32:20

text tick second is complete.

32:24

So we'll go to the tick day function.

32:26

Now enter down a couple times. Backspace

32:28

to the wall. Then we're going to write a

32:31

function called tick the whole day.

32:34

Perfect. So our day go into there. Oh,

32:38

helps by a space right there. Then colon

32:42

enter down our day by one.

32:47

So the day also has to check for leap

32:51

years. So we need to check for the leap

32:53

year the day too.

32:55

So, and to make it more specific, every

32:58

four years. So, we write this down

33:01

unless

33:03

divided by 100 but not 400.

33:09

So, that's the equation for the leap

33:11

years. So, if you divide it by 100, it's

33:14

every four years. But if it's divisible

33:16

by 400, it's not. And once again, you

33:19

can find this equation anywhere really.

33:21

So we actually take our

33:25

function down here or our equation down

33:26

here. We can take that and we're just

33:28

going to use that again. Copy it. Crl +

33:31

C and we're going to paste it right

33:33

there because we need that again. And

33:36

then after that we need to have the

33:39

we're actually going to take the max

33:41

days as well. The max days we'll take

33:44

that line there. We can copy that and

33:48

then paste that because remember we also

33:50

need make sure the month one once again

33:54

just to specify the month is a onebased

33:57

index

33:58

one based index which means

34:02

this is 13 minus one or this be 12 - 1

34:06

11 is actually December in the index

34:09

because it starts at zero. Great. And

34:12

then after these two, we're actually

34:14

checking the same thing. If the month is

34:16

equal to February, so two and is leap

34:21

well, we're going to change the max days

34:23

to 29,

34:25

just like we did in the

34:28

is input valid function right here.

34:32

So when you're polishing or refactoring,

34:34

you can actually make this its own

34:36

separate function, but for now, we'll

34:38

just keep it in these separate ones

34:40

here. And after that we can check the

34:44

day. So if the day is greater than max

34:46

days,

34:48

well we want to make the day equal back

34:50

to one because we've rolled over the

34:52

whole month. Then after we do that, we

34:54

need to check make sure the month is

34:57

actually over by one. So if it's

35:00

February 28th or February 29th on a leap

35:04

year and the day goes up by one

35:08

and it's over the max days, then we're

35:11

going to change the month into the next

35:13

month. Hopefully that makes sense. Then

35:16

we check the month after we increment

35:18

the month to make sure it's not the 13th

35:21

month of the year because if it is, we

35:23

need to go back to January. So the month

35:25

is greater than 12 and the month back to

35:29

one, which is January. And then we're

35:31

going to change the year.

35:34

So the year is going to go up by one.

35:38

Perfect. There we go. And save that. Now

35:40

after all that,

35:43

we go back to our make this smaller. Go

35:46

back to our timestamp label. And we have

35:48

all these dates and months. Now we have,

35:51

if I go back to the world

35:54

in our 3D section here,

35:58

we're going to save it. If I play now

36:02

here, I can see our time stamp on the

36:05

bottom right. It's ticking up. And there

36:09

we go. Rolled over to midnight. Change

36:11

the date and the year. And that's all

36:14

this. And we're ticking up now. We

36:17

should probably bring this up a little

36:19

bit, but I'll leave it for now because

36:21

we're about to add that VHS shader,

36:24

which is going to change our viewport

36:26

settings.

36:29

And exit that. Then we can do a little

36:31

test here. If I go into

36:34

our timestamp label, let's check our

36:36

verification. I'll put an extra digit

36:39

here and make this the 13th. Well, this

36:43

won't even run because the it's going to

36:45

check the year first. So, if I added an

36:48

extra digit there and save it.

36:52

We can do here.

36:56

So, I just notice on this timestamp

36:57

label.

37:00

There we go. We do here is go into

37:02

script. I'm going to go down to make

37:05

this bigger.

37:08

And after our string formatting

37:13

here,

37:15

I'm going to add another new line there.

37:18

That way it puts that new line on the

37:20

bottom. And save that.

37:22

Enter there. And go back to my world

37:26

3D. Go and run the current scene.

37:31

And now we have our space down here.

37:35

There we go.

37:37

And we see our debugger flashed. Going

37:40

to exit that. And then we have our

37:43

custom

37:45

error. I entered a one on the end of

37:48

1989,

37:49

which means it's an invalid date.

37:53

Perfect. So, our check is working. Turn

37:56

that back to default. We have a space

37:59

here. We have this record here.

38:02

and the error console will yell at us

38:04

and reset the timeline to where it's

38:06

supposed to be. Now, before we add that

38:08

VHS shader, let's make our lights glow a

38:12

bit. Old cameras tend to blow out the

38:14

bright lights a little more than the

38:15

newer ones. So, let's turn on some glow

38:17

in our world environment and then kind

38:20

of replicate that look. So, back here in

38:22

our world scene here, we're going to go

38:25

up to our world environment.

38:28

down to the in our world environment

38:31

resource.

38:33

I'm going to minimize this stuff here.

38:35

I'm going to go down to glow. I'm going

38:37

turn that on. I'm going keep the

38:39

intensity at 0.8.

38:42

I'm going turn the bloom to 0.2.

38:45

Make it blow up a little bit. And to

38:48

accentuate that glow a little more, I'm

38:51

going do some volutric fog. Turn that

38:54

on. I'm going set this to 0.03. 03. So

38:58

you still see pretty far and it's not so

39:00

crazy. I'm going change the albido to

39:03

the same bright yellow as we have here

39:05

as the lights. And then the hex code for

39:09

that is FF E B0.

39:15

Well, that didn't take. Let's try that

39:16

again. FF E

39:19

B 0. There we go. Click. Press enter on

39:23

that. There we go. That's a slight

39:25

yellow. Perfect. Then I want to change

39:28

the emission to the same as this. I

39:30

actually copy that. Click on my

39:33

emission. Instead of black, we want that

39:36

yellow haze.

39:38

I want turn energy quite a bit. 0.5.

39:42

So it's not so crazy, but it gives that

39:44

eerie kind of smoky

39:47

long distance haze. Great. Now, that'll

39:51

give us some spooky

39:54

cinema, especially when we add that

39:56

shader.

39:57

Let's go and test that scene.

40:00

There's that. Now, we kind of have this

40:02

spooky fog. Give it more of an eerie

40:05

feel and these glowing lights. All

40:08

right,

40:11

you made it to the post-processing

40:13

setup. Now, we're about to add the VHS

40:16

shader. Post-processing in GDAU is done

40:18

by putting a flat rectangle over the

40:21

entire screen and applying material to

40:23

it. Now, we need a node that covers the

40:26

whole screen and it needs to sit on a

40:29

layer above the 3D world, but not below

40:32

our UI. So, back in our player scene

40:34

here,

40:36

we need a new canvas layer. So, we're

40:38

click on our player scene here, add

40:40

child node, canvas layer right there.

40:46

Double click. There we go. Once it's in

40:49

there, we're going to rename it to

40:50

postprocessing

40:53

layer.

40:54

And we need to add a color rect. So,

40:57

right click, add child to color rect.

41:00

Right there. I'm going to rename this to

41:03

VHS shader.

41:06

Just like that. And for this, we need to

41:10

take the anchors and apply it to the

41:12

whole screen. So, full wctck.

41:15

Now it should turn white and cover the

41:17

entire thing.

41:19

Then we need to take our camcorder UI.

41:23

What we're going to do is we're going to

41:24

drag it down and make it a child of the

41:28

VHS shader we just made. Just like that.

41:33

So right now we're looking at a white

41:35

rectangle. We need to tell GDAU to

41:37

render the 3D game onto this triangle

41:40

and then distort it. First thing we want

41:43

to make sure is that this doesn't

41:44

actually block our mouse inputs. So on

41:47

the VHS shader, we're going to go to

41:50

mouse here and make sure the filter here

41:55

says ignore. There we go. Go to save

41:59

that. If you don't do this, you won't be

42:01

able to click through like on our

42:03

interactions

42:04

or look around.

42:07

All right. After that, I'm going to go

42:08

to the file system here in my resources

42:12

folder

42:14

and we're going to right click in our

42:15

resources folder or on it and create new

42:18

and we're go to resource.

42:21

Then we're going to look for shader

42:23

which is right here. Once you have that

42:25

selected and create it and we're going

42:28

to create a new shader we're going to

42:30

call VHS shader.

42:34

There we go. and create it in the

42:37

resources folder. And now we have it

42:39

right here. Now for this shader, we're

42:42

not going to reinvent the wheel here.

42:44

You double click and open. It has a some

42:46

default code here. Click on this to up

42:48

it. There we go. But shaders include

42:51

lots of math and those kind of things.

42:54

They're really hard to kind of go over

42:55

line by line. And to be frank, there's

42:59

so many people that have done gorgeous

43:02

shaders. are so much better than I will

43:04

ever be at it. I've only written maybe

43:05

one or two by myself and you can't

43:08

really be good at everything and you

43:10

shouldn't be. Use the tools like this

43:12

open- source GDAU engine for example to

43:15

your advantage. So where I found the one

43:18

I'm using was on a website or is on a

43:20

website that has tons of shaders

43:23

available for GDO gdosshaders.com.

43:27

super resourceful stuff for here. This

43:31

old school VHS CRT monitor effect is the

43:33

one I went for. Now, unfortunately, this

43:36

is an older one. So, this is for GDAU 3.

43:39

So, this will actually not work. So, we

43:42

also found or I also found someone who

43:45

updated this exact VHS CRT minor effect

43:49

for GDO4 and they were nice enough to

43:52

actually change the variables and stuff

43:55

to work in GDO4.

43:58

Did not include the

44:00

the comments though. And I love having

44:03

the comments because as much as looking

44:06

through this and you'll probably be able

44:08

to figure it out, not having the

44:10

comments makes it a lot more mysterious.

44:13

So I took this code and these are all

44:16

you got to make sure

44:18

that the person who wrote it doesn't

44:21

mind if you use it for anything.

44:24

And this this original shader here, if

44:26

you look at the top,

44:30

put it under the CCO license. So you

44:32

feel free to use improve and change this

44:34

according to your needs which is what

44:36

we're going to do and that's perfect and

44:39

I appreciate the one who put it in GDO4

44:42

which is great. So we took this and I

44:44

put it on my GitHub and added the

44:47

comments and I also added the

44:52

inspector numbers we're going to use to

44:54

make it look like I had in the intro

44:57

video of the first video. So, in the co

45:00

in the description below, I'll have the

45:01

link to the VHS cam shader we're using

45:04

for this tutorial. And then you can also

45:08

check out gdosshaders.com and look at

45:10

all the other shaders they have because

45:11

they have tons. But you might have to

45:14

update a few because there's a lot for

45:15

GDAU 3. But once you you get to go to

45:19

this GitHub and you can actually copy

45:20

it. You go to the raw section here and

45:23

then you can actually just copy it.

45:25

Control A, copy. or you can actually

45:28

just

45:29

copy the RAW file right here. So once

45:32

you have it, we'll go into which I'll do

45:34

here. I'll copy RAW file and I'm going

45:36

to go into back into our project. And

45:39

with the VHS shader selected and we have

45:43

the window open here. I'm going A and

45:45

paste all of that in here. So now we

45:48

have the entire VHS shader imported with

45:51

the inspector

45:54

values we're going to use and all the

45:56

comments and the links to where it got

45:58

from. I'm going to save that. Crl S. I'm

46:01

going to make this smaller.

46:04

Then with the VHS shader selected,

46:07

I'm going to scroll down to

46:10

material

46:12

right here and the canvas item material.

46:15

This material is empty. I'm going to

46:17

drag this shader into this material

46:21

section and drop it. Now I'll close this

46:26

shader editor. Now we don't need it.

46:28

You'll see the default is just like a

46:31

TV. Now we do not want that. It's going

46:33

to be hard to play through. That's where

46:35

the shader settings come in. So the

46:38

material shader material open that up.

46:41

And we have a shader parameters here.

46:44

They have all these settings. Now, the

46:46

resolution we're going to use is like a

46:49

square resolution. The ones I thought

46:52

looked the best for now is 1024

46:56

by 768.

46:58

That's the one I decided there. That's

47:00

gives you that kind of square CRT look.

47:02

Anyway, but we also need to change this

47:05

resolution to match our project

47:06

settings. So, if we go to our project,

47:09

project project settings, and then our

47:12

window, we need to change this to match.

47:15

So 1024 by 768.

47:19

There we go.

47:22

Now we have that and close that.

47:25

You'll see the viewport matches here.

47:27

But GDAU can get kind of finicky and it

47:30

needs to actually reload the scene here.

47:32

So if you click

47:34

control S is for saving and save it.

47:38

Click back to the world scene and just

47:41

change our viewport. go back to the

47:42

player scene and then it'll match the

47:45

new settings we just put in. All right.

47:47

And the other settings we want to do,

47:49

I'm going to change the roll speed, I'm

47:50

going to change it to three.

47:53

And then the roll size, I put that at

47:56

seven.

47:57

And then the distort intensity, put that

48:01

at 0.01.

48:04

I scroll down to the disc color, I'm

48:06

going to turn that off. Then the warp

48:08

amount, I'm going to turn that to zero.

48:12

Don't want any of that warp. Then the

48:14

vignet intensity. I'm going turn that to

48:17

0.5.

48:19

Darken the edges a little bit. Oh, we

48:22

also need to add the overlay to on. I'll

48:25

add that to the GitHub a little later.

48:27

And that puts our

48:30

words where it should be. Oh, the other

48:32

one I missed was the aberration.

48:34

We don't want those words

48:37

so far over like that. We're going to

48:39

change it to 0.01.

48:41

We still have a little bit of that

48:43

coloration, but not such an extreme.

48:47

Now, all these are adjustable to however

48:49

you want. That's what I decided for this

48:52

tutorial. And if we go back to our Let

48:55

me save that. Go back to our world here.

48:58

And we're going to try the play.

49:02

Look at that. Instant nostalgia.

49:05

In the inspector under shader

49:07

parameters, you can tweak the scan line

49:09

count, grain, and the color bleed until

49:12

it feels right to you. Now, the

49:14

difference really is night and day. It's

49:17

no longer a geometry test. It's a piece

49:20

of found footage. The bright lights

49:22

combined with the dirty lens create a

49:24

perfect uncomfortable atmosphere.

49:28

Now, if you're following along, take a

49:29

screenshot of what you ended up looking

49:31

like and tag me on Blue Sky. I want to

49:34

see your level layouts and your cameras.

49:37

Now, we have the look, we have the

49:38

movement. Now, in the next video, we're

49:40

going to add some interactions. We'll

49:42

implement a raycast system so the player

49:44

can open doors and collect items. Now,

49:47

if you found this helpful at all or fun,

49:49

leave a comment on what your GDO game

49:51

dev goals are. Please like, subscribe,

49:54

and hit that notification bell. It

49:55

really helps out the channel. And thank

49:57

you to all our current and past Patreon

49:59

and coffee members. Your generous

50:01

support keeps the channel moving. Now,

50:03

if you want early access to tutorials,

50:05

source code, or suggesting future

50:07

tutorials, please consider becoming a

50:09

member yourself. The links are in the

50:11

description. I'm Spaghetti Syntax, and

50:14

remember, always stay curious, and I'll

50:17

see you at the next checkpoint.

Interactive Summary

The video tutorial details how to implement a retro VHS camcorder effect in a Godot game to make it feel more authentic. It covers creating a UI overlay with a record indicator and a dynamically updating timestamp, which includes script-based date and time rollovers and input validation. The tutorial also shows how to enhance the environment with glow and volumetric fog for a spooky atmosphere. The core VHS effect is achieved by applying a custom Godot 4 compatible shader to a full-screen ColorRect, with adjustments to resolution and various parameters like roll speed, distortion, and vignette, to transform the game's visual style into a 'found footage' aesthetic.

Suggested questions

5 ready-made prompts