Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
crisis averted yes the crisis has
been averted
hna you the crisis actually has not been
averted unfortunately the reason that
the stream is starting late today is
because well we're having a little bit
of a problem I wanted to get rid of my
taskbar I was talking about this on the
last on the last stream and I thought I
had seen some people say that you could
finally get rid of the taskbar again
used to be able to the taskbar on
Windows XP and of course when they
introduced their improvements to Windows
with Vista and 7 where they improved
everything they improved it so that it
no longer works so you can't actually
hide the taskbar it anymore basically
you only have this thing that basically
it always pops up if you go back up to
the edge of the screen and it's awful
and so you used to be able there was a
thing in here that said taskbar is
always on top or whatever and you could
uncheck that and that was awesome it was
like totally perfect and did exactly
what you want because then all of your
fullscreen windows would just be over it
which is what I wanted but I don't know
what to say so basically I was trying to
get rid of that I was looking on the web
for some of these things basically and
ya couldn't find it there's there's like
some tools you could course they got rid
of it so thoroughly that you have to
taskbar always on top Windows 7 and like
I was trying to find people who were
talking about this sort of thing and
there's like utilities you can install
where I tried installing one of them but
didn't actually work so basically like
you know when you're not using the track
bar Start menu blah blah blah right it
simulates to keep taskbar on top
unchecking that box this is what I
actually wanted like I've been surpassed
the simplest act taskbar Tweaker does
this job better than my code I recommend
you song said I installed this I do not
actually see any option for doing it so
I don't know if I'm just using the tool
wrong I haven't tried this one yet I
guess I could try it just to get a few
more viruses on my machine you know it's
always good but I don't actually know
yeah if it would actually work I could
try it and I don't I just understand why
this guy thinks that this tool does it
but he doesn't actually say how you
would do it you can see here like I've
got this thing installed if you open it
up right I don't even see an option for
it I don't even see I don't even see a
heading where the option would go but I
don't know like there just doesn't seem
to be I got I got nothing there doesn't
seem to be any any actual thing here to
click on you know I'm saying you know
what I'm saying
anyone no no one on the snow one on the
stream probably knows because I'm
guessing that people on the stream
probably have already moved to some
other thing I should probably try to
install a classic shell and see if that
has it or one of those other shell tools
and see if it you know can replace this
whole taskbar was something more usable
but yes so he says install seven-plus
taskbar speaker here is seven plus
taskbar Tweaker I do not actually see
any options that actually would work
dropping hovering thumbnails pin left
click other hi the start button that
actually does Head Start button doesn't
help show desktop button can go away
that doesn't help either although I'd be
fine with having that go I never used
that button display seconds is good but
doesn't help here reserved empty space
doesn't help doesn't do anything in our
case I just I don't know I guess I could
look at the help me the help have
something let's see
search top some of these tend office
with your tuned aspects of the tweeker
disabled tab topmost oh wait so it does
have a setting but how do you access the
setting options e^x
can use the eventual objects is it can
be open from the tray icon okay all
right all right let me see if I
right-click on the tray icon advanced
okay wait for it people this could be
exciting this could be exciting right
here apply okay and I think I also
accidentally shut this thing off so
let's see run that startup okay alright
done there we go
let's take a look that does not appear
to be disabling topmost to me but maybe
it did I don't know it doesn't look like
it let's take a look
my default password to type this option
allows change behavior always on top not
always on top but not over okay so I got
sent it to to RTFM I guess is the answer
there
try it one minute left in the stream can
we do it can we do it to return apply
okay oh my God look at it are you
looking at it look at how beautiful that
is
that is so excellent although it ruins
other top most windows like my top most
windows are now not topmost anymore so
close and yet so far
why would you taught me like that people
why well I guess we could also just
double check trying I could exit the
timer app and then start the timer app
again I suppose let's see if that helps
there we go so I guess it just it did it
to all top level windows it must have
messed up the Z order alright so what
day are we on I don't even know what is
it day 37 I want to say let's take a
look what day what actual day are we at
right now sorry we we may have actually
solved this problem so I'm pretty happy
about that but let's see what make sure
we're on the right day here video
archive day 37 was yesterday so we're on
day 38 today alright well that's pretty
exciting you have to admit that is is
pretty exciting I am relatively excited
about that hmm let's get all this stuff
straightened out again that means we no
longer have this ridiculous unused area
at the top of the screen we can actually
have everything go up to the height that
was supposed to be let's see does our
Emacs go to the hole look at that that's
fantastic well that is just great news I
am very happy about that that is super
cool you know that's the little things
you know I'm saying even if someone else
had to write them for for Microsoft at
least someone did there we go all right
I guess we can start the stream now
I hope everyone shared in that triumph I
don't know if they did or not can't see
what's going on on there yeah yeah I
think everyone's pretty except excited I
know I am so let's go ahead and get the
get the gloves on here and we will we
will go ahead and start the stream now
that we've had that that small victory I
guess I can close the old command prompt
from yesterday as well get back to our
standard standard screen and we can
actually get programming which seems
like a pretty good idea since this is
supposed to be handmade hero not
handmade fighting with the Windows user
interface get the taskbar out of the way
even though sometimes that is what
programming ends up being fighting with
Microsoft to get it out of your way is
often thing that does happen when you're
programming so you know it's not that
far off I suppose but let us go ahead
and return to the program hello everyone
welcome to day 38 of handmade hero the
show where we code a complete game from
scratch using nothing but our typing
little fingers no libraries no engines
so we can actually see the incomplete
process of making game and you can learn
how everything works right from where
the pixels are drawn on the screen all
the way up to how the game code operates
at a high level so today we happen to be
at the point where we are putting
sprites on screen and we are not doing
our full render yet because that's a
little bit more of an involved process
but basically we just wanted to have
something where we could easily put some
graphics up on the screen for our own
testing purposes as we are sort of going
through and figuring out what we want in
our engine architecture and one of the
big parts of that obviously is going to
be what we want for our rendering
architecture and it's kind of hard to
make those decisions without something
to work with so that's what we wrote
yesterday but we have a couple things
left that we need to do to it so that's
what we're gonna be doing today if you'd
like to follow along at home and you
went to hand made here at Oregon
pre-order the source code you should
have gotten a link in your email address
in your email inbox and that link will
allow you to download both the art
assets that we're using and it will also
allow you to download the source
so if you download that source code
today is day 38 so go ahead and unzip
day 37 source code out of the source
code zip file does zip files basically
has a ton of little zip files in it's
like a Russian nesting doll kind of
thing and there you go that will
basically give you the same source code
that I am starting with right now so
let's go ahead we've got a bunch of
stuff to do so let's get to it I'm gonna
open up the debugger here and just point
out where we were before if you remember
we were looking at putting the sprite up
on the screen but the colors were wrong
and so the question was what was going
on there and it turned out that since I
think it was my fault actually I had run
a little resizing tool on some of the I
had run image magic to resize some of
the pit maps and it rode them out in a
different byte order than the ones that
came straight out again and so basically
what we have to do today we figured out
this at the end of last stream but
basically the bitmap header has these
things at the bottom red green and blue
masks that we figured out and we've got
them laid out in here so we know where
they are and then in the files well that
basically tell us where the red green
and blue components go and it's I guess
assumed that the Alpha is just whatever
these aren't because there's obviously
an alpha component as well and there
isn't an alpha mask parameter as far as
I can tell although maybe there actually
is in an extended version of the file
format I'm not sure but well we were
looking on on the website of the
documentation it looks like it was only
red green and blue but doesn't really
matter because we can tell if the Alpha
is because it's where the red green and
blue isn't so what we need to do here is
we need to I don't know if you remember
this but basically we already were doing
a thing where we were swapping around
the order of the stuff that came in
because it wasn't the order that we
wanted so our pixels were packed with a
BGR which is this thing right here and
so this is actually not correct anymore
this comment we've learned is erroneous
and so basically what we need to do is
change this to say what's actually going
on which is the byte order memory is
determined by the header itself so we
have to read out the masks and convert
our pixels ourselves
right and so that's what we're gonna
have to do today so basically now we
assume that when we load one of these
BMP files we have no idea what order the
things are in and we basically have to
go ahead and figure out where they are
yeah we could for we now know we know
that basically none of the files that
we're saving you're gonna have anything
other than 8 bits per channel so we do
know that we're basically looking at an
oxf F kind of a mass but we just don't
know where it actually is in the 32 bits
we don't really know where it shows up
so what we need to do is we basically
need to get a shift value for each of
our components so if you think about it
we basically have a red shift not to be
confused with the kind of red shift that
they use in astronomy obviously that's a
different kind of red ship but we have a
red shift of green shift a blue shift
and an alpha shift right there we go and
so what we're gonna have to do is we
have to figure out what those are and
then we're gonna have to come in here
and actually get them out
right and so when we actually build our
thing we could make this a little simple
by taking the actual color value grab
that and then we could do it this way
just make it a little more easy for us
to write here we basically can figure
that we we know we need to put PAC
things such that the Alpha is on top
then the red then the green and the blue
right so what we need to do essentially
is we need to shift the red hmmm well
you know what unfortunately I don't know
that there's really any way we can do
the shift totally generically in with
only one ship I'd have to think about
that because really we need to shift it
they could have to shift in either
direction right where where the red is
in our source I don't know if you guys
are already on the same page here in
terms of what I want to do but basically
I've got something where I've did you
know I've got a 32-bit value right this
is my 32-bit value and essentially I've
got the eight here the this is 8 bits 8
bits 8 bits 8 bits right this is the low
this is the high and basically what I
need to do is I've got you know some set
of things I've got the reddest some
where the greenest number that blue is
somewhere whatever so I've got my ABCD
and I basically need to rearrange these
right in some arbitrary way like I have
no idea where they actually need to go
but I know that I'm going to determine
where they need to go so what I need to
be able to do is I need to be able to
mask it out and then shift it to the
right location but I don't actually know
which directions gonna have to go it may
be that like this was the green before
and the green now has to go here so the
shift would actually be a left shift
right it'd be getting higher but it
could be the other way around where it's
actually below and so it's actually
gonna be the right shift right and since
I don't actually know if there's really
any way to write that concisely what I
think I'm gonna have to do instead is
first shift it down and then shift it up
so I know that my shifts are always
basically are always going to be to the
right for the parametric amount so
basically my take the C and I'll shift
it down by the alpha shift value right
whatever that alpha shift value is I
will end it with with the mask so that I
know that I've basically now just got
the Alpha sitting in the low eight bits
and then I'll shift it up by 24 to put
it in the position where I actually want
my alpha to be right so that is
basically what I'm gonna do for each of
my values just so I can usually a lot of
times people call this like a Swizzle
I'm not really sure why they call it a
Swizzle but a lot of times they do so i
basically want to get the red the green
and the blue by shifting them down like
this masking them and then putting them
back into the place where i actually
want them to be like that and so really
all i need to do here is figure out what
the shift would be to get whatever the
value is down into the bottom down to
the bottom a bit problem is that only
have that i have the mask and i dont
have an alpha mask technically right
whew hello that was odd what I actually
have I've got the red mask right that
comes out of the header red mask I've
got the green mask I've got the blue
mask but the Alpha mask actually isn't
there as far as we know right I don't
actually have an alpha mask so what I'm
going to do is I'm going to assume that
the Alpha mask is just wherever there
wasn't a red a green or a blue so if I
or the other masks together basically
make a composite mass that would mask
for red green and blue all at the same
time
I'm gonna assume that the knot of that
if I flip all the bits in that then I'm
gonna get basically where the Alpha is
right because that'll basically give us
wherever the other ones aren't right and
I'll just I'll dummy up these values for
a moment just so I can show you what I'm
talking about for those of you who may
not be super comfortable with bit
operations yet
I think it's amusing actually but I
think someone was actually asking just
on like a scream like yesterday or the
day before whether we how if bit
operations normally get used and today
is like all about bid operations right
so so the answer is definitely yes
anyway so if we read out the red green
the blue mask you can see them here
right there's the red mask the green
mask and the blue mask that's saying
it's basically the Reds in the high
greens in the second down the Blues in
the second from the bottom and the and
the Alpha we don't know we don't get get
that right so what I'm going to do is
gonna order them all together which will
basically produce Oh X ffffff right and
then I'm going to not it so you can see
that basically what I get is I get what
the part is that isn't filled in in any
of these other ones right and so that's
what that that's what I want I just want
to fill in that extra value right and I
can do that a little more explicitly if
you guys want just to just to see what
I'm talking about here right I can do it
in two steps I wish they allowed you
step into an expression it'd be so much
nicer god what do all the things
debuggers could do and don't so there's
the alpha mask first before I've knotted
it right you can see basically if I
order them together I get the composite
of all of those masks basically and then
the not just this flips just flips what
the actual values are right so that's
what that's what I was doing there so
that gives you all the masks but now we
have a problem which is basically we
need to actually know essentially what
the lowest bit is that set in these
values right because we need to know how
far down to shift so we're essentially
want to count how many bits there are
that are 0 starting from the first bit
and going up to the very first bit
that's set right now what's interesting
about this is this is actually something
the processor can sometimes actually
just do for you it's called a bit scan
right and basically like well you know
what I can even probably
right here right so if I look in here
it's a bit stand forward there we go if
I take a look at this here you can look
at MSDN it's actually compiler intrinsic
the compiler can actually instructions
for it basically what it says it'll
search from the least significant bit
right which if you remember if I was Li
significance at the bottom right so this
is this is we're talking about the bit
here this is the most significant this
is the least significant bit this is the
most significant one right and just in
our 32-bit value so this is bit 31 and
this is bit zero okay so basically we do
bits can forward what we can do there is
we can say okay what I'd like you to do
is give me back whatever the position
was where the first bit was set right so
tell me which bit was the first one set
which is kind of what we want because up
here somewhere we've got eight bits set
right somewhere and we want to know how
far to shift them down so that they line
up right here so they start here and so
really what we're trying to do is we're
trying to do a bit scan to find where
that value is right so we can implement
this ourselves obviously right we could
go ahead and actually search for it so I
could do for example I could come in
here and say internal and I could
basically have I guess of bool 32 for
example if I guess I don't really know
because this is the way that this
processor I don't actually remember what
the how the actual instruction works but
it looks like the way this thing works
is it basically returns a boolean that
says whether or not it found a bit at
all and then it writes to an index to
tell you where where that index where
where we did actually find it so if we
were going to mirror the way that that
worked basically it's an unsigned care
that it returns and so I don't actually
know that I care about that so much I'm
going to do a UN 32 there and then it's
going to be an unsigned int that's the
that's the index as well so basically it
looks something like this
it's can forward right and if I go ahead
in here and say all right I want to
implement this myself right you can kind
of see how we would do it it's not
particularly complicated right we just
have a UN 32 well I I can actually do
Buhl can beat you here because it's
still 3 2 value and I can you know found
equals false I can then do a search like
literally with a for loop right which is
you know tests equals zero test is less
than 32 plus plus test right and then I
can do value and one shifted up by
whatever the test amount is and if that
turns out to be set right if value and
one should set up test turns out to be
set then I will write the value of the
bit into the result and otherwise I will
not and so that will basically give me
you know which whichever one it hits now
if I find one oh sorry I've I've
actually done that slightly backwards if
we're trying to look for the first bit
that's set not the first myth that's not
set so we actually as soon as we find
one that is set we want to stop looking
and if we didn't hit one we will write
to our index value right so if it's a
zero we count that as a as a as an index
no no okay nevermind no I'm correct I
was correct the first time sorry I got I
confused my own self there as soon as we
find those in set we're actually trying
to return that index so we just set the
index equal to the one we found and we
break out everything should be fine
right and and I guess we set found equal
to true here so that we know that we
actually found one we can return the
value properly now let me take a look
here because since I confused my own
self during the explanation let's
actually go ahead and make sure that we
actually did it correctly so this is
redshift
we passed the address of redshift and we
will basically look and see red found
equals that and we can assert red found
so and then we'll compile that oh right
we already have the redshift there we go
so and what was the problem cannot
convert argument one from int 32 oh yes
right sorry UN 32 there we go
so if I go ahead in here and actually
step into it what I should find is that
I pass in here I've got a value that I'm
checking for it's all the way at the top
so I'm expecting the value to basically
be 24 right so I come in here and I keep
shifting up test to see whether it
actually hits against the value it's not
gonna hit for the first 24 times right
bla bla bla well it's what 23 times I
should say turn off X vessels you can
see 13 testing testing testing testing
testing testing up to 20 22 23 and now
24 should hit it rights back to the
index so now the index gets 24 written
to it at least that's what should happen
find out oops start index right 24 we
say that we did find it and then we
return so there we go we've done the bit
scan forward and we say that red was
found the red shift is 24 which is
exactly what we wanted so that's the bit
scan operation but we're now doing it in
a very slow way so what we'd like to do
is we'd like to actually have the
processor do it and this is the perfect
time to talk a little about the
intrinsics things that I keep alluding
to but haven't actually done yet so
maybe today we will actually do
intrinsic so that we can call the bit
scan forward okay yeah also I should
point out for those of you who aren't
familiar with these there's a bunch of
these sorts of things right so you can
actually count the other way as well
right if you want to do from the from
the high downward to count like the
basically the zeroes that come at the
top you can call the reverse version so
so you know you've got there's yeah
there's a bunch of intrinsic that will
output those sort of things that the
that the CPU can do but that don't
really have any way of specifying them
in C per se so anyway let's go ahead and
get this working first with that but
then what I think we might do is just go
ahead and do that today so we can go
ahead and do move this into the
intrinsics and call the MSB C version
and there we go and we can leave this
you know sort of slow implementation as
the reference implementation as well
which will be nice because that would
basically mean that you know we wouldn't
have sort of a yeah we wouldn't have a
problem if people wanted to compel on an
architecture where the CPU can't do that
and they just need a slow version of it
to make it work that's good too because
remember this isn't really time critical
here so at least for this function it
wouldn't matter if you could you could
use the slowest possible thing and it
wouldn't really matter right so the
other thing too is I wonder if I should
fix the API a little bit because I guess
we can always wrap the intrinsic in our
own in line that just kind of would get
you know kind of felt out a little bit I
could make it so you don't have to pass
an address there basically so I could do
something more like this which is like a
bit scan result or something like that
which is you know whether or not it was
found and the new in 32 that was the
index right something like this and then
that could do something that looks more
like that in line bit scan results so
bit scan result and that would equal you
know nothing at first
having some typing problems today is
true and so then when we actually go
through we will then return the result
here and we will do results that index
equals tests and results ound equals
true like that and break out and then
we'll return the result that way and so
that would be a little handier than them
having to do sort of passing the address
nonsense which doesn't seem particularly
useful to me I don't I don't really
think there's any reason to structure it
like that I was just mirroring the way
they were doing it any other one so now
you can basically do something like this
where we basically have these so we'll
just get the bit scan results out of our
mass values directly like that and we'll
do the bit scan for words here and you
know the other thing I might do since
I'm kind of in charge now in Microsoft
bit scan for words kind of a weird term
maybe I would do something like find
lowest find least significant one
bit person least-significant set bit
something like that right because that
actually says what it is the bits came
forward well what do you mean by forward
at least now we know we're trying to
find the least significant one that's
set and so that actually seems maybe a
little more saying to me I don't know I
guess it would depend on endianness
things and blah blah blah but I think
that might be a little bit better
because at least I understand what that
is when I read it at least on one
architecture it makes sense so that
seems like priced a better idea so let's
go ahead and do that will now get each
of them out blue mask and alpha mask so
now we have found those and now we just
shift those by their indices like so
index index index index and we can also
do an assertion on each of them because
basically we're not supporting loading
anything that doesn't have all of these
panels at the moment maybe in the future
we would but for now we want at least
ensure that we don't actually
accidentally load something that doesn't
have one of these channels so let's take
a look at where that puts us on the
scale of fixing our color problems hey
it looks exactly right to me now the
only thing that we're not handling now
is of course the alpha blending around
those the edges and on the background
and that's the next thing we have to do
anyway so that seems like a pretty good
thing to do I'm gonna go ahead and say
though that since we're we've got a fair
bit of timer I'm just going to go ahead
and give the intrinsic thing a shot just
because it's about time that we started
talking about those sorts of things we
don't have to do very much it's not very
complicated it's a very simple thing to
do so it might be a good one to start
with so basically what I want to do in
here is I want to move this bit scan
result I want to move this out and I
want to move it to here right and so
what I want to do is be able to have
this dysfunction such that if we are on
a compiler that can do it really quickly
it will do it and and not have to go
through this for loop it'll instead just
tell the processor to basically tell the
processor to do it you know in a much
more expedient way if that makes sense
so really what I need to do here is I
need to be able to figure out whether or
not you know basically whether I'm on it
welcome
however I'm alone if that makes sense
and as you know as I said I talked about
quite a bit at the beginning you want to
keep all of your stuff segregated as
much as possible in terms of keeping
platform code out of
platform-independent code right so
you'll notice that we buried everything
inside win32 handmade and you'll notice
none of this stuff leaks out into our
main code all the win32 specific code is
all in here right but there are limits
to what we can do there if we don't want
to sacrifice performance like what I
could do here right is I could call a
function back in the platform layer that
did this operation right and that would
keep it and I could even pass in a
pointer to that function so it was
completely isolated I could do all kinds
of stuff but the problem is the only
reason why you ever care about intrinsic
sin the first place is for a performance
if we didn't care about performance we
just run this for loop right so the
intrinsics file the whole point of this
intrinsics file is going to be the this
is the place where we make a compromise
and say that this is the place where we
allowed to do platform specific stuff
that can be directly included right into
the code of platform nonspecific stuff
if that makes sense and again the only
reason we're doing that is for
performance if we didn't care about
performance at all if we literally just
had no performance concerns then there
would be no reason to do this there'd be
no point you would just always do things
the way we had been doing them but in
the case of intrinsics which are which
you're only using really when you're
caring about performance in the first
place this is where that sort of stuff
that comes in and so what you want to do
is you basically want to have it
isolated again you know even though it's
you're sort of saying it's okay to mix
things up a little bit here you still
want it as isolated as possible and so
you want to basically boil it down to
like a file or two that have compiler
switches in them and that bring in that
sort of non independent parts of the
code right so that's basically what
we're going to do here so what we're
going to do is basically say you know if
the compiler is msec
right then we know that we can issue
this thing because this
compiler happens to support this bits
can forward thing right and we want to
do from lowes LSB to MSB so we're
basically going to call this one we know
that in this case we're scanning a
32-bit value so basically what we're
gonna do here is we're going to to call
this bits can forward the result found
is going to be equal to that return
value we're going to pass the address of
the index that we wanted to be set and
it'll set it and then we're gonna pass
that value and so that's just gonna
allow it to do it right there we're
gonna make sure this is smart to in line
so hopefully if the compiler isn't dumb
it will go ahead and say oh yes we can
go ahead and in line this directly and
turn this into a instruction right so
that's about all we have to do there but
we have to do this compiler of
determination and so I'm gonna go back
to our handmade believe it's have a
platform right yeah in handmade platform
what I'm going to introduce at the top
kind of like you know we have this sort
of basic this is like the basic setup
for the the code this is what has to
happen in the code I'm going to do a
little thing here which basically says
you know compiler m SVC is zero and
maybe compiler LLVM because i know those
are the two things at least that way
we'll compile under right and what we
will do is we'll sort of do an if here
on some kind of thing basically if you
know if not compiler m SVC I should do
this way if n dev compiler MSD C and if
and if and F LLVM this you know I could
write these out a little bit more
cleanly so you can kind of see what
they're doing it's a short if end death
is like a shorthand do you find that so
what I'm going to do is if the compiler
variables and maybe I'll even make a
little section here like this and this
can be you know note AC pipes like this
Thank You Emacs for indenting me it's
finding the C++ bracket they're doing
the indentation but I didn't actually
want to do what are you gonna do
compilers so basically what I want to do
here is I want to basically say okay
if the build system whoever is building
us our batch file whatever if they want
to explicitly set what the compiler is
then we'll just let them set it so
basically we're only going to set these
if they're not already set then so we're
gonna and we're going to clear them to
zero or actually I guess what we could
do is if they're not already set right
then what we do is at the end here no I
still need to do this so we need to do
something like if the if the compiler is
not set at all right if we have no
compiler set whatsoever right this sort
of thing then inside here is where I'm
going to actually try to determine what
the compiler actually is so if neither
the compiler things have been set by
anyone then I'm going to go ahead and
try to see what the compiler actually is
and MSV see for example will
automatically define something that
tells us what it is I don't remember
it's like MS Sivir I mean I think it's
it's something like that but I want to
actually go see what it actually is
before I make that clock Proclamation
underscore I'm a sefer yeah almost
underscore MS Sivir so basically I want
to do that and say if that's true then
compiler MSB c equals one right and then
what we'll also do is we'll do an else
here and in this case we'll just assume
it's LLVM for now but we'll put it to do
here which is basically like more
compilers or something right maybe even
like that and so eventually we'll do
something a little smarter than that as
we go but right now we're only compiling
nm SVC so you know for now that should
be good enough so when we actually do
that let's take a look at what happens
here oh right we have to undefined
compiler it because we define it to zero
and you can't just change it
unfortunately you got a undef it first
like so and then when I got one one
missing Kendra so then there's a end if
there alright so now it's coming that
bits can forward is not defined and that
may be true let's see what has to be
defined in order for that to exist
somewhere let's
well it looks like we just need to do
that or do we actually have to pound
include in trindade I'm not actually
sure if we need to do that or not we
could take a look I guess the first
thing we could do is try this first and
see what it does so if we're defining
MSB see we can basically now have our
little section where we do the things
that we want to do if ms DC is here such
as that pragma in terms of function not
declared so okay so I guess we have to
do include this file as well which is
the intrinsics and then we'll see okay
bits can forward cannot convert argument
one from you at 32 start to unsigned
long star why not types pointing to or
unrelated is that really true why would
those be unrelated
I guess unsigned in and unsigned long or
technically different types oh the
mystery is of C++ I can program it for
so long and yet things like that always
still confused very much what actually
do you believe the technical difference
to be between those types and I have
absolutely no idea
oops put that in the wrong place there
we go so I believe that should probably
work let's find out and see if it does
and hey guess what it does and now let's
take a look in there and see what it
actually did differently now when we
step into it so if we step in here you
can see that this is actually using this
this line that we talked about and if we
go to the disassembly we can take a look
at what it does so essentially what
happens here is do you see this BSF
that's bit scan forward it's literally
one assembly language instruction that
does all the work of that for loop now
don't let that fool you because the
assembly language terms can still take a
while to execute sometimes but the point
here is basically that like that is so
much more concise certainly to the
processor and it's probably going to be
much faster than if we were to actually
have to micro to code the loop ourselves
because if this is executing something
in micro code that's still gonna be a
lot faster right so basically what
happens here in fact you can even watch
it work
what its gonna do here is going to move
the value this this thing right here
it's going to load that value into the
EAX register right and that's this
register right here it's a little
confusing because we're in x64 mode
which means that it uses our ax to
denote the ax register because it's 64
bits long but really what we're talking
about is we're talking about the bottom
portion of it here right we're talking
about the bottom 32 bit value so when we
do that you see how it loaded it in
there there it is it just loaded it
right there and now it's going to call
that BS F function on the value in the
register to load it out right it goes
ahead and does that and the destination
is also e ax so it's going to write the
result back in there right and you can
see that it written wrote the result
back in there and that's the result that
we were expecting right that's what we
wanted to actually have again it's in
hexadecimal which is why it looks like
an 18 instead of a 24 but you know
that's that's just well you know I can I
can here you go
so Oh X 18 right you can see that that's
just the hexadecimal encoding for 24 so
there it is and then that is the
entirety that right there did like the
entirety of that this loop right so
that's intrinsics in a nutshell they're
really pretty simple and basically what
we want to do is we want to do those for
anything where there is a convenience
CPU instructions so that we can access
it because we don't want to go around
especially when we start getting more
time critical code we don't want to go
around wasting a lot of that stuff that
the processor could do for us by Optus
getting it now it's possible that the
compiler might have actually been smart
enough sometimes depending on the
compiler to actually realize that this
is a bit scam forward but why make it do
that when we could just go ahead and say
this is f what we want right and so now
we've done that and we're in good shape
so now we're loading our stuff and we're
pretty happy but if you actually take a
look at what happens here you'll notice
that we would like to be able to
composite this guy on top of things and
right now we're not actually doing that
and so that brings up use of the Alpha
channel which we should talk about now
it's actually very very easy for us to
make this work but you know well you
know what I'll do first I'll basically
show you the really simple version first
and then we'll talk about it a little
bit so as you know the Alpha Channel
right if you remember how this is how
this works in the actual art tool let me
see if I can actually
how would I do this I'll go to a
hand-made data test and I will load up
that hero front head there we go edit
with GIMP so if we look at this here you
can see that basically you've got your
red green and blue color channels but
you also have a fourth channel and that
channel is called the Alpha Channel now
most people probably sort of you know
even if you don't know exactly what that
is
you know intuitively now what it is
because you've probably seen it in paint
programs like you've probably worked
with it before right and so if we take a
look at the channels dialog let's take a
look here inside GIMP there's a channels
dialog right which is this you can
actually see I can turn off the channels
and we can actually see the Alpha
Channel by itself right instead of the
other channels which is basically all
the Alpha channel is is it's basically
just something that says where the image
exists and where it doesn't
and it's got partial values around the
edges that basically say well the it was
transitioning at this point right it was
transitioning its anti-aliasing that
edge basically right it's giving a
partial value because the shape
obviously can't be rep is not perfectly
pixelated the shape was actually
supposed to be a smooth line that went
through there and so these alpha values
are basically there to kind of smooth
that out and to sort of give you that
gradual fall off so it's not a hard
cookie cutter edge right it just kind of
feathers the things into the background
for you that's the way the art was set
up to work so right now we're drawing
those red green and blue channels but
we're not doing anything with the Alpha
Channel and obviously since the Alpha
Channel is the only thing that tells us
where the image exists we need to start
doing something with the Alpha Channel
to display the person such that display
things on top of other things so that
like bottom layers show through upper
layers right and so inside our renderer
this is going to work well yeah I won't
say how it's going to work in the
renderer necessarily that's that's a
little premature so let's not say that
word let's say a different word what I'm
actually going to say it's not that what
I'm going to say is let's talk about one
way we could easily implement this
for our testing purposes for our testing
purposes what we can do is basically do
exactly what Photoshop or anything else
does where we basically just think about
things in terms of layers we could draw
something first we could draw down you
know our trees or whatever in the
background right and then we want to
stick a guy on top of that what we would
do is we'd essentially think of creating
a separate layer right which has our guy
on it and basically what we'll do is
when we draw that layer will only draw
in the places where the Alpha Channel
says there was actually a shape and we
won't touch what's underneath in the
places where it's not so well basically
do compositing very much the way you
would think about it in Photoshop where
you have one layer and you're basically
drawing layers on top of each other and
you just don't draw where the Alpha
Channel says there isn't anything and
that gives you this ER through so
basically like it's like taking pieces
of paper cutouts and stacking them on
top of each other wherever it was cut
out you could still see through to the
thing that was underneath right so that
alpha layer at the Alpha channel is
basically telling us where to do the
cutout it's basically what tells us how
to do the cutout so how do we actually
implement that right well while we are
drawing right we basically have
something you know we've got our trees
you know they're there and then we've
got our guy and he's got the Alpha
channel on and says where things exist
and basically it's zero everywhere where
he does not exist it's 255 everywhere
that he does and at the edges it's
somewhere between those two values right
so it's basically a brightness value you
might think of it between 0 and 25 that
says what you know how much he exists at
that particular point so what we would
like to do right is we'd like to think
about that essentially for now as an
opacity value basically to say how much
of a guy blends through and by the way
we could use this alpha channel as well
for partial transparency like if we have
something that's supposed to be sort of
ghost-like that we want to sort of only
partially blend on just like in
Photoshop how you could paint the Alpha
Channel to be some middle value like 128
or something that's partially
translucent we might want to do that too
so what we'd like to do is use this
value essentially as a way of blending
in between the two right so I don't want
to talk about that
yet because let's just do the simplest
possible thing let's do something that
just for starters
uses zero or 255 or sort of rather on or
off so we'll basically say if it's zero
we won't draw anything and if it's 255
or sorry if it's anything from 1 to 255
anything in between we will I guess
another thing we could do is say 128 is
the cutoff so basically anything less
than 128 we won't draw anything greater
than 128 we will draw right you can
pretty much see how we could do that
very simply right because we're
iterating over all the pixels of the guy
in our drawbitmap regime right we we
iterate over all the values here to do
this dest plus plus equal source plus of
us right so what we could do instead is
we could go ahead and change the way
this works we could do both we could
always do both advances right and we can
isolate just the copy like that and what
we could say is if that source value the
source part that's coming in extract the
alpha right we shift it down by 24 to
get just the alpha by itself if that
value is greater than 128 then we do the
copy otherwise we don't make sense right
so if we did that and we ran it we now
get much more of what we would expect to
get right we now get something which
doesn't draw the guy everywhere where he
had an alpha value less than 128 and it
does draw the guy everywhere there's a
value over 128 and all we did was just
add that one simple test right that's
all we were doing now what you'll notice
is it has a very hard edge around him
right if I was to do the the zoom in on
this right let's say we go in tikrit a--
there i don't actually know how creative
work sir can i do a paste as new image
paste into new image i don't know i
don't really know how to use this
program Oh does this what I want I don't
even know all right yeah I guess it is
it's doing what I wanted okay good
enough so if you're looking here you can
see you know there's a lot of
anti-aliasing this is very smooth
graphics there's a lot of anti aliasing
everywhere in here there's a lot of kind
of you know blurring of those edges to
make them a little smoother that's kind
of the way the art works but when we get
to this guy you'll notice there's
no smooth there's no blending there at
all so it's a very hard pixel edge along
the guy and the reason for that again is
because we're not using any partial
alpha values at all right we're not
doing anything to try and use those
values that are in between 0 and 255
we're just making a hard cutoff now what
this is often called in fact you'd see
this called this in 3d graphics lot it's
called alpha test is what this is called
which is basically a hard clamp limit
which basically just looks at the Alpha
value and says I'm either gonna do an
operation or not based on whether the
Alpha exceeds a threshold or not and
that is exactly what we implemented this
is basically alpha test right here but
what we'd like to do is something a
little bit better than alpha test we'd
rather do something that's actually some
kind of an alpha blend a blend that uses
the alpha value to compute the the
resulting color that we'll use what's
underneath
to actually and show through
what's underneath in case the alpha
value is not 255 that makes sense now
we are going to do this in the slowest
and dumbest possible way because I'd
like to make show the math being
explicit and so this will not be fast by
any stretch of the imagination it will
be very slow but again we are not
writing the render at the moment what
we're trying to do is write stuff that
we can use and so what I'd rather do is
just well you know what no I'm not going
to talk about how to do any of the fast
stuff we're just going to do it in the
slowest possible way so what we'd like
to do now is we'd like to go ahead and
and see about how to actually do that
alpha blend now I probably shouldn't
spend too much time belabor this because
there's actually an entire video in fact
of me explaining interpolation and I
don't know whether we want to rehash
that entirely on the stream or just did
that just crash I think frita just
totally crashed on me it did didn't it
uh yes it did
creative just totally just crashed it
just full-on it full-on went away
completely well what are you gonna do
watch it back up come on you can do it
it was working so well there for a while
see I tried to make a new image I guess
the thing to remember has never tried to
make a new image people that's the rules
you don't ever want to make a new image
all right that's fine make the image
please there we go hello all right okay
so here we go so what we need to
essentially do here right is I want to
make something that allows us to
smoothly blend between the two values so
we have a background value right I don't
know why that's always the hand shape
just is I guess the hand was what they
thought was good there so I have a
background color that's coming in right
I've got a hand apparently that's
drawing this now I've got a background
color it's funny to have it be a hand
like that that helped it all nope that
doesn't help at all welcome to the
mysteries of the universe ladies and
gentlemen I've got a background pixel so
this is one pixel right I've got a
background pixel and I've got a
foreground pixel right that this is the
sprogis I'll call this the sprite pixel
the bitmap pixel that we're drawing
right so this is whatever is in the
buffer and this is whatever is in the
thing we're putting on top right and so
in this code here we've got a source and
a desk right so basically this is the
desk this is the thing we're writing to
and we've got the source here this is
the source this is the thing that we're
trying to draw down this is the guy's
head right so this is the trees pixels
this is the the head pixels right so now
if we do this what we need to do is this
is some color
you know let's call that color a and
this is another color we'll call that
color B Wow
this is awful like I can't even click
down anymore ah I tell you computers
these days nothing ever works anymore
okay so I've got these two colors a and
B and what I want to do is I want to
produce a third color out of these right
I want to produce a C that's some blend
between a and B and what I wanted to do
is I want it to
blend based on that alpha channel right
I want the alpha channel to blend it
such that when it's zero I get a and
when it's 255 right I get B does that
make sense so when I actually go to do
this what I need to do is figure out
some some mathematical way of getting
from A to B smoothly based on another
value right I need to figure out some
way to pick because if you think about
the number line right you know I've got
255 at the high end for each Channel and
I've got 0 at the low end right
essentially what I'm doing here is I'm
saying I've got two points on this and I
don't really know where they are in fact
they don't even have to be in a Pickler
order a could be higher than B or vice
versa or whatever right so this is let's
say and this is when I say colors
obviously I mean one channel so we could
think of this as just the red Channel
right or the green channel or the blue
channel just one of them so when I'm
going to do this I basically have
whatever was in the background whatever
that channels color was right that's
here and then I have whatever the the
new color is that I'm blinging on top
whatever that the sprite is whatever is
in the guy and that's here and what I
need to do is figure out a way to
produce all of these values in between
here right I need to be able to produce
all of those values based on what the
Alpha channel is based on what the Alpha
Channel says and if the Alpha Channel
Zero that I'm going to leave it where it
was so I'm not gonna touch the
background at all at the Alpha Channel
typically five I want to drive it all
the way to be right so essentially the
way you could think about this and the
way that I usually like to sort of
explain it to begin with is that you can
think of it as being based around one of
the numbers we can think of it as being
based around the number that's that's
zero primal so the number where we have
zero yields that value which in this
case is the background color right we
can think of starting there and what we
want to do is you want to start there
and we want to sort of go some distance
towards be where that distance is going
to be 255 if we went all the way right
and zero if we didn't so how do we
produce what that with that actual
distance is right what's that value well
if you know rudimentary math you already
know what that is
it's just B minus a right B minus a is
if you will almost and we haven't talked
about vectors yet but it is essentially
a one-dimensional vector but it's
basically the Delta right it's the it's
the difference between a and B such that
if I were to take a star today and add
back in some you know this this full
portion I would get B and it's pretty
trivial to see why algebra wise right a
plus B minus a well the to the a
positive and a negative cancel and you
just are left with B which is the value
that I said we would get right so this
is basically the core the core of the
thing that we're going to use to
determine how to plan something right
because basically all I really need to
do is take this expression the a plus
the B minus a right and say as if I can
figure out some way to only add part of
this in there right all I really need to
do is stick some kind of a percentage in
here right some kind of a value that's
like a percentage from zero to a hundred
percent right if I could just multiply
this by some percentage then I could go
any percentage of the way from A to B
just by changing what P is right a plus
some percent of the distance from A to B
is going to give me exactly what I want
right so if we go ahead and build on
that assumption right if I want to say
I've got a plus some percentage here
right and also by convention this is
often called T I'll just point that out
to you we can use that cuz you'll see it
use us this way for a often but some
percentage of the distance from A to B
this would basically give me that value
that I wanted this would be that result
in color this would be the color that I
wanted out right so really all I have to
do is figure out how to do that
now what you'll also notice is I can
rearrange this expression in a couple of
different ways if you know algebra which
I'm hoping everyone on the stream does
because well honestly I've never thought
about how to teach algebra before so I
don't suspect that would give a very
good explanation but assuming you know
algebra then you also know that I can
pretty trivially use the distributive
property here to distribute T into this
expression and I would end up with these
terms right a plus TB minus T a right
and I can rearrange those terms any way
I want to so I could group them this way
right I could group them here by just
removing this term this term here moves
here right and this term stays where it
is this term slides there if I do that
rearrangement what you can see here is
these two front terms both have an A in
it so I can pull out the 1 minus T there
times a plus TB okay and now you have
what's usually the more canonical
version of what's called a linear blend
right this is usually called a linear
blend and what it is in either form
doesn't matter which one you find more
attractive they're just different ways
of computing the exact same thing right
algebra it's the same thing all they are
are a way of taking one thing in that's
just you know your starting value one
thing in that your ending value and
basically being able to produce anything
in between them by plugging in this
percentage value here but we haven't
actually talked about how to actually
make this percentage value work in
practice I just kind of magically waved
my hand and said we had a percentage
value here so we now need to talk a
little bit about just how that guy works
right well literally in the math sense
and if you're doing this entirely in
floating point math it could literally
just be a percentage right you know how
to translate percentages again if you've
had high school math or whatever you
know how to track translate percentages
into floating point math 100 percent
right is 1.0 50 percent is 0.5 right
zero percent is zero right so the number
is between zero and one all inclusive in
there are just those four
so really in this expression if T were
to range between zero and one including
all the fractional values in between it
then no matter what a and B are I don't
care what they are they could be colors
that could be anything positions in
space whatever doesn't matter this will
give us a blend between them right this
will allow us to move smoothly between
the two of them okay and so if you're
interested about in more about this sort
of stuff as well I would also recommend
if you do want to go to YouTube on the
hand mate in fact YouTube Casey Mira
Torre I think is what you would type in
here let's see here
Casey Mira Tory on YouTube there we go
you can actually see in my videos page
there is a witness Wednesday part 10
interpolation video and that is a full
on 50 minute explanation of
interpolation and how it works in a lot
of different ways so basically if you
want to watch that for more information
you can do that as well so where are we
at here we've only got seven minutes
left so let's go ahead and slam in the
floating-point version of this so that
we can actually see it in action and
then maybe we'll go ahead and fix it to
the fixed point version later but
basically you can see exactly what I'm
talking about here right so if I was to
go in here and write the floating-point
version of this let's go ahead and see
what we get
right what I would get first of all is I
gotta extract my read write and so my
read channel is going to basically be
shifted down by by 16 whatever's in that
source rank and then masked off so there
we go
and convert it to a float so that's a
number between 0 and 255 there we go
doop doop so then we have green I guess
I could just do our G and B for short
all right the green is the 8 and that's
0 then the alpha channel right I need I
just said I need it to be a number
between 0 and 1 well this will be a
number between 0 and 255 right so if I
want to turn a number between 0 to 255
into a number between 0 and 1 I need to
divide by that range but I need to
divide by 255 so that way 0 will map
0-255 will map-21 and everything in
between will map somewhere in between
right so now I've got an Arg and a bead
that are actually in floating-point now
I need to do the exact equation I just
said I need to create my new read so
I'll say that my read is now going to be
equal to oh I forgot something
I need the desk as well so I have my ice
or SARS and my Death Star's right I've
got I've got to pull them out of here
so that I can blend with them right so I
pull out the Death Star of the desk G
the desk be and I've got my sorcerer and
source' G and and to be fair I guess I
don't actually even care what these are
we don't even care if these are our G
and B we just care that their channels 0
1 & 2 right we don't even care so we
could be wrong about these shifts and it
wouldn't matter as long as we do them
all so anyway now I'm going to actually
produce my result red and my result red
is just going to be the exact equation
but I just specified it's going to be a
plus T a minus B if I wanted to do it
that way or I can do it this way over
here which is 1 minus T plus TB
right so I can do it this way right
times a plus T times B so we'll leave it
that way for now and we'll basically
just say okay if I do one
what's my T well my T is the Alpha value
that's the thing that's that's actually
causing it to work there and then what's
my a might be my a is going to be my
destination red times my source red
because I'm trying to get to the source
red right so that source red is the B
color and the the back and color is the
a color right all right I believe that's
what we said it was and so off we go now
we'll go ahead in and just do that for
all of them I've got to move that up a
bit so it's not obscured by the
five-minute warning the dreaded
five-minute warning be a B be like that
and then once we're done we have to then
reassemble the resulting value back into
something that we can actually use so
what I have to do now is actually do
sort of that that build back again for
the thing that we're going to actually
write to death so we have to actually
write something to death and what we're
going to write to death is going to be
our board with our G or with our B but
we have to now turn them back into
actual actual rounded values right so we
have to actually round the values each
time now so like that I suppose we could
just go ahead since we know these are
always positive we could also do this as
a truncation which would be a little
cleaner right I could do it this way
where we just actually truncate the
values plus the rounding amount like so
which I think you know probably is a
little stainer here since we are
actually doing this per pixel per pixel
things are very expensive so we do have
to watch out even in our test code so
that we won't get too slow and not be
able for not for us to use it but we may
replace this we probably don't want to
be doing this necessarily in floating
point math the way that we're doing it
here right now anyway but anyway point
being so here we go we're gonna actually
take these values and pack them back
into the places that they normally go
right like so we basically unpack them
and pack them oops
8:16 like that the argot shifted back up
thank God to put everything in there I
don't know I wrote that in pretty
quickly there we'll have to step through
this and see if it works
but I believe if we typed it correctly
we should have I'm not gonna open I'm
not gonna paste things into crea anymore
lesson learned we're gonna paste things
into GIMP from now on that way at the
crashes we can still draw in the
background so now let's take a look at
what happened can you see and hear how
that how that looks now we're you've
basically got you know that kind of
smooth that nice smooth edge now that
we're being the alpha Channel so that's
a much nicer comp right that's just a
much nicer thing to look at right and
yeah I mean that's that's alpha blending
in a nutshell right and so what kind of
alpha blending actually is this this is
a straight linear blend between the two
there's other like I said before on the
previous stream there's lots of
different things you could mean we say
alpha Bunny it depends on what that
blend equation is right so basically
this guy here this is our blend equation
that we're using there are other blend
equations so what I'll also say here is
to do KC
someday we need to talk about
premultiplied alpha because we are not
talking about that at the moment but now
is not the time to start that discussion
suffice to say this is not be multiplied
alpha but I'll just leave that for a
little thing that we can talk about
later on because at the moment it's
really not something that you need to
think about whether it's premultiplied
or or not but it is something that we
will have to think about a little later
on because it affects the math in very
important ways and we will need to
switch to using p mult multiplied alpha
for our final assets and so on so since
we are basically out of time here I
believe yes we have one minute left I'm
gonna call that done for the day we have
our alpha pudding working oh you know
what I'm not gonna quite call it done
for the day I might do one more thing
although I think this this actually will
cause us to have a couple bugs but I'm
gonna go ahead and make our our hero
head actually draw at the location of
the player now yeah so there we go so
there's our hero head very exciting he's
not actually in the right position but
at least he moves around there with the
guy very much fun yay yay for alpha
blending we're pretty close now so I
think basically tomorrow we'll have a
little guy walking around instead of our
rectangle because we're pretty close
all right everyone that is it for now
the Q & A has begun remember I only
start looking for Q colons when we start
the Q&A so please if you have a question
that you like answered now is the time
to post a chip to the twitch chat put a
Q : in front of it and please keep the
questions here in the post stream to
stuff that's actually out the code that
we wrote today or in previous days if
it's something that's off topic and
about something else please come before
our stream sometime oftentimes I try to
be on the stream about 15 minutes early
to answer just any off-topic questions
that you want answered and so I do
answer those that it's not on the po
stream because this is the one that kind
of goes into the recorded handmade hero
stream for people to learn on later and
I don't want to have lots of off-topic
stuff that they have to skip through
okay tiny typo in function name finally
significant set bit is missing an eye
okay thank you gasps blizzard let's take
a look at that intrinsic find least
significant there we go
that's better let's go ahead and click
that finally sick okay thank you very
much that is a definitely a typo yes
that's true
so mosaic Oh was talking about asserting
the compression mode is true we only
load one type of compression now which
is compression mode three so while we
are asserting the masks we should
probably also go ahead and assert that
the header compression mode is still in
that three mode because we don't load
any of the other compression modes at
present so we'd want to know if we got a
file that didn't conform to that
compression mode so that we could be
warned about it it's a good point so
also someone was saying we don't need
that intrinsic definition anymore well
we do actually need so I that's not
actually true so um I'll tell you what
the person saying and then I want to
make sure that is actually the case that
I'm not sure it is
so we'll yeah we'll talk about that so
basically what the person was saying
they were saying that the you don't need
this pragma intrinsic if you include
intrinsic but I'm not 100% certain if
that's the case let's find out so let's
say we do that right
now let's go take a look at the code
that gets generated just so I can see if
it actually still does that is intrinsic
it might but I just want to make sure
because I don't actually know sometimes
it doesn't for other functions I'm
pretty sure it doesn't but for this
function because they may not have done
a separate implementation of it then it
might not so that's that's definitely
possible all right what am I looking for
here I'm looking for a load bitmap right
load BMP so basically in here what we
want to do is take a look at this and
see what it generated go to disassembly
nope so does it okay so that's totally
fine so then it is fine without it
sometimes the reason that I don't that I
sometimes if you if you have if you
don't put the private intrinsic it'll
only use it in optimized builds or
whatever and so I wanted to make sure it
was I we there's no reason for us not to
always use it but as long as it always
does do that then that's totally fine
would it be worthwhile to avoid
converting to float when doing the alpha
blend yeah well so this is one of those
things that basically what we have to
say is who knows so technically I think
it probably would be in this particular
case right but we're so far away from
actually doing performance oriented
stuff that who knows it may be that it
really just doesn't matter for our
purposes at all in this particular case
but for something this trivial you can
do it entirely without moving to float
but you know first of all you'd never do
this you'd load the whole thing as a
Sindhi vector instead of doing the
channels individually like this is just
not we aren't thinking about performance
right now so thinking about whether you
could convert to float or not is just
not that relevant because there's so
many things that are wrong with this and
from a performance standpoint but it's
it's just not really that useful to
think about it I mean it's an I I
actually would suspect probably that at
the end of the day we won't even be
storing things in this format we won't
even have a RGB ease we might have like
a buffer of A's a buffer of ours and a
buffer of G's and so on right so things
might it's it's it's worth being aware
of how your code is performing but it's
also worth knowing when you don't really
care about some differences and in that
case I think that's a difference we
probably wouldn't care about that much
it might be interesting to do it just to
show how you would do it without
converting it to float but yeah do I
expect this to be a major performance
thing no not really because
already performing so poorly probably
that I'm not sure how much worse this
would really make it you know it's hard
to say why is the windows logo still
visit I have no idea because I don't
know if you caught at the beginning of
the stream I was doing that that tweak
thing that seven-plus task for our
Tweaker thing and it's the thing that
that's causing the windows to not be on
top it might be it might be possible
that that's a thing that was intentional
so let me see if it's in the Advanced
Options I'm not sure let's see let's see
why that's doing that you know that's in
the the help over here
so see option Z X and fix is about when
the classic theme is used clicking on
the string crooner no customize
horizontal paging it's a showing trick
lock allows to customize your desktop
button its rest reverse the direction
yeah I don't I don't actually know if
there's a thing I'll look for it later
but I don't see unfortunate I don't see
a way to get it to stop doing that
so I think that's might just happen for
a while until we figure out how to get
rid of it
let's see are there other ways to use
out or are there other ways to alpha
blend and should you be taking into
account which colors are easier to see
like green appears to be brighter than
red so assuming that I understand your
question correctly I think what you're
asking is are there other ways to blend
between two colors such that you're not
just using per channel so the first
thing I will say is that yes there are
many ways you could consider blending
between two things this is a linear
blend for starters and it's linear in
whatever space the colors are in which
themselves may not be linear so we
haven't we'll talk about this a lot we
get to the renderer but basically what
you have to understand is that the
colors that are displayed out of the
monitor are actually not linear so
basically you know we think about these
colors and we're doing this math the
math actually is assuming that that
colors are are linear a lot of times but
actually the way things work is there's
actually a curve so basically you know
there's a color value that you set so
there's basically a value from 0 to 255
that we are setting and we're calling
that the color right so what happens
though is that when that value is given
over to the display it actually goes
through a number of mappings potentially
once potentially on the graphics card
and once potentially by the monitor that
actually changes the perceived
brightness of that to not be linear so
then there's brightness here right and
so what actually happens is there some
curve that happens here right that you
know there's there's some curve you can
imagine where as you change
the actual numerical value of the color
instead of it getting you know if you
change it from between zero and ten the
difference in brightness may be much
more than the same distance right 240 to
250 or something might be a lot less of
a difference in brightness right let's
say or vice versa depending on how those
curves are set I think they're usually
set in this way but I can't quite
remember their exponentiated right yeah
so well exponentially they went through
this I don't know let's take a look
so just to just to give you the it's
been a lot this is the first graphics
programming I've done in a long time
actually so you know a lot of this stuff
is rusty for me to be honest with you so
let's see srgb gama curve can you look
at that can we get that up here
somewhere gamma curve there we go so
linear space and there's well that's not
what I actually wanted I wanted one on
one side and one with the other this is
not giving me the values I want I just
want brightness on one side and value on
the other I'm not looking for gamma
correction I'm actually looking for just
that doesn't anyone bake it down I just
want someone who's baked it down for me
that's really all I want well let's take
a look and see if this has it so srgb
that's actually got the full Clark you
here we go that's RGB intensities versus
HIV numerical values right so basically
let's see which was red so srgb
numerical values are red curve these are
the numerical values and I assume that's
the intensity showing exact low a
compressed value observe as linear
intensity or at a linear intensity as
this curve is linear so the gamma is 1
which curve are we talking about all
right this is not what I wanted I just
want why can't I get what I want maybe
I'm misinterpreting these diagrams but I
literally just want what I just drew
I wanted something that's the value that
you put into the buffer that's coming
out and how bright it appears on the
monitor that's all I wanted I don't know
why I can't get I just want one graph
that's just got that curve on it so that
I could show you but I don't know okay
so we can't get that curve maybe we'll
look up that curve I'll look up that
curve outside the stream so I won't have
to waste your time watching me try to
read through documentation but basically
point being it's nonlinear so it's
entirely possible that that is a bad
thing for your blend right you may be
doing alpha blending and you want this
this alpha was expecting it to be you
know let's say a smooth linear
transition so as you change alpha you
get a smooth step all along the way but
instead you're actually if you're doing
it in this exponentiated space
unbeknownst to you a little bit of the
blend actually goes a long way in terms
of what the perceived blend towards the
new color is things like that so there's
alpha corrected versions you can do some
of these things there's other blend
equations that do other operations that
aren't designed to basically map one
thing on to the other there's pre
multiplied versus not putting on
premultiplied alpha which is basically
getting rid of this 1.0 minus a term and
baking it into the to the I'm sorry gets
rid of this a term and bakes it into the
sr term which is another thing
altogether so there is a lot of stuff
that goes on here I don't know if that's
exactly what you were asking but that's
how that works
whether you take into account the fact
that channels work differently I don't
think so because the images themselves
have already had that taken into account
and you need to smoothly blend between
them so you could blend in a different
color space like you could blend a set
of blending in RGB you could blend in
HSV or you could blend in log or you
could do other things like this I don't
know whether that's really such a good
idea though because then what you'll get
is you're not going to get smooth
changes in the colors of the pixel
elements on the screen since they are RG
and B so I think that's probably where
you want to be for the operation that
we're doing but if you were trying to
alpha blend if you're trying to do an
alpha line that was trying to do
something else like smoothly blend hues
of things together then you might want
to blend in a different
space one that wasn't based on our gene
be one that had different properties I
don't know sorry I don't have a good
answer to that question really I don't
know yeah I don't think I answered that
very well but there are different ways
of blending things but I don't know if
they are exactly the way that maybe
you're thinking about it are we at all
concerned with the destinations alpha or
blending with a transparent destination
so well we are and we aren't basically
we're not concerned the reason we're not
concerned with the destinations alpha
channel at the moment is a because we
don't so two reasons first of all we
never really right the destinations
alpha Channel
because we don't care about it at all
right so you can see in this expression
we don't even write it it's always zero
right the destination just always gonna
have a zero alpha channel always now
that doesn't mean you have to do that
you can do rendering that uses the
destination alpha Channel to store
important information that it will use
and this is basically something that we
may explore later when we're actually
doing our actual renderer because
there's reasons why you might want to
use that summation alpha to do things
but right now we don't have a
destination alpha however what I do want
to point out is this doesn't have
anything to do with blending with other
transparent things because that actually
just always works because basically
since we are since we're basically since
we are always drawing things in
Photoshop style like I was saying before
where we're going to layer things down
such that we start with the bottom layer
right which has just whatever our base
code is right at some grass or something
right and then we're gonna like right on
to that a tree or whatever and then
we're going to write on top of that the
guy that's in front of the tree since we
know we're always going to be doing that
photoshop on top up on top up on top up
on top of compositing we will always
work because just like Photoshop layers
always stack on top of each other
properly we will always that on top of
each other properly if we were to draw
out of order right so in other words if
we're trying to draw stuff stacked up
right I'm gonna try and do a really bad
stacking diagram here so if this is our
background and this is sprite one
and this is sprite two if we're always
drawing in this order right from the
bottom most thing to the top then
stamping down we know that all we're
doing is writing in the colors of this
thing where they exist and blending them
with the background whatever it was so
another transparent thing that comes on
top doesn't have to care that the
destination buffer is actually already
the combination of two things
it doesn't care it'll just stack on top
of it properly so it doesn't matter to
this guy whether this guy had a
transparent portion or not because
that's already been resolved by this guy
by this operation right by the time this
guy writes to it it's as if they're only
ever was one buffer because all the
things that came before and have already
been slammed in there right if we were
going out of order if we were gonna try
and render the top thing like the this
bottom thing then this top thing then
the middle thing and this has to insert
between them then that's the point where
you start worrying about what the what
was actually written into the buffer
before right and that's all a huge mess
so basically what we want to do as much
as possible since we are a 2-d game we
have the luxury of probably being able
to do always to always know the order in
which we're drawing things and that will
let us do a bunch of things that are
actually extremely difficult in fact
sometimes impossible in 3d renderers
which is basically order independent
transparency is what they have to do and
they have to do all kinds of work to
make that stuff happen properly it's
really a nightmare for them it's why
games really hate stuff like looking
through several sets of windows at some
smokey particles right having lots of
translucence is actually really hard in
renderers for a number of reasons so
they try to avoid those sorts of things
or do them with sort of what they'll
usually do is they'll they'll actually
break apart the pieces of the scene that
are transparent partially and they'll
sort they actually will sort those
they'll draw everything that's not
transparent first and then will actually
sort the transparent pieces and draw
those in passes just like we're gonna do
for our renderer but we have the luxury
of being able to sort all of our stuff
so everything will just work for free in
that way
but they don't have the luxury of that
because they have a much higher
primitive account they have a much
higher primitive per pixel count than we
do and so they don't they can't get away
with that right so yeah well the final
blend favored the source over the
destination or is linear good enough I'm
not sure what that means we're really
not favoring anybody we're just using
the Alpha Channel to tell us how much of
the foreground should come in at that
point right how much of the source
should be used so I'm not sure can you
restate that question let's see how
would you deal with other picture
formats such as PNG JPEG GIF etc well we
just write a loader for whatever the
other format was or if you're lazy and
don't want to write another loader you
could just run a conversion tool and
then load them that way right you could
just run some freely available
conversion to a batch conversion tool
like image magic to batch convert your
stuff from whatever your source format
is into BMP so you could either load
them yourself review that or like I said
I'm hand made hero we write everything
from scratch but you don't have to write
everything from scratch you know there's
no reason that it's you can't use a
image loading library if you'd like to
and there are several that are available
there's thing called free image that
loads images you know your mileage may
vary but there's libraries you can use
so it's entirely up to you yeah
why is the math so complicated to use I
assume the BMP format does that because
it is somehow easier than doing
something else why isn't the math they
specified something that can just be
ANDed with the value or something so I
don't know why they chose that it seems
like a really bad idea to me what I
would have done is I would have
specified the order just hard-coded the
order and if I really wanted two
different orders like one for
little-endian one for big any and I
would have had a flag but you're right
the masks and BMP are complicated to use
for no real reason like why do we have
two bits can them because they're just
it was not a very smart format or store
the shift in there to write like store
the shift and they're like what spend an
extra 16 bits at the front of you're at
the front of your file format right to
tell what the ships were
something else that came up earlier the
stream did you mean to call the arc zone
of caprara LLVM or clang I always call
it LLVM because really it's it's not
clang that really is the thing that
determines what the intrinsics are it's
LLVM for the most part because LLVM
either has those intrinsic sin the bike
code or doesn't and if LLVM doesn't have
the intrinsic in the byte code then it's
like playing is just I mean playing just
a thing that like spits out LLVM byte
code right like and so if LLVM byte code
has intrinsic then it has it and if not
it doesn't so I typically always think
of it as LLVM but you could call it
playing if you wanted to it's up to you
in the bits can function what about
returning the index and have it sets a
negative one if not found
I see search functions doing that a lot
yes you could do that I find that to
just be a little more error-prone so I
would rather have there be a clear rule
that you can switch on because the
compiler is is probably going to
reorganize that stuff anyway and so it
just seems like an easier thing to do
can you go over the linear alpha blend
diagram again sure I certainly can so a
linear blend is actually something that
you can think about working between any
two things even if you don't really even
know what they were as long as they obey
a few simple properties right you could
almost think of it as just any two
points in any space right as long as
that space obey some linearity things
which let's not let's not get too crazy
for the moment but basically if I have a
point that I'm going to and a point that
I'm starting from right and I want a
linear blend between these all I need to
do to be able to do a linear blend is
have a way of producing the sort of the
the difference between those right I
need a way of being able to say a minus
B now I need to be able to produce that
and what that is like a minus B right
B minus a because we're going to be so B
minus a is basically telling me this
motion it's telling me how to go from A
to B right so on a simple number line
right if if I'm talking about just 5 the
number 5 is B and the number 2 is a I
subtract them right and I get 3 it's the
amount of steps it would take the
distance it would take to get from one
to the other right but this works in all
dimensions not just one so I'm just
gonna say like okay it's something it
doesn't matter two dimensions three
dimensions four dimensions I don't care
as long as we're talking about is you
know basically Euclidian stuff here as
long as I can produce this I can do a
linear blend and the way I do that
linear blend is you can think about it
exactly like you think about starting
someplace and walking somewhere else
right if I start a day and I add in this
difference this move movement right here
that B minus a right and I add in B
minus a I will get to B that's just how
it worked like you can think of it very
simply if I take the distance between
these two things and I and I walk it I'm
gonna end up at the other one right now
technically it's not quite a distance
it's actually a directional distance
right I know what direction I'm walking
to and that's why it's important that
we're talking about sign the numbers
here
right B you know if I say like I said
before let's say B was was actually
three and a was the five are sorry just
to was what I said before let's say B
was two when a was the five it's
important that I don't end up with three
here when I do this operation I need to
end up with negative three because it's
a direction I need to know which way I'm
going
right but basically as long as you can
produce that you could end up with this
which is basically just I mean it's it's
as simple as as this it's B equals a
plus B minus a right this this equation
right here if you can produce that
equation for the things that you're
talking about linear blending is as
simple as introducing this right you
could produce that new point by saying
instead of walking the whole distance
between a and B I'm going to walk some
portion of the distance between a and B
some fractional value that can be
whatever it is it could be 50%
it could be 25% what
ever it is and I will get however far
along there I need to go and that is a
linear blend like I said you can use
algebra to rearrange it if you want to
you can multiply this out if I have a
plus T B minus a equals some new value I
know that if I rearrange that I can use
the distributive property t be minus T
hey like that and I can go ahead and
regroup the terms these two a terms I
have a I have a 1 here in front of my a
coefficient right and I have a minus T
here so that's just 1 minus T times a
plus TB I just regroup the terms I
grouped this term in this term into one
term and then the TB still there and
that's the other form of the linear
blend that you often see so you've got
those two different formats there right
and so that's linear blending in a
nutshell it's very very simple
extremely powerful this one equation is
so powerful actually that you will see
it underlie almost everything we do in
this game there will be almost no part
of the code that does not at some point
compute some variation of this then so
trust me on this one you will have if
you don't quite understand it now you
will have a lot of opportunity to
practice because this is literally this
is probably if I had to say and I don't
know I haven't thought this through I'm
just saying this off the cuff but if I
had to say this is probably the most
important equation in all of gaming like
games need this equation probably more
than any other equation and there's tons
of equations that are important to
gaming but if you could only have one
this is probably the one you would need
because games can't do anything without
a linear blend because everything else
is built on top of it nonlinear blending
is built on top of it
all rasterization is built on top of it
all of animation is built on top of it
it's just incredibly incredibly
important
I'm unexperienced with Windows I know
we'd do a large virtual Alec at the
beginning is this basically the same as
an EM map in Linux yes for the most part
I'm not super experienced with M map so
I'm not prepared to say exactly but what
I would say is I would encourage you if
you have questions like that the best
place to go at the moment since I
haven't really looked at the Linux stuff
and haven't done an implementation of it
yet if you go to hand-made here or click
on news and forums there's a coding
resources page if you go to that coding
resources page go to the Linux listing
and click on handmade penguin SDL port
because I believe and I'm sorry if I it
turns out to be wrong but I believe he
actually explains how to do all of the
stuff that I did in in in Linux so you
can kind of go through here and look so
there's that M map and it appears to be
in the same place as our virtual Alex so
so take a look at that page handmade
penguin because that that would probably
be the best place to go for an
exploration since I know he's actually
worked it all out already
let's take a look here what bit value if
is 50% brightness well I'd be you have
zero and you have 255 so you can either
think of it as 127 well okay so here's
how to think about it in our actual
thing right here's how to answer that
question basically so you know that the
Alpha value that we're pulling out is
going to be whatever the alpha value in
in the bitmap is divided by 2 times 5
right so if you think about it what we
would want to do is say all right if we
have 128 divided by 255 what is that
well it's point 500 something something
something right not quite exactly 50 127
divided by 255 is 0.49 8 something
something something something right so
the actual answer is that there is no
actual value for exactly 50 127 is a
little bit low 128 is a little bit high
what are you gonna do you could adjust
this math to make it exact
you know if you wanted to write but but
the problem is you want to make sure
that one is exact so you need to make
sure that to be 5 by 2 to 5 is 0 like if
we were to do 128 divided by 56 you
could get an exact so if we divided by
triple 86 or you can get exact but you
could never get 1 because then your
highest value is typically 625 you would
end up never quite being able to get one
either and that has consequences as well
worst consequences in fact let's see
here let's see
what else we got does the display blit
operation actually do anything with the
Alpha Channel no it just writes zeros to
the Alpha Channel it's only using the
Alpha channels of control to basically
control how the blitt operates so it's
reading it but it never writes it if
that's what you're asking which i think
is what you're asking them now the solid
curve on Wikipedia's gamma correction is
the linear space intensity should be
what you are looking for okay so you're
saying go to Wikipedia and look up gamma
correction did you say or something else
what I'm sorry I just spaced out there
let's see oh we're out of time let's
just grab it then saw curve on gamma
correction I think so gamma correction
look at you so you're saying there's a
solid curve on here okay so you're
saying this curve right here hopefully
is what you're saying so I didn't do the
reading yet but assuming that that's the
solid curve basically is this what are
the two axes though the dotted line it's
a linear transfer function so I should
CRT there's difference what are the axes
by the way which axis is which hi there
guys can you tell me what the axes are
because which one is which one is the
brightness and which one is the input
value enable sheriff you have a
correction the dotted line indicates a
linear transfer function those solid
line shows how a typical CRT behaves the
dashed line represents the inverse
function so yeah so I guess I don't
actually know it doesn't say I assume
this is brightness and this is the input
value but I guess I don't actually know
assuming it was and you can see that's
what the curve looks like so it actually
has a lot more kind of resolution there
at the bottom then at the top there's
not a lot of resolution in the
brightness but I don't know I don't know
if that's reading this right because it
doesn't actually have the thing so we'll
have to look at that a little more
detail later all right
let's see I think that's about it for
stuff we can cover today
we have gotten this is pretty good we
have gotten to the point where we can
now do layered graphics on the screen so
I'm thinking it's a you know it's a it's
kind of a question to some degree about
where we go next like you know what what
is the next thing that we should be
doing if we're actually talking about
moving forwards on the game and so what
I was thinking of doing next is is
working on our player motion code
because I think that's important because
it's going to talk it's going to
basically speak to how we need to do our
collision detection which speaks to how
we need to interpret the tile map so I
was thinking of doing is basically
saying all right maybe we do a little
cleanup tomorrow and Friday of stuff
that still needs to kind of get cleaned
up a little bit just looking looking at
things like that see what we want to do
in terms of that sort of stuff but maybe
what I was thinking is so we'll start
next week on like actually talking about
linear algebra and vectors and we'll
actually start writing the movement code
for the guy for real so that it feels
good and we'll talk talking about
collision detection for real so that we
can kind of see what we need from our
engine for that because that's a really
important thing to spec that's one
direction to go the other direction to
go is we need to talk about how to
actually build these background bitmaps
right which is to say take the tile map
and kind of go ahead and build the
background bitmaps I don't know which
one we should do next it's kind of a
tough thing to say so it's a toss-up
maybe we'll flip a coin maybe we'll take
a poll I'm not sure both of them have to
get done before we know what our what
our engine spec really truly is so it's
something to think about but for now we
can always be happy that we now have a
nice living engine we can use so we can
put stuff up on the screen which is kind
of nice and from now on we'll always
have graphics to back us up which is
much nicer than looking at a bunch of
rectangles in my opinion so thank you
everyone for joining me for another
episode of handmade hero it has been a
pleasure coding with you as always and
it was a pleasure talking about the
linear blend which like I said is one of
the most important things you will see
it come up again and again and again on
the screen so it was nice to finally get
to that I think that's a pretty big
milestone starting to actually use the
linear blend and again like I said we'll
talk about it a lot more
in the future and we'll see a lot more
about it and we'll kind of learn more
and more about how interesting it is and
how intricate you can basically how
amazing it is that you can do so much
for such a simple function and basically
how it underlies everything if you will
so anyway thank you very much for
joining me if you would like to follow
along at home with the source code you
can pre-order the game and it comes with
full source code already every night I
update the source code you'll basically
a link in your email that you can use to
download the source code it also has the
art assets that we've been using on the
stream there's a separate zip file you
can download if you want to use like you
know the little guy and the backgrounds
and that sort of stuff for doing your
development and so you know anything you
basically completely follow along at
home and all the assets that you need to
follow along completely at home come
with the with with that pre-order so
check that out if you're interested we
also have a patreon if you want to
support the video series you can always
subscribe there we also have that news
and forums site which I showed just a
few minutes ago which has a ton of
resources for people who are trying to
learn on the stream too a lot of great
stuff the schedule for the week's always
posted here there's also the episode
guide which allows you to catch up with
old episodes got nice annotated video
series on there coding resources has the
ports like I showed before and other
resources you might need like good
documentation of stuff and there's a
forum you can post in when you need to
ask questions so please check that out
if you're trying to learn from the
series it's a great resource and there's
a lot of very helpful people on there
who are very nice on the forums who will
also try to answer your questions if I'm
not around to do so
so thank you very much for joining me I
will see you tomorrow same time saying
place 8:00 p.m. Pacific Standard Time on
Twitch so I hope to see you all there
and if I don't have an excellent
Thursday see you later everybody
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.