Post-processing effects in OpenGL are implemented through multi-pass rendering pipelines where effects like chromatic aberration, vignette, and film grain are applied to the final rendered image using fragment shaders. Chromatic aberration creates color fringing at screen edges by offsetting RGB channels based on distance from center, while vignette darkens corners using smooth step functions to create radial falloff. Film grain adds noise using pseudo-random generation based on frame time and UV coordinates to break up banding. These effects are configured through shader uniforms and can be integrated into game engines through configurable option systems that allow runtime adjustment of parameters like strength and feather.
Approfondir
Prérequis
- Pas de données disponibles.
Prochaines étapes
- Pas de données disponibles.
Approfondir
FPS From Scratch (C++26 & OpenGL4.6) // Post ProcessingAjouté :
Are we here? We doing it.
Am I talking to myself?
Hand. Hello. I'm not here by myself.
There's at least one other person here.
Quiet June. Hello.
Oran sneaking into Twitch as uh I need to bring back some of the other rewards, but I keep forgetting to do it.
What you going to do?
Crack. Hello.
Thor. Hello. Sth thought.
I think that's right.
Right. quite a few more people roll in and then we will start cuz there is more to be done. There's always more to be done. There is plenty to be done.
These windows I don't need.
It's fine. Don't worry about me. I won't take offense.
Betty, hello.
Oh, not even attempt to pronounce that.
Hello.
When I do the fixing videos, does it need to be in English? It kind of does because is it is the only language I speak. So, I don't really have I personally don't have a choice.
Uh, right. Okay. So plan for today is I want to continue along the journey of post-processing effects. We've got a couple got fog which is pretty sweet. We've got chromatic aberation which I did a very small amount of work on post last stream. So that's kind of working now.
We'll go through that.
Then I want to do vignette and uh noise or I guess like film grain.
And then um Oh, sorry. I misunderstood you. No, it doesn't have to. As long as I can reproduce it, like I don't care what language the game is in. Um makes very little difference to me. Um I just need steps to reproduce it.
Do I think OpenGL is is deprecated for modern rendering since it's basically developed during the '90s? No. I mean, it was last updated in what 2017. So, like that's it's not new, but it's certainly not old. Um, I think it's great for what I want to do. Uh, this this topic comes up over and over again. I just I do not need Vulcan, right? Like Vulcan does not need me and I do not need it. So, what where does that leave me? Um, and I've done OpenGL before and I know it. And I think if you kind of lean into the happy part of OpenGL, you can still get something pretty optimal out of it.
So, yeah, I think I think it's a great learning experience for graphics programming as well because I think if you start now and think, I'm going to write a renderer and you open up hello world, hello triangle on Vulcan, you like, okay, maybe this isn't for me. So I think I think it has a lower barrier to entry for learning a lot of the core concepts that are still applicable in Vulcan anyway even if the interface and the API is different materials. Hello uh yep we're going to go through it now.
Let's go through it now points. Right.
Okay. So let's uh let's make this run. Let's do let's do running things.
DX9 is pretty out of date, right? Like I think if you're going to do anything DirectX, you want to be targeting probably DirectX11, which I think is roughly analogous to OpenGL 4. Um, and then Direct X12 is sort of the uh Microsoft equivalent of Vulcan, I'd say, as in that kind of lower level API.
Right. So, we got we got all our things and we're doing things now. So, we got the fog and uh crunchy aberration now has a strength slider and uh you actually get quite I don't know if you can see it might be a little bit subtle. You actually get quite cool effect when you now move. So, it now affects radially outwards. So, you can basically set the threshold where you want the chromatic aberration to apply and by weakening the that number probably should be inversed but doesn't really matter. The smaller the number the more chromatic aberation you get, right? So, as you bring it out, you get less. So if you want it just like in the corners, you can set it like there. And then you can still set like the offsets, right? So if you wanted like real I know whatever horror like that. And then you can bring that um all the way in if you wanted. So if you set it quite quite extreme, you can see more of it here.
Yeah, indeed. Um but it doesn't apply to the center of the screen. So, as you see, if you as you can see, as I it is more strong, I guess, to the corners.
Um, so that's where we're at at the moment. Uh, I I think it would be disingenuous of me to say that I didn't uh consult the Oracle about this uh which I did. Um, and it because I was trying to work out how to apply it radially, right? And uh the the oracle suggested using smooth step on the strength and the strength of plus some small offset. Uh and then the distance the distance between the distance here is the distance between the center of the screen and whichever pixel we're currently rendering. So this will give us a value between zero and one zero if it's less than this one if it's greater than this and some interpolated value between the two. And then you can use this to basically scale the uh direction vector. Right? of zero then you'll have a shift of zero which means you won't have any offset and one means you'll have the full offset. So you can effectively use this to provide a scaling factor for the offset that you want and it works quite nicely. So you know can't really can't really complain.
Um so I think we can probably use this for the um vignette. Like it's going to be exactly the same thing, right? We're going to want a radius and some sort of feather, I guess, like you know, I think that's what Photoshop would call it. But like the like the the softness that should probably be customizable, but I'm not not that fast at the moment, but we'll definitely do it for vignette.
So, we should be able to say like the So, vignette is basically the um rendered final image gets darker in the corners, right? It's like a soft shadow, soft color bleeding in from the edges. And you'll see what that is when hopefully we get get to implementing it.
But it kind of just helps just darken the corners and focus your eye a bit in the center. And it's just kind of a nice little visual effect. Um, and I kind of want it in there just because one, I think it's fun. I've never done it before. I think it'd be fun. And two, if we have sliders and stuff, if we don't like it, we can just disable it. Um, so the idea, the first thing to do today is to add that. So we'll have a vignette, um, watch as I try and spell that a few times. Uh, function here. So, we're going to vignetti this pretty hard. Then after that, I want to do film grain. So, do you remember we were looking at this chap's blog post um and we had this issue where in the country that I live in, I can no longer see these images, but he actually has all this on GitHub, which was quite nice uh with the with the effect. So, we're going to add this.
This is way way overdone. enough. I don't want it nearly this strong, but it does have a um a strength, I think. Well, he has a hard coded amount. So, we'll put that as a slider. And then we can basically add it. And it just helps break up banding and just gives the scene a little bit more dynam dynam dynamis. It makes the scene a little bit more dynamic.
I think bait lighting is great. I'm not doing it, but I don't The reason just because I'm not doing it doesn't mean that that you shouldn't. I'm I I think if we want to do like screen space reflections or something fun like that in the future, we might have to have like light probes and render out like at the beginning of the scene cube maps of lights and stuff like that, but I don't really know enough. I've not done a lot of research in it. So maybe in the future.
Wouldn't shader specialization work better for configuration variables? Uh, I don't really know what you mean, but sure. What do you mean by shaders? You mean like compile a new instance of the shader with that value baked in? Is that what you mean?
Um, doing a video on hypervisor cracks is is is on my to-do list. I just don't know if and when I'll get around to it. So, maybe I'm kind of a little bit DRM out at the moment. I want to focus more on fixing interesting bugs in obscure games. That's kind of where I'm my mind is at the moment. Doesn't mean I won't come back to DRM, but it's just the RM videos are a huge amount of work.
Basically, pass variables at program creation.
What what is that like a specific OpenGLism that I'm missing or are you passing it into the format string?
Again, I'm not I'm I'm not aware of the mechanism of which you're talking about, I'm afraid.
for sure. Right. Maybe.
Uh, okay. So, let's do what's the best way of doing this? I guess let's let's start with strruct uh is it vignetti?
Is that right?
And then we're going to want color color uh float strength, I guess, and float softness.
I'm going to say feather.
I think I think I'm right with that.
And let's do uh colors.
Let's go black to start with cuz remember if we control the color then we can make it red in the future. Say if we're shot or something like that. So I think again having this kind of all configurable gives us a lot of u lot of um options, a lot of flexibility. Right.
Okay. I'm going to wire all this nonsense up. So, give me bear with me one sec while I just type the things.
Why I type the things? Uh, so we're going to want conextra. This is it. Like, this is actually kind of good use for an LM cuz it's it's shortcutting a lot of typing, but that's not what we're here for today.
uh options and then back to wherever we use the steady steady wherever we use the chro my mic in the right place chromatic aberration.
So, we're going to want options. I feel like this uh this constructor can be simplified to just use the default constructed ones, but that sounds like a problem for another day. Movie movie. Even though we don't need to, but whatever. Makes it feel like I know what I'm talking about.
Uh that's missing a T. Am I right?
Uh I'm working on a on a sort of most of the videos are reverse engineering, right? I think that's mainly like main channel videos reverse engineering.
Streaming is forward engineering. So the next video I'm working on at the moment is is that there's some there's some gedra, there's some debugging.
Uh oh, so good. I named it twice.
Uh, vignetty options. Vignetty options. Keep that happy. I'm not going to wire into the serialization just for the moment. Let's just get this working first.
Uh, conra auto scene vignetti options.
this auto self return self dot vignetti options right okay let's now wire that into uh the debug renderer so mue uh so got exposure options so let's do so much typing this I I really spend some time in this code like quietly and try and uh improve it cuz it's so grim.
All this I feel like could be reflected out or just just made better. Do you know what I mean? Like just made better.
It's just a lot of copying around boiler plate and I absolutely hate it. But for debug code, you know, strength.
Uh so let's do vignetti strengths and this is vignetti dot strengths equals value.
Thank you very much. I'm glad you're here.
Uh do I think the streams are for beginners? That's a really good question. Like I I would hope so, but I'm also kind of using it as a vehicle to discuss like how I program especially in C++ and especially modern C++. So like there is you're also if you if this is your first stream, we're like 30 streams in. So you're joining 30 streams into a quite a big project which is built on the work we did from 12 a previous 12-monthl long project. So, there's quite a lot, but I do try and keep each, as much as possible, I do try and keep each stream relatively self-contained. This is effectively a part two from the last one. So, I do appreciate that. You know, I try and do try and have a goal for each stream. We come along and we do it and then people should ask questions and if they've missed stuff before or they're new, then I'm more than happy to catch people up.
Um, so yeah, do ask questions. I'll do my best to catch up. But like it's it's the streams are not tutorials, right? So they they're not designed to kind of take you from like maybe specifically nothing to a certain goal. It's more of just a journey that I'm going on and I hope you will come along and find it interesting and we kind of have a chat as we go along. Does that answer your question? I feel like I I feel like I spoke a lot there without maybe giving you exactly what you wanted.
Yeah. There's there's there's a lot going on, right? There's like modern C++ is complex. OpenGL 4.6, right? And ASTO is complex. Game development is complex.
I've sort of taken quite three complex topics and decided to try and figure it out live as I go along. Um, so you know, we're all in this. We're all in this together. Uh, strength is going to want to be between Z, but I do encourage people to ask questions like, you know, cuz questions make great shorts. Um, let's do this between a zero and like I suppose 1.0F. Sure.
Yes. Thank you. Just done that. And then we need to do a color as well. So, I'm going to find a color one that I can go and steal.
Bog color as good as any.
I just feel in in in the year 2026 with C++ 26 and reflection, I should not be doing any of this.
Uh, so let's do vignetti options, but I need to sit down and have a think. It might be fun to do on a stream. I just feel like it's not it's not so important that it's progress I kind of, you know, maybe we'll want to do together. I don't know. Um, it feels like something I should probably just sit down quietly and think about. Right, let's just see if this builds and blends and runs and does the things.
Hello.
What else would you spell color? I don't I don't I don't think I recognize any other spelling.
Looking pretty good. Looking pretty good.
Okay. Okay.
It's it's very much a case of like this is this is my code base, right? Like I I feel like I feel like I can be reasonably precious around. Not that I'm super precious about most of the code I write because most of the code I write is terrible. But I feel like there's some things I can be precious about and that is that is my choice of spelling.
Thanks. I'm glad you're here. Well, we're writing vignette a lot today or vignette. I suppos it's not vignette French. It's not Italian. So don't pronounce the vowel at the end. Or am I just massively showing my ignorance of European of other languages? I think it's vignette.
How do you pronounce?
It's going to give it to me in like the the the pronunciation language, isn't it? I don't want a YouTube video. I want someone to phonetically tell me.
Uh, it's I think it's French, so it's probably vignette.
Vignette vinette.
V vignette. Yeah. Okay, nailed it. Not vignette, which is a type of ice cream. Oh, no, that's never mind.
Right. So, I got the Vienna strength and the feather. Let's Let's Do you know what? I ran it and I didn't even look at the bloody debugger to see if it was the options were there.
Okay, so we've got this and strength and fella. Uh, this should have a label.
Where's this green offset come from?
Whoa.
Have I I just copy and pasted this just for the funsies I have, haven't I? Okay.
Okay. Yeah. Sorry, was that question about WSL? I think I saw that somewhere.
Um this is just this is this is just WSL right that is all it is like to cross compile um build then I have a docker image setup uh which is all part of this project that you can find which uses which builds you trunk GCC and B and latest MGW and there's a make file which kind of ties it all Uh, I don't know what RTI bug you're going to be having cuz I don't think any of my code relies on RTI, but I could be wrong.
Trunk GCC trunk. Trunk trunk trunk. Is that not Is that right?
Uh, okay. Right. Uh, frank.
Okay. So, now let's uh don't know what I'm doing here. Uh, I think I'm going to change this um this shader from chromatic aberration to post-processing. I think I think I need like post-processing A and post-processing B and then just do as much stuff as in there where like the the the end of A is the tone mapping and then the end of B is the final image, right? Because some of them have to some of them require you to read and work on the effectively the final composited image.
Yeah, I'm having an existential crisis here.
Uh, Vet Veta.
Uh, I hate that. Okay. Right. So, I'm going to want some more uniforms between friends.
Uh uniform vex three U vignette color U vignette strength U vet feather.
Uh that's not how numbers work.
Classic integers. You add one each time except for five. Why don't you skip six and go straight to seven?
Uh, okay. So, I think I can start building this out.
Uh, so I want to do something like uh float. I guess I want float.
Uh it's basically like the v vignette amount equals the smooth step of u oh font a little bit smaller. Just keep you on your toes. Uh u vignette strength and then u vignette strength plus I might need to clamp this. um undecided color and then I'm going to Oh, I need to recal this.
Seems a bit of a shame to recalculate this, but I'm I might just might be able to optimize it later.
Uh but basically the same thing, right? So, this this is doing the same thing as the uh chromatic aberration. It's going to create a scale factor of like um based on how far the current fragment is away from the center based on some kind of initial strength and then some feathering amount.
Uh yeah, I could pass that in then like let's get it work and let's make it let's make it better.
Uh, and then I'm going to want to mix this. So like return mix uh u vignette color with I think it's going to want something like a vex 3 in color. I'll just call it color color vignette amounts. Right. So let's do uh vex free uh color equals chromatic aberration and let's do color equals vignetti color and let's do ve for cf steady steady cut Hold on.
What could go wrong? What could go wrong?
Oh, hang on. I know exactly what's going to go wrong. I need to wire some of those wire some of those uh new brand new fancy uniforms we've got in.
Uh so this is going to be uh scene dot vignetti options dot I think it was color and then strength and then filler Nope.
Oh, put a put put a float in there. Put a float in there.
Uh, chromatic aberration.
U vignette color is definitely that oh smooth step.
Oh, hang on. Don't want color, do I? I want classic.
Oh, nailed it.
You know what this is?
Exactly what I wanted was just a great big dirty smudge in the middle of the screen.
So, I've obviously got some numbers the wrong way around, but does does everything else kind of work? So, can I Okay, so I can change that, which is good. And then can I I can change the strength. And then presuming I can change the feather around. Okay. So if I wanted to just like if it was really important to the gameplay to just have like a great big pink circle in the middle there oval then like absolutely crushed it.
Uh what's what's wrong? Do I need to swap these round?
There we go.
Well, that feels quite costly. Right.
So, now I should be able to change this feathering quite a bit and then move this in and out. And then if I wanted like it to be red cuz I put like a darker red cuz we're being shot at or whatever then just it's not bad. Like you know I mean it certainly does what it says on the tin.
And in fact, you could wire this up to a co- routine to just like pulse this slightly.
Yeah.
Yeah. Exactly. Well, we can easily do that, right?
Just lean into the uh purple purple vibes.
And then yeah, I mean I think we're pretty much there, right? That's obviously it's never this easy. Uh you can make it really feathered. Bring that in.
Really, really feather that up.
Yeah. And then we could bring in the chromatic aberation. Yeah. Basically done, right? I like that. Let's super quick wire that up into the serializer.
Uh so description now needs one of these. So vignette options, vignetti options.
And then when we construct with this we can do vignetti options description dot vignetti options. All right. No, not semicolon there. That's not how C++ works, obviously. Uh, and then description dot vignetti vetti options equals self dot vignetti options. Okay, so this uh what great question. Uh, have I got any plans for shadows? Uh, yes, but I don't know what they are.
Like, as in like I've not really fully thought this through yet. So, we've got SAO, which I think is kind of enough to get going. And then I'm going to slap a whole [ __ ] ton of post-processing effects on there to make it look great or less less [ __ ] Um, I think shadows I will probably do a very basic form of um shadow maps, right? Probably from like a spotlight. So, we need to add I think we'll add a spotlight at some point.
Then just have like some top down lights and some of those can cast shadows and or maybe like a torch or something on the player. So, yes, but probably very because we don't have particularly large scenes. I don't think I need it PCF shadows or I don't think I need anything too complex. I think I can get away with some quite basic shadow like shadow techniques. So, that's that's my that's my current thought process. If anyone has any better ideas because they actually know what they're doing, then I'm all ears.
Right. So, this won't work because the scene YAML is now technically incorrect.
So, we need to do see if I can handcraft this uh vignette options and this will be here. Infinity options type and then this will have a color which will be a color type which will have a R of not RGB.
Uh, and then this will have some sort of doesn't it doesn't actually matter what the initial value is because I'm going to save I'm going to adjust it and then save it back.
Let's see if this works.
Postprocessing is a GPU effect, right?
got nothing to do with nothing to do with compile time C++.
Yeah, we might need to do something around like light at the moment. You're right. Like this light here, right, is coming from in here, but like clearly there's a wall in the way. So there there's some stuff I think we do just to maybe add a little bit of realism to it.
Yeah. So my I have automatic serialization of classes right um of my scene. So my scene automatically gets written into a YAML file whenever I click save here. So anything I change will get saved. The problem is that there's no concept of like migrations right I don't have a migration system.
So whenever I add something new right it will fail to load the old YAML file because those new values won't exist. So I have to manually put something in there and then I can go and tweak them and then save them back and then it will load every time after that.
So that's that's that's that's that that that be that I think I want it like quite feathered and just a little bit in the corner, you know, just that might even be that might even be too much. Just a little bit just to bring in the uh I can't see [ __ ] now. Uh I have to click somewhere else, right?
Just to look at a bright color wall. I want to just bring that in just a little bit.
I have vignettes on all my thumbnails, by the way, or most of them. And the amount of time I spend with the sliders in Photoshop trying to get craft the perfect vignette just for the compression algorithms basic just for YouTube's compression thumbnail compression algorithm to throw all away.
I think that's right. I think that's might be too subtle now. Oh man, this Welcome to vignette simulator.
A little bit there. And then maybe just feather it a little more. Yeah.
Something like that. And then we can make the let's make the chromatic aberration just a little bit stronger as well.
It's just on the fringes of that. There we go.
Let's just commit and save that before.
There you go. I think that's I think that's all right. Like it's not perfect, but I think it's I think it's made the scene already just a little bit more interesting.
It's a little That chation is just a little bit too strong now. But I think it's fine just to showcase it. So when we're doing the streams, people can kind of see what we've been working on.
Um, I don't really have like a lot of book recommendations. Like Effective on C++ is my favorite C++ book by Scott Mayers. Um, I really wish retired because it only goes up to 14, but it's an incredible book. Uh, the templates book is pretty good. Um if you want more classic CS then CLRS um AL al algorithms and is pretty pretty it's it's a pretty big book.
Okay. Right. So let's this let's commit let's in the git hole. Uh I it's basically all one commit. Right.
There's not really a lot I can kind of tease out of this because none of this is going to work separately. So this add vignette.
Okay.
Okay. Right now let's look at this film grain nonsense. So we've got here this I'm basically just going to largely transcribe what he's got. Right. I don't understand why he passes pie in here cuz I think he hardcodes it in the other one. But sure. I I don't really care for this formatting if I'm being honest, but like it it is what it is. Um indeed that is is that is that is the formatting that they have gone for.
Right. So, the next thing we now need is a uh strength for this. Oh, it's got to add so many more options. Oh, it's so tedious. I absolutely despise it.
Right. Still this [ __ ] again.
Green. At least it's consistent, I guess.
Float strength.
strengths. Uh, yes, I know it's not used. Give me a chance. Uh, fine. You were right. So, I take it all back.
Yeah, I know it does. I just It's It's a video as in like cuz I'm working towards the next video at the moment. So, most of my spare time is taken up with that.
After that's done, I normally have like a few I allow myself a few days before working on the next video. And that's normally a time when it's kind of like I can take a couple in an evening, couple beers, go over UFPS and you know do some refactoring work.
Uh film grain options.
Oh no, I don't want to add it. Uh should I just add it? Let's just add it to everything in one go. Just cannot be bothered.
Sorry, this is this is boring for me.
So, I don't know why it's snipe you guys out there.
Right.
Right. Okay. I don't need to be don't need to be rude about it. Uh film grain options description dot film grain options.
Uh 375 uh film grain options go away templates film grain options and then this will have dot another big refactor I need to do at some point is to commit to this handlebased system that we spent ages writing and refactor some of the um like the entities system as well. I think I might mention this last stream. Uh I think that's all I need. So scene we're going to have uh film grain options is a film grain options type. Uh when that is a strengths 0.1 F or see 0.01 F. Uh, I don't think I need the f on the end or the semicolon because this is actually YAML, not C++.
Uh, scene. Got thing I didn't give this a default value, which is naughty cuz it's inconsistent with everything else.
Thanks. Thanks for the thanks to the affirmation, right?
Uh let's do 523.
So that here. So this is going to be film grain options uh dot fil grain options dot strength. Uh, and then this is going to be film grain strengths and this is going to be do film grain options dot strings equals value. Okay, fine. That's all good. Um, then we're going to want to go to the chromatic aberation fragment shader.
gonna need another uniform, which means this should probably be a UBO or SSBO at this point, but that's a refactor for another day. Uh, film grain strength. Also going to need Oh, thank you. Yes.
Uh, probably like 0 to one, I guess. like either all noise or no noise or some some some noise. Uh we're also going to need a you uh I guess a is it a float? What do you pass the time? What's he taking the time as?
Float frame time float frame you frame time, right? Which we're going to have to bodgege in because we have no concept of frame timing or delta time or anything. I'm literally going to bodgege that in.
I think it depends how the maths works.
I think the maths assumes 0 to one.
Is it okay to use C++ without any of the modern features? Like again, programming languages are tools. C++ is a tool, right? If your understanding of the knowledge allows you to achieve your goals, um then yeah, you don't have to use any of the modern features. the modern features are really there and it may not seem like it to make your life easier. They tend to they they normally attempt to fix issu existing issues in the language or give you new primitives to work with or new vocabulary types or sand off rough edges or provide better abstractions. So like it may make your life easier but there's an inherent learning curve to all of those especially with C++. So if the time it takes you to learn those new features does not bring you any benefit then no.
However, I would always encourage you to try and keep up with the latest stuff because there is some good stuff coming out. Also metaroming is kind of like an old technique anyway. It's a kind of umbrella term. So I wouldn't consider there are now better ways of doing meta programming but meta programming isn't a new idea and you definitely don't need it.
Um yeah, don't know if that helps.
See, seems all right. Like I just think it's just for me the I think the language is too simple for the kind of abstractions that I want to build. And obviously like I know like like obviously the Linux kernel is written in C and like the wind32 like NT kernel is written in C. So obviously there's a lot of large scale software written in C but it's just not I want different abstractions that are easier to write in C++ when it comes to systems programming.
I want RAI, right? Do you know what I mean? Um I want smart pointers. I want a dynamic array.
I want exceptions.
Okay. Right. So now I got frame time.
Let's do I guess it's going to be vex 3 film grain. Uh vex 3 color.
Uh and then we're going to do yeah I think I'm going to once this works I'm going to try and remember to come back and pre calculate this only once and pass these in as parameters. But I think for now it's fine. So basically it looks like the way you work is you you basically fudge randomness right into the shader by taking the sign of time and with a some other inputs and that will give you like a pseudo random number and then that pseudo random number you use to offset the color of the pixel which will make it change right which will give you like a noise effect.
I think the idea that there is only room for senior engineers in the world of AI is kind of misguided but not not on your part on the view of employers who think that because how do you think you get more senior engineers right they don't just you don't they don't just you don't grow them right well sorry no that's a lie you do grow them they don't just come off like trees. My analogies run a bit short here. Um the only way to get more senior engineers when people inevitably leave or retire or whatever is to have more junior engineers and grow them and give them the domain knowledge that they need. So I think yeah I think I think basically firing all your junior engineers and replacing them with Claude is shortterm gain for very long-term pain.
Reflection is complex, right? It is a fundamental and like no one understands it in the sense that sorry that's not how I mean we don't really know what the best practices for reflection is yet. It's very new on the scene like people are figuring out what they can do with it.
Um so that is not a great place to learn C++ at the moment because the syntax is wild. It's very complex. It involves just to get reflection working involves like two or three other like other modern C++ 26 features as well like you need template expansion.
Um you need uh what else do you need? You need all the meta stuff. There's about five papers that were written and submitted to kind of make reflection works. There's a lot of moving parts to it. So have that as an aspirational goal. Like work up to that. But I wouldn't say you necessarily need to start with that.
Yeah, I was going down the analogy like you don't I don't really know where I was going with there. Like they don't just spring out of the air, right? Do you have to It's like yogurt, right? You make yogurt by taking some yogurt you've already got and like sticking in milk, right? And then it all turns to yogurt.
Like I I'm pretty sure that's how it works, right? You start with the culture, right? And then you you let that culture grow and expand.
around it. So you start off with senior engineers and then you give them junior engineers and then after a while you get more senior engineers.
So yeah, I mean it doesn't necessarily mean the job market isn't difficult at the moment and I do appreciate that. Um but I think I think it's not it's never too late to learn something new, right?
I think that should be what you even if you don't use it professionally like you've still learned a skill and you've still developed your brain and you've still shown that you can kind of learn something and you still have something to talk about in interviews right like hey I decided to learn C++ and you know here's this project I wrote like that's a great thing to have on the CV because it shows that you're interested in learning new things and it shows you can kind of talk confidently about what you've done and hopefully you can kind of use that to reflect on like your learning journey and the limitations and sort of show an understanding of like what else you know you still need to No, no, no. Senior engineers are yogurt.
Junior engineers are the milk that you put the yogurt that that surrounds the yogurt and then the culture makes more yogurt.
I I don't I I really don't understand how that's not clear. Like I really I don't I could not have made that analogy any clearer.
What am I doing? Um, float rand equals I want the fract which I think is the fractional version of one some magic number. Great. Love it. Of uh direction.x X plus direction do Y times U frame time times some other random magic number which oh this is this is heavy on the magic numbers over 180. So why is it two radians? Oh, cuz cuz it's float. Okay. Sorry. Cuz it's sign, right? So, you're converting that out.
That's fine. Um, I feel like I'm missing a He's got an extra Why's he got an extra bracket times times that?
That's right.
Yeah. Yeah. Yeah. Yeah. Sorry. Yes. I'm I'm aware of it. Yes. Yes. I'm aware.
Right. I just I feel like I've missed a times the sign of Why is he double bracketed that? And do I need to not sure that makes a difference, but sure.
Okay, so now we got that. Then we do uh rand times equals uh u from going strength and then we return color time oh interesting plus equals amount. So you're going to add a small Oh, you're going to add to it. I guess that makes sense. Um, and then color is going to be film grain.
Uh, and then render renderer. And then we're going to add some add just keep just keep adding more stuff. Scene dot uh film grain options do strength.
Right. And now I need to pudge in some time. He I think in his article he says that the time is the number of seconds have passed. So he wants that as seconds. We can do that.
Oh, right. Okay. Did I have that? I see what that makes. Yes. So, I'm taking that value and I'm converting it to uh radians.
Super is all flavors. Whatever. It's all things to all people.
I'm going to look up now if that's actually how you make yogurt because I use this I use that analogy an awful lot and I've never actually bothered to fact check myself whether that's true or not but I'm sure like like I'm sure I'm pretty sure you something something starts off with a culture and then grows more Right.
Yeah. Exactly. Right. So, if you take the yogurt you've already got and put in milk and get more yogurt, like it's an infinite yogurt glitch, right?
Right.
Yeah, it's just on bacteria. Right.
Okay. Let's do let's do this. Let's do static. Uh let's do static con start equals stood chrono. Ah, which one do I want? steady, which is which is the monotonically increasing clock that is not subject to system clock changes. I'm pretty sure it's steady clock, isn't it?
And then we're going to do uh here we're going to we might as well do this below.
We'll do con auto elap is two piece or one piece in elapsed just general engineering chat right when I talk about work about junior engineers and stuff like this comes up surprisingly often elapsed equals stood corono jur or chrono duration dur duration cast stood chrono seconds. Uh, and then I want to do stood chrono steady clock now minus start. Right? So that will that will get the elapsed time since the this function was first called. Um and then but I think the standard duration on Windows is nanoseconds or it's 100 ncond intervals isn't it? But the granularity is nanoseconds even if you only get them at 100 ncond intervals. So this will just convert that to seconds, which means we should now be able to here do elapsed dot elapsed elapsed dot uh the count.
There you go.
Yeah, that's true. Uh ah yes, I bet that's what that rando thing is.
Um yeah, uh duration cast is just a way of moving between because uh chrono types are uh safe against narrowing. You cannot you cannot implicitly convert from a more precise type to a less precise type because that will remove um information. Right? So I cannot implicitly go from nanconds to seconds without a duration cast because that is the me as as the programmer telling the compiler no I do want this loss of precision. It won't it won't automatically lose precision for you which is quite nice.
Ah let's just see what happens.
This looks awfully like my uniform code.
Yeah, error. Corner overload.
Oh, interesting. long long unsigned int I suppose it wouldn't would it so yeah sorry this count will give it to me as a size t or something like that so this wants to be a static cast float I could actually probably pass it as an integer in but I think that'll be fine failed. Chromatic aberation does not define the global function.
Oh, because it's fracked fracting sylons.
Uh, what am I looking at?
And amount is undefined. And a mount.
Uh, oh yeah, hang on. Let's show you around. What? Good spots.
Thank you.
Yeah, we'll get there in the end.
Is it weird to ask you about the current state of game industry and AI use ask? I don't know if I've got an answer for you. Is that I feel like it's just giving me lot weird banding.
It's quite low like a lowfi but it's not what I want.
M m.
It's not what I wanted. It's not what I wanted.
Right. I'm pretty sure he mentions stuff like this here. It's like in his article it's like also like if I pass it in every Yeah, I'm obviously going to want milliseconds, right? Because otherwise every second it's it's only going to update every second.
Yeah, I think I need to pass. Let's try that first.
Uh so let's get rid of this [ __ ] Uh and then go to renderer and then do this is quite nice cuz the duration cost. We can just change this to milliseconds.
I feel like the noise is now much bigger.
Oh, lovely.
Oh, that's not that's not horrible to look at.
And I would agree much worse. I like how it's also getting like these bands are getting narrower and then we're going to start getting like interference patterns.
All right. Okay. Let's let's debug this.
Let's have a look.
Uh right. How does one how does one how does one write code?
film grain. Yeah, I know. It looks like VHS grain though, right? Rand intensity.
Take the fract that was 10,000 times, which is not the number of milliseconds anyway, right?
Yeah. I Yeah. So I would I need times it by 10 times sign times the He adds the two coordinates together and multiplies them. But hang on mass uh brackets indices division multiplication has precedence over addition. So it's going to multiply the ycoordinate. I think there's missing brackets in there.
Yeah.
I do I want that.
You think that's not deliver? Yeah. I don't know why he passes. So, let's Okay, let's actually go through the article, right? Because this that's just an implementation. Blame. Yeah.
Wasting my evening. Float amount. Nailed it. Got that. Tick. Tick in the box. The amount controls how notable the film grain is. Crank it up for a snow picture. Sure. Sure. Sure. Sure. We got frame time. Then he has two rodons and then he has that. And then he does random intensity is 10,000 * x + y * that time 2 radians. Okay.
The snippet calc random just the amount.
So time since frame one, frame number four. So let's do frame time. So he has one tick per frame, right?
As part of Hannah 3D, the frame time is a time stamp of how many seconds have passed since the first frame. The example code used to animate the film grain as ocean will be be different each frame.
For static film grain, replace ocean with a large number. You may have to try different numbers to avoid seeing any patterns.
Both the X and the Y coordinates are used to create points or specs of film grain. If only X was used, there would only be vertical lines. Similarly, if only Y was used, there would also be horizontal lines. The reason multiplies one coordinate. The reason the snippet multiplies one coordinate by some number is to break up the diagonal symmetry.
Okay, you can of course remove the coordinate have a somewhat decent looking rain effect. Animate the rain effect.
Multiply the output of sign by that.
Play around with the x and y coordinates. Try and get the rain to change directions. No, no, no, no. Don't care.
Uh sign is used as a hashing function. The fragments coordinates are hashed to some output of sign. This has the nice property that no matter the input big or small, the output range is negative 1 to one.
Signs also use a pseudo random generator refract. Okay. Take a look at the first sequence of numbers and the second each sequence.
So while the output is it doesn't have much of a certain pattern. See, we were seeing something a little bit like this.
You can see the sign.
If you increase the sign output multiplier, you get less and less of a pattern. This is the reason the snippet multiplies sign by 10,000. Okay.
Also, hang on. Whoa. I think I actually I just want to use in UV, don't I? I don't want to I don't want to normalize this to the center of the screen like I've been doing for everything else. Right.
So, don't I want in UV? So, let's back up back up. Back it up. Back it up. Back it up.
So, I do want that because I want the thing to be broken up more. And I definitely I think I just want that.
I know I'm still passing milliseconds.
That might just make it go wild. We'll see what happens.
It's not too bad that that kind of is kind of interesting. So, if we just drop that down like a little bit.
Yeah, I think that's pretty cool.
I don't know if I like it now that I've seen it. It might actually be quite annoying, but it's there.
I think it might be too It might need to be more subtle. Like it might need to be like like it was before. Just like 0.1 just like really really subtle just to break up any like uh patterns that we have like banding that we have in the future.
It might be going too fast now. Should we should we try reverting that back to seconds then and see? No, it doesn't matter cuz he's just using it. He just wants a unique value every frame. It doesn't actually have anything to do with the rate of changes, right? Because he's sampling the he's using the UV core. So, I don't think actually makes any difference. But let's just let's just return that to seconds anyway. Just see if it makes a difference.
Oh yeah, I'll try. I mean, we probably should make this. This is still just like a demo, right? So, I just want to build out the rendering tech and get a feel for like the different techniques and stuff like that. I presumed if I was to ever make like an actual game, I would Oh, no. That's That's demonstrabably worse. Do not like that.
I can I can already see the patterns.
Yeah, it's got to be milliseconds, right? What is this? What is this [ __ ] Yeah, options at some point cuz you're going to want to do toggle like options such a pain, right? Cuz it's actually so much we'd have to do like you got to do different resolutions and full screen and windowed mode and key bindings and language support and like That's not the fun bit. This is This is the fun bit. Fun bit is adding little sliders.
That's I think the 0.1 is probably about right.
Don't talk about text rendering. Got to break out my proxy blanket.
Uh probably again optimization. I'm going to think about optimizing later.
I'm going just I'm kind of happy just to follow some tutorials and get stuff working.
Just Yeah, could do that. I know. This is looking pretty good. This is really coming together now. Like it's starting to feel like it's got a bit of a of a vibe to it as as the kids would say.
And great. Okay. Right. So, the next thing now is we got to work our way up to bloom, right? Because I think that's um Right, we need to we need to work our way up to bloom because that's the last process the last post-processing effect I want to do as part of this run of like streams is bloom.
But there's nothing we can really um No, I want to use the advanced warfare bloom, the one that does the 13 tap down sample and was it the nine tap up sample. Um but to that's the last processing doing this kind of run of streams, right? Then after that, I've got some more fun and interesting stuff to plan uh to do.
Sorry. Um, so after but in order to bloom, you need to kind of already have something bright in the scene. Like we have floatingoint buffers, but there's we could crank all the lights up, but I think the precursor to that is emissive materials. So this um asset pack that I purchased has some of the models have emissive materials. So they have a texture map which is like the bright points which are colored and then we can have for each we can make it as part of the entity that they have a um emissive scale. So we can basically render out the emissive data and then have a multiplier for it which will scale it up or down and probably like a global one as well. And then that will allow us to have like bright points on some of the models and then from that we'll have something to to bloom. Right. So bloom is where you just take the effectively you take the bright points and blur them and apply them back over the top and it looks like the the bright lights are bleeding into the kind of surrounding geometry. I don't know how this well this is going to work now that I think about it with the dynamic exposure although I guess that's applied after the light path. So that should be fine.
Um uh wasn't we going to use down from Balloon 2?
Yes.
Um uh Wednesday stream should still be on although actually not this Wednesday technically. Um I am I have a I have a prior engagement this Wednesday so I can that will not be on but the the Discord should be up to date. Let me check that and um they should all maybe I meant to cancel one and accident cancel them all because I don't really understand how computers work.
Okay.
So, let's So, for instance, I'm I'm pretty sure that the generator in the room to the left of our spawn point has an emissive material. Uh, and one of the doors, which I've not put in yet, does. So, uh, this here I think has like some lights around it, which obviously aren't rendered at the moment. So, the first thing we're going to do is just try and render out the emissive materials because that's going to be a whole bunch of like plumbing. And then from that, we need to add some dials so that we can turn them up and down. And then from that, we can then bloom because I don't really want to go to all the effort of adding bloom without knowing there is something in which to bloom. If that makes sense cuz how we know how we know if it's working or not.
So let's So there's quite a let's just check we got everything committed up right. So there's quite a bit of work to be doing for this. So let's let's jump into it. We're going to get as much done as we can now. So um render entity. Okay. I've already wired this in. So that's good. So render entity should already have the emissive texture bindless handle which should mean it is available to pass to the Oh, wait a minute. I should be able to see this. All right. Let's just let's take a step back and prove this. Right.
So, if I select this. Yeah. Okay. Fine.
This this these are the the three sub meshes that make up the generator. You can see here there's the albido, there's the uh compressed normal map, there's the metallic, the AO, which I think has been defaulted, the roughness, and then here, this is the emissive. So, it should have a blue light coming out of it. So, we need to wire that up first. And although it won't be bright, we should be able to see it first.
Um, now I I'm not a rendering expert in any of this, but I believe as I was doing some research and thinking about this, I think basically I don't want to have an emissive frame buffer that seems wasteful. My understanding is that emissive is basically light that doesn't go through any other lighting calculations. So I think I have to be wrong. I think I can just write that straight to the light path frame buffer right where all the lighting calculations go and then just change the blend mode to render everything on top of that.
So I think that prevent me having to have a whole separate frame buffer. I'll just reuse the one I've already got.
Let's let's give it a go. So, so we've got emissive texture bonus handle there.
So, I don't So, if we go to the GBuffer fragment shader.
So, this is currently not passed in, but let's give it a go. So, I need to pass this in, which means I'll then have access to it in the shader, which means I can then have another outpass, which will be the I'll need another out target, but the out target will be one that I've already pre-allocated.
Right. F3 R4 out emissive. To be honest, if I just call it out emissive, then it's a total disaster. I'll just create a new one and then bind it to this and then pass those in the light buffer. But I think it's worth having a little play around with.
Um, so FG missive. Uh, and then R4, R5, R6, R7.
Uh, G buffervert.
I'm hoping herand might uh, chime in.
Uh, oh, subs. Thank you.
Lavender de subscribe for three months.
Thank you very much.
Does anything I say make any sense?
Hello. I'm glad you're here.
Yeah. Can I just write the emissive value straight to the light path frame buffer and then just change the blending mode so that when I do when I execute the light path program, it just adds all the values on top of that with the lighting calculations.
So this will need uh this will need changing. So we need to have uh emissive bindus handle. So I need to change the object data for that. 0 1 2 3 4 5 6 7 and then this becomes out emissive bindless handle equals object data GL draw ID dot emissive buttons handle gh what is going on handle This is pretty big. It's It's a musive.
No, it won't be. It's a separate buffer.
It would be ideal not to defer it to its own separate paths. As in Yes. As in its own Wait a minute. Do we need it own separate frame buffer?
Like I don't want to write the emissive stuff out to us. I don't want to make my G buffer even fatter with a separate emissive color target. I'd rather just write it to the thing that I know I'm going to be writing all the lighting values to eventually anyway.
Whatever. Give it a go. I could be wrong indeed. Uh okay. So Gbuffer V frag. So we got all this now. So this then just becomes uh out emissive equals vec for texture sampler 2D in imusive text handle in UVRGB 1.0. I think that's right. Let's just wherever that's that's going somewhere, right? That is going somewhere.
That would be beneficial. Okay, fine.
Let's give it a go. I'm going to read that asand agrees with everything I've said.
Uh where where's the object data?
But this now needs a emissive texture hand index.
So renderer.
So renderer. Uh where's the glossiness?
So this is then going to it's where build the object. I want to get rid of all this as well. This is all I think this could be massively improved. Uh, E dot emissive texture bindless handle.
Uh, well, no, I'm using trunk build. So technically the version technically is GCC 17, but yes, I'm using the latest version of GCC, right? Okay. So, we're going to stick that in the emissive hole. Uh, and then I need to fuff around with all this passes. So, I don't want to clear this, right?
Because it's already going to have data in it. I need to clear it here. I don't want to bind it. Can I just g frame buffer? Is there like a gio clear?
Here we go. What's this? What's this?
It's a home gear named frame buffer.
So what the what the J.
So frame buffer be the thing I want.
What's what specify the buffer to clear?
Is that going to be like ah GL color? So I can clear the given a frame buffer and a color and and a buffer type. So the color I can clear it glint. So it's my particular buffer draw buff to clear.
What's draw buffer?
Have I even got that mapped? Can I do GL clear?
Right. Okay. You know what time it is?
So puffy glare named frame buffer FI or FB.
I think I want FV.
GL clear named frame buffer FV.
I think yes, I think there are some goodies to have at the end of the stream if you hang around. Right. So now can I do glare named frame buffer FV and I want to pass in the light buffer RT dot frame buffer dot native handle. Sure bit mouthful we'll get there. Then gl color. Wrong spelling but I'll I won't split hairs. What the hell is What? What is this? Draw buffer buffer and draw buffer. Identify the buffer to clear. So why is it there?
Oh, is it is it if it has multiple buffers attached GL draw buffer zero and then I want the clear values. So that's going to be uh const static con x con x uh static conra uh what's values and floats datic con auto clear color equals sto array blow boot for you.
Uh I think that was just default initialize them. All right. And then I can do uh clear color dot data.
It's the ICE geo draw buffer. If you're writing to multiple frame buffers in the same shader. Oh, I am.
But hang on. What? I don't I don't understand why I need a This is But this is all DSA, right? Like this doesn't matter. I've just bound this. Sorry.
I've just used this named handle. I haven't bound it. So why do I need to know which I'm obviously misunderstanding the concept here. Why does this care about what program I found if I'm just issuing a clear here?
Oh, I see. I got you. I got you. I got you. Okay, fine. Which case, I only have one, right? Yes, I only have one attached to the frame buffer, so that's fine. Got you, I think.
Okay. So, that should clear it. And then I need to do uh Yes, yes, yes. Sorry, I didn't I was mis I was was being stupid.
Okay, so that should work. So, then the light pass. I think the only thing we need to do here is before we issue the draw call, I think we need to do GL enable uh GL blend.
Uh GL blend. Is it funk?
I what's is it G1 GL1 where you write where you just preserve what's below it and then GL disable GL blend.
Let's give it a go. I don't know if I do I have to worry about the depth buffer when I'm doing that or is that kind of already taken care of?
Oh, actually, nope. No, no, no. Not finished wiring all this up yet, have I?
So, this needs G buffer frag now need actually no is that that will work on it I've not changed I've not added any uniforms have I yeah that's fine it's unhappy draw buffer is negative or exceeds the maximum number of supported draw buffers. Interesting. That seems like my mistake.
Uh I could just bind it and clear it. Like it's not ideal, but like is it expecting?
Oh, you're right. It is.
Well done.
Passing I as draw buffer. Yes. Well done.
Literal zero.
Nailed it.
This got the fog.
Certainly not done what I thought it was going to do. Right. Let's go back and debug all this step by step.
Uh so out emissive bind handle takes the emissive bindance handle from the object which we pretty sure we've already passed through. So that's fine.
Uh Gbuffer frag has now the in handle for that and then an out.
Oh, I don't think I bind this.
I don't remember changing anything around that.
Uh, where do you bind all the gubbins for the How does it know?
Ah, here we go. Need to just bump this up. So this can now have another output find this handle. Is that is that is that right?
No, this isn't something's not right here.
How do I repurpose another?
So, hang on. When we create when we create a render target, we say how many color attachments it's going to have, right?
But then I I create them here.
Yes, this this creates them.
But I want to reuse an existing one.
This might not fit in with my current architecture.
I might be right. Let's keep it simple, right? Let's keep it simple. Uh, let's just create a new Let's create a new T cuz I want to compress down all the render targets. Uh I want to redo all the formats for all the render targets as a future optimization part. So for now let's just create a new one because it is easier.
So let's do where do we create the Gbuffer one? So Gbuffer target five doesn't feel right. Why is that that right?
One, two, three. Yeah, five. Okay, fine.
So, let's add another one. Yeah, all these can be compressed, downloaded.
Like you can throw you can reconstruct position. Um, I think we can package specular into the color one. There's a whole bunch of stuff we can do. So, let's let's just keep that as is. So, that's going to write out to that.
That's fine. So then the the light path fragment shader is now going to need to take in another one. So this will now take in the emissive.
Uh, and then I think I just want to just do result plus equals texture.
Two S is emissive. Okay, fine.
Uh, emissive texture in UV. All right. I think I just want to slap that on there.
Is that going to blend them together?
I think.
Don't I want to Hang on.
I think that's fine. I think that's fine. Uh, and then back to renderer. We basically now want to undo all the gubbins we just did.
So, this can go. This can go. This can go.
And then uh bring this back for the light pass.
So set that there.
Do all this. And then this is going to have set uniforms the other render texture. Right. I think something like that.
Oh, I've still got the blend enabled.
You're right. Uh, blend. Get rid of this. Get this. Get this. Get this. Get this. All right.
light pass program failed to link fun light. What have I changed?
I added that and that.
Does it need to be inverted? I don't think so.
No.
It's not like a limit to how many I can have, is there? But I expect that to fail to compile rather than fail to link.
That's very strange that it's not linking.
It's definitely light pass, isn't it?
All right. What's that?
That was intended.
No, this doesn't like it. Let's just It's not a runtime error. It's not like it's the universal. I can't Why it won't Oh, how weird. Why is it not like this?
Unless that does this need to be RGB.
Yeah. Okay.
Uh is that is that blue?
Was that there before?
It does look different, doesn't it? I think maybe that as well.
Yeah. Okay, that's I need to add an emissive like multiplier as well.
Uh I don't know. I I'm not convinced.
Are they just Were they they now just brighter?
What I need to do is uh the easiest way for us to see this is to properly wire in an emissive scaler into the material. So let's do let's do render entity.
Uh let's do uh is this going to be part of the whole this part of the entity itself?
Uh I think yeah I don't want to change it per like sub mesh. I just want the whole thing to have the concept of a float uh emissive uh scalar power factor amount strength.
Shouldn't I multiply?
No, because the you clear the scaler, sorry, the emissive texture. So where the where there is no emissive material be black, which means you multiply by 0 0. So you would then only get the emissive part of the data. I think you want to add them unless you mix them based on the alpha channel.
I think we might want like once this was working, we might want like a global emissive strength which over which is combined with the per entity one cuz it' be kind of cool if something happened and all the bright lights like flickered at once and we could do that by just having a globe. just turning the global emissive scale like zero and then one.
That would be cool.
Uh and then this I guess is going to have to be in the description which means oh that means all entire scene file is going to crap out.
I might add that in a minute. I just want to just see if I can get this working first. Let's assume if you create one here and this is strength. Let's just make that 1.0.
Um, right. So, you should always get that back, which is fine. So let's go to debug render and go to the inspector and then entity. So if we go the entity, let's do uh here basically want to pinch one of these other ones.
Where do I have like a float? Oh my goodness, I hate this so much. Uh, inspector after the entity name, we'll put this here. And then we'll have a uh value is uh entity emiss strengths.
Uh you missed an R and yeah almost certainly uh strengths value equals 0.0F to 10.0F.
Uh and then All right. Hang on. Going back. Going back. Where's I?
Yeah, I did.
And actually, I'm going to want the ability to set that as well because this is now mutable information about the entity.
Set float strengths. Uh that will not be const.
And then this will be uh that'll be void. And then we'll do emissive trunks equals emissive trunks. Uh, nope.
Uh, strength.
Uh, okay. Fine. And that's now all wrong cuz everything is terrible.
Set load strengths dx FF void. Okay. Right.
Okay, so now we're getting somewhere. So now we can go back to debug renderer and then when this is right, we can do uh entity set emissive strengths value. Okay.
Uh so now the last thing buffer pass. So this now let's go back to Gbuffer vertex. Uh sorry G might to pass this in through here.
I guess it's part of the object data, isn't it? So, we have to do float emissive string. Oh, I think that's still going to be aligned. I think that's still be aligned.
And then out flat. Nope. Close float uh out.
emissive trunks. And then we can do out emissive trunks equals object data. G. I wonder if you just passing the drawer ID over into the uh into the fragment shader and having it pull all this data out.
9761 changes.
Uh in where in the debug renderer there's not that many files with that many uh lines of code in oh okay fine just distracting me now g buff frag. So then this will have a location sh uh did I not change it in the other one? Okay fine. uh in flat flat a flat float in emissive strengths.
Uh this will become forive sample 2D times uh in Mrs. strengths.
Uh, and then back to Gbuffer but um eight. Oh my goodness, so much boiler plate. Uh, and then over to renderer object data should now technically be unhappy, which it is not.
Emissive.
Oh, have I not added it into this? Ah, interesting. Okay, fine. Over here. So this is now going to have to have a float emissive strongs.
Go back here. This should now be unhappy. So we do dot hello.
Uh I told you float float, not flat float. Okay, thank you. Let's just fix that while I'm here. Was that in?
Oh, yes. Thank you.
That right. Uh renderer. Right now it's unhappy. So now we can do dot emissive strength equals uh e dot emissive strength. I feel like there must be a better way of I'm basically taking every entity. Oh, those render entities.
So, it now needs to be entity dot.
That's fine.
All right, let's see what happens.
God, floor typing very quickly.
Uh, failed to compile shader G buffer fragment shader error location 8 component zero already used. See what what do you mean location composer is already used.
Anyone want to see my mistake?
Don't understand.
Is it going give me a line number line 12?
I'm pretty sure I did save the file and it's specifically just compiling the fragment shader. So, it's got no knowledge of the vertex shader at this point because it's before link time.
Have I got a limit? Is there any Is there like weird 7 7599.
That's a new one to me. 759 0 1 2 3 4 5 6 7 8 like I don't I mean I could just pass an index a flat index over and then index it again on the fragment side. It might be easier than shoving all the data across.
It's in the shader. What is in the shader?
I don't know. The flats here is fine, right? Oh, you saying all the flats have to be together? I don't think so.
What a weird error.
Uh yeah, cuz I don't want it inter I don't want the emissive strength to be interpolated across uh across vertices right because if it's not uh I can struggle quite a while before asking them also I can struggle more online live because I think it's more interesting personal projects and stuff then I probably like I use I use LMS as a glorified Google anyway right I tend to ask I ask Gemini probably more often than I Google things now but online sorry um Five. Part of the process is like debugging, right?
Does it need to be flat?
What's the error again?
We've got failed to compile shader.
Gbuffer fragment shader error location 8 component zero already used.
Mistake resubbing. Thank you very much.
I'd really like to get a miss materials wired up tonight. I think that' be a really good place to stop because that means like next stream we can just hit um Bloom head on.
I really don't understand this.
I mean, it doesn't technically need to be flat because isn't it going to be the same for every vertex? Like, there's no varying in it. So, maybe I we could try it without It still doesn't like it.
Location 8 already used.
Yeah, I guess that is true.
The flat means it doesn't interpolate it across vertices. So normally when you pass in when the vertex shader passes data to the fragment shader um it will you set the vertex shaders run per vertex, right? But the fragment shaders run per fragment per pixel. So it will smoothly interpolate whatever value you give it between two vertices as it's rendering them. This is how you get the classic colored triangle, right? When you first render when you do your first OpenGL program and you you set a color at each vertex, it automatically interpolates the colors between them. A flat means just use the same value for each vertex.
You had a second flat in out.
I may have to ask the oracle.
my my gut feeling is that uh uh there is some sort of limit that I'm not aware of.
The oracle just says you've already you put something in this slot which seems rude and also wrong.
There is no like look.
Oh, Matt 3 takes up more than one slot.
Oh, interesting. Interesting. How many slots does it take up?
Uh, OpenGL.
OpenGL. Yes. Uh, three. Uh, out slot.
How many Float Falls being the one true unit.
Interesting. Okay, so how many how many how many locations does it take up?
Takes up four slots. Okay, so I need to do 7 8 9 10.
Hang on. 7 7 8 9 10. So this needs to be 11.
Wow, hate it.
that message should be 10.
Can I not count?
7 8 9 10. I'm at three. Yes, you're right.
I suppose it shouldn't actually matter, but let's Okay.
Why is that? I've got the wrong scale.
Hang on. I fix that.
Yeah. Like a like a a layout slot is a conceptual thing, right? It's just an index. It's like here is here is how you tie up the thing I've written from this one and here's how you tie up to the other end. The fact that they have size like implicit size information is really frustrating.
Okay.
Okay. Nice. So there's this definitely has now some sort of emissiveness to it.
which is cool.
Uh, what else has emissive textures? I don't think a lot of other things do. I think this pack is quite low on the old emissiveness.
So, let's just switch the fog off for a second.
Uh, right.
I add I think one of the doors has it if I remember correctly when I was looking at these. Like door one.
Door two.
Yeah, this has some sort of emissiveness. Which which side is it on?
Okay. Uh, not what I was expecting, but sure.
Okay. It's definitely got some emissive thing here. Why is this not Why is this Why is this all over here as well? What's going on?
Oh, this might be I wonder if this is some sort of transparent thing that I don't support.
Um, right. Well, we got something to start play around with.
Yeah.
Uh, I need to find some more emissive stuff. I think some of the weapon like the weapon pack I bought is quissive, which is quite cool because then it' be something you see a lot because it'll be on you.
Um, okay, cool. Right, that feels like a commit. I think the only thing I'm missing is it's the emissive value being written to the YAML file, but I'll sort that later. Uh, so much changed. So much changed.
really should have done this as smaller commits.
Uh I don't need that new function anymore, do I? Give it that.
Okay, let's do that much of a choice but to probably just do this as a couple of grim commits. So add emissive to immiss emissive to shaders.
See wire uh sorry wire up emissive to renderer three right four so we on stream 32 the githole right I'll start off the free goodies.
It doesn't pop up on the new on my new notification bar and I looked at the settings earlier and it should do. So, I don't know what's going on there, but on TW I think you should see it on the YouTube chat anyway. Uh, five rando premium gifts months. get access to videos and I'm hoping this should there's a video I try and aim for a video every month and I'm working on this month's video. So hopefully if I have enough time I will get it in in the the month that we are in um before everyone disappears and scatters to the wind for other better things to do with their evening. Uh one, thank you for spending some time with me. I've very much appreciated it. Uh two, uh I think we got some good stuff done today. Like we added some extra effects. It's all starting to come together now. You know, it feels like it's got a bit of an atmosphere to it, which is nice. Um, next stream. So, I'm not streaming this Wednesday for I am busy, but I think I'm back the following Sunday.
Keep an eye on Discord because that is when the stream schedule is. It's the master list, the golden truth. Um, what was I going to say? Next stream we shall we shall bloom. That'll be I think that'll be the first thing we need to do. We'll just I'm gonna pull up the There's an article for it. Uh Twitch schedule is wrong for sure. Okay.
So much admin to do.
Um I will try and remember to have a look at those. Um yeah, we're going to bloom. And I think once we get that a nice little soft blur on some of the highlights, um I think I think that'll be it for post-processing.
After that, I want to do some profiling.
I want to track memory usage. I want to track GPU memory usage. I want to maybe even do some thread profiling. Um, so I think there's a couple of streams of like fun low-level stuff to do there.
And then um you know I try to avoid internet drama um only because like I don't know there's already enough going on in my life but maybe um but I'm sure I'll see it on Reddit at some point. Um, new GPU from VSync. Is you spelling? No.
The what I want to do is I want to track CPU memory usage, GPU memory usage, and is it the what's the OpenGL?
Um, there's like GM OpenGL timer or something, isn't there? Query performance GL query something or other.
Um, I want to just know roughly how long the GPU is taking per pass. Uh, I think I can. Isn't Isn't there just an OpenGL function I can call for that? Like, can't I insert like a a timing instruction into the pipeline?
Um, unless that's what you're talking about.
It will take close to Vync timings DV, I think. And then like almost regardless of how good the data out is, I think it'd be an interesting experience to kind of go through because I've never done that kind of OpenGL stuff before. You know, we'll build out some tooling. Um, yeah, that's it. Query counter time elapsed. I think that's it. I I'll do some research.
But anyway, I think it' be fun to do like some stuff I've never done before.
We'll figure it out live. Build out a profiling tab in MGUI so we can kind of see how much memory we've allocated.
Might set some kind of like upper limit budgets and like some bars so we can kind of see how close we're getting. Um yeah, I think I think it should be fun.
Like it should be fun, right? Be fun fun.
Um and then after all that's done, I will probably look at all the data and go cool. I'm not profile. not optimizing it now um is fast enough. Uh and then proceed to ignore it. But at least we would have spent a few streams building it out. Um other than that, well then we can then go on to Jolt.
Other than that, thank you all for hanging out with me. I hope you enjoy the rest of your day and I will see you all on
Vidéos Similaires
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 views•2026-06-01











