26/03/2023 [Pinned]

A place for Studies and Rambles.

Hello! This is my talky place. I'm gonna (hopefully) write things about graphics and modelling in video games and put 'em here.
In the meantime, enjoy some more maxwell.


20/06/2023

CoreToon, my own toon shader!

I made my own toon shader!
It was mostly inspired by Breath of the Wild and was designed to work with the standard PBR Metal/Rough workflow.

I based it off of MinionsArt's toon shader and added my own specular reflections, support for normalmaps, emission maps and metallics.
Speaking of metallics- those are done with a matcap. It's as shrimple as that. I also added a quick and kinda janky option for hatched specular highlights, but it doesn't look great right now.

I'm not going to go into how everything works, just because I've been working on it all day and I'm tired. Maybe some other day I will.

The TL;DR:
a lot of blending and some dot products here and there. I'm sure you can fill in the gaps yourself :3

Anyways, here's what it looks like:

> savage lynel crusher model belongs to nintendo

kinda good ngl.


Download the shader here [URP, BiRP rewrite not planned for now.]:
coreToon_toonSurface.zip


30/05/2023

[No Spoilers] Neat graphical trick(s) in Tears of the Kingdom.

Like the rest of the internet, I'm playing a lot of The Legend of Zelda Tears of the Kingdom.
I noticed a neat little trick used for mesh/grid surfaces to save polygons that's used in plenty of shrines and at least one of the dungeons.

Say you have a catwalk with a see-through mesh texture on the floor. You obviously don't want to model every single hole of that mesh.
The obvious solution is a flat plane with alpha-cutout. But with that you lose all possible depth in that texture, maybe besides a normalmap.

The artists working on Tears of the Kingdom used a clever technique to use cutout but still keep some depth: They simply stacked multiple planes on top of each other.

I then noticed an even more clever use of this method to simply save polygons on a big plate. It just looks like a solid modeled object, doesn't it? :O

Well, look closely. There's the same layer lines as that catwalk!


Replicating the effect:

This is quite straightforward. Model a lowpoly version with a few planes stacked on top of each other, model a highpoly version with all the fancy branches as geometry, render the resulting shape as an alpha texture and apply it to the lowpoly model. Or just draw the alpha texture by hand!
To improve lighting around the edges, create a normalmap by using the alpha texture as a heightmap.

The results:

It's almost indistinguishable in motion and the illusion only breaks close-up. This method also allows for fancier shapes that you couldn't feasibly model with geometry!
If you're developing games for a smaller handheld system like Mobile Phones or the Nintendo Switch, this could be a nice trick to keep in your toolbox.


01/05/2023

Where I've been.

I'm alive! And I'm feeling better than ever. I'm just really busy with a bunch of projects and I want to commit to a biggie:
Making a full game.
I'm making good progress, and maybe I'll get some models and a blogpost or two to showcase from it. I'll talk more about what I'm working on when it's more fleshed out. My knowledge of c# has improved a lot and I'm soaking up more knowledge about game art like a goddamn sponge. I'm gonna pull at least one friend into the boat as well and I really hope we can make this project work together. I'm sure it'll be a fun journey. <3


27/03/2023

Making a mud shader.

Soooooo... I've been playing a lot of Red Dead Redemption 2 recently.
The game (thanks to the amazing graphics and story) is absolutely stunning, but there's one thing in particular that captivated me:
mud and puddles.

A convincing mud or puddle effect has been something I wanted to do for a while now, so my first thought to achieve that kind of effect was using the roughness and basecolor maps to add puddles. But it's not quite that easy.

My goal with this mini-project isn't to craft an intricate mud-simulation system with displacement- and footstep-maps like RDR2's.
Instead, I want to make a still somewhat simple shader that can render a layer of water on top of a surface without transparency.
I'm going to use the Unity URP and create the shader in Shadergraph.

My initial approach/thought is to have a separate 'mud' map that affects the heightmap, roughness and basecolor depending on viewing angle, which can be achieved with a fresnel node and some math.
For assets I'm going to use this ground texture from AmbientCG.

The first step is - of course - just to set up a basic URP lit shader. I chose to also add some Parallax Occlusion Mapping for extra fanciness™.

Sigh... first roadblock. The Parallax Occlusion Mapping Node in URP Shadergraph only accepts T2 inputs. Blend Nodes (for blending the puddle map and the heightmap) output Out(4).

> it no worky.

So instead, I'm going to use the Unity HDRP with Tesselation.
I know I said it wouldn't have displacement mapping, but fuck it we ball (and tesselate).
I won't document the entire process of getting the shadergraph to work as that was enough of a headache alone, but I'll give some Insights.

I (again) started off with a simple Lit shader, then hooked up all the textures to the fragment outputs and checking what they look like.
Next, I started working on the math to blend the heightmap and mudmap. Screening the mudmap over height, then subtracting the mudmap from the result gave me what I needed.

> it's getting cursed already

Next, I had to actually learn how tesselation in shadergraph works. It was easy enough, just a 'quality' value going into Tesselation Factor plus a NormalVector multiplied with 'amplitude' and the freshly blended heightmap going into Tesselation Displacement.

The rest was just figuring out more blending. It's simpler to imagine than to implement. So here's the main parts that make the effect work:
> The mudmap determines where water pools and where it doesn't. black = dry, white = water.
> Water flattens out the normalmap. This is done by changing the mudmap from black/white to white/blue, then multiplying it with the main normalmap.
> Water also has a smoothness of 1.0, but it gets rougher (=more transparent because it's less reflective) when viewed head-on. This is done by multiplying the mudmap with a fresnel node and adding it to the main roughness map.

That's basically all the shader does. I only added some extra parameters to tweak the water level and how hard the waterline should be. That's all done with a power and a contrast node.

"But why not just make the heightmap manually and not have to worry about blending at runtime?" I hear you ask.
The answer is simple: because I fuckin' can.
The less simple answer is that I wanted the shader to be dynamic and for the puddles to be easily editable. That allows me to quickly change out textures and do dumb stuff with it, all within Unity.

> just doin' research™.

Back to what I was saying.
2 coffees and a headache later, here it is.

> it ain't pretty, but it sure works.

A little organizing doesn't hurt (anyone besides me), so I might as well. brb.

> ahhh, that's better.

Alright! So what does it actually look like? It's about time I show the results.
It may not be as perfect as RDR2's mud and dirt, and with extreme tesselation it may not be the nicest to your GPU, but it still looks real good.

> wowee. that sure is water!

And a little animation to show off the reflections and parameters:

> reflections, waterlevel, waterline, wetness

> material inputs and parameters to allow various materials

Download the shader here [UNOPTIMIZED, HDRP ONLY]:
YASU3D_MudShader.shadergraph

if you'd like to create mudmaps, here's some tips:
> invert an AO map and increase brightness+contrast for a quick and dirty mudmap of pavement.
> puddles can easily be painted or generated with blurred noise/gradient noise.
> mudmaps should be slightly soft/blurry, greyscale and range from 0 - 255.

Final verdict:
I like mud.

this website does not support your current resolution.

> this message will appear if your browser window is too thin or your phone is too small.