How I built a realistic grass shader in UE5! Shader driven bend, clump, tilt, wind and more!

Ghislain Girardot
29 Feb 202443:51

Summary

TLDRIn this comprehensive video, the creator shares an in-depth guide on crafting realistic animated grass using Blender and Unreal Engine. The tutorial builds upon a previous video that introduced a 2D wind system and grass animation techniques. Here, the focus shifts to advanced methods for achieving a natural and fluffy appearance in animated grass. The artist is inspired by the grass rendering in 'Ghost of Tsushima' and explores the potential of world position offset for creating dynamic grass features. The video delves into intricate details, such as reconstructing world positions, applying instance scaling, and utilizing vertex normals for random 2D directions. It also covers the creation of a clump map for added realism and the application of various shaders and techniques to manipulate the grass's appearance based on environmental factors like wind and landscape. The summary also touches on the challenges and solutions related to normal mapping and the importance of managing vertex count and LODs for performance optimization. The creator concludes by teasing upcoming content on foliage asset creation in Blender and the development of a related Blender addon.

Takeaways

  • 🌱 The video is a tutorial on creating realistic animated grass using Blender and Unreal Engine, focusing on techniques for natural and fluffy animations.
  • 🎨 The creator used Niagara to build a 2D wind system and dynamically generate a tiling wind texture, as well as animating grass and achieving a spherical projection trick.
  • 📐 The grass mesh is non-traditional, with flat cards oriented towards the positive x-axis, and utilizes UV mapping for texturing and baking pivots, height, and random values for variation.
  • 🌿 World Position Offset (WPO) is central to achieving the grass features, with the idea of controlling features and their randomization for a more natural look.
  • 🤔 The video explores the Ghost of Tsushima game's grass rendering as inspiration, despite not having the same level of UI and rendering pipeline knowledge.
  • 💡 A key technique involves reconstructing world position from scratch and converting it to an offset, which simplifies vertex manipulation for the grass.
  • 🔄 The use of a 3x3 matrix to rotate each grass card randomly around the z-axis allows for more control and leads to more natural-looking grass.
  • 🌬️ Wind effects are integrated into the grass animation, with the wind direction influencing how much the grass cards tilt, simulating a 'sail' effect.
  • 🌄 A clump map is created to define areas where grass clumps together, adding to the natural and chaotic look of the grass field.
  • 🎭 The grass shader includes features for controlling the scale, bend, and orientation of the grass, with texture maps used to randomize these features.
  • 📉 The video discusses the importance of managing the vertex count and level of detail (LOD) to maintain performance, especially when using complex shaders and effects.

Q & A

  • What is the main focus of the video series?

    -The video series focuses on explaining how to create realistic-looking grass using Blender and Unreal Engine, with a particular emphasis on techniques for animating and rendering the grass.

  • What was covered in the first video of the series?

    -The first video covered the use of Niagara to build a 2D wind system, dynamically generating a tiling wind texture, and a simple way to animate grass using the texture. It also demonstrated a spherical normal projection trick.

  • What are some of the cool tricks showcased in the second video?

    -The second video showcases various tricks to create natural and fluffy looking animated grass, including using World Position Offset for grass mesh features, orientation, and control over these features' randomization.

  • How does the grass mesh used in the video differ from typical grass meshes?

    -The grass mesh used in the video has flat cards that are purposely undeformed and oriented towards the positive x-axis, which is not typical for grass meshes. This unique design allows for more control over the grass's appearance and behavior.

  • What is the purpose of using a 3x3 Matrix for rotating cards?

    -The 3x3 Matrix is used to rotate each card around three axes, allowing for more complex and natural-looking rotations. This method also enables the creation of cool effects, such as random rotations and aligning cards with the landscape normal.

  • How does the video approach wind animation for the grass?

    -The video uses a combination of wind direction from a texture and the direction each card is facing to modulate how much wind is applied. This creates a more natural response to wind, with grass blades acting somewhat like sails.

  • What is the significance of using a Clump Map in the grass shader?

    -The Clump Map is used to create clusters of grass, adding more randomness and a natural look to the grass field. It influences the position and tilt of the grass cards, contributing to the overall visual complexity and realism.

  • How does the video address the issue of perceived grass density?

    -The video discusses the use of Billboards or camera-facing cards to maximize pixel coverage and improve perceived grass density. It also explores techniques like pixel depth offsetting to give the illusion of depth in the grass.

  • What is the role of the landscape layer capture tool mentioned in the video?

    -The landscape layer capture tool is used to bake the painted landscape grass layer into a texture, which can then be projected in world space in the grass shader. This helps to create a smooth transition between grass and other layers like dirt.

  • How does the video handle the challenge of normal reconstruction for the grass?

    -The video describes a process of rebuilding a world space normal from scratch due to the complexities introduced by vertex offsetting and encoding a random direction in normals. It uses various techniques, including a Lerp function and a cheat method of luring the normal towards the tilt direction.

  • What are some performance considerations mentioned in the video for rendering grass?

    -The video emphasizes the importance of keeping the vertex count under control, being aggressive with LODs (Level of Detail), and minimizing quad overdraw to maintain decent performance with a large amount of grass instances.

Outlines

00:00

🎨 Creating Realistic Animated Grass with Blender and Unreal Engine

This paragraph introduces the video as the second part of a three-part series. The creator discusses using Blender and Unreal Engine to make realistic animated grass. They recap the first video, where they used Niagara to create a 2D wind system and animate grass, and mention the Ghost of Tsushima game as an inspiration. The focus is on using world position offset to control grass features and orientation for a more natural look.

05:01

🌟 Advanced Techniques for Rendering Grass

The creator references an earlier video on industry-grade techniques for rendering grass and suggests viewers watch it for context. They then delve into the specifics of their grass mesh, which is atypical with flat cards oriented towards the positive x-axis. They discuss using UV mapping for textures, baking pivots and height into UVs, and random values for variation. The paragraph concludes with the idea of using world position offset tricks to achieve a natural grass appearance.

10:02

🤔 Exploring World Position Offset for Grass Features

The paragraph details the process of using world position offset to manipulate the grass mesh. It covers reconstructing world position, applying local position, and using baked pivots to center cards. The creator also discusses scaling, rotating, and offsetting the cards using various techniques. They touch on using instance position in world space and interpolating between positions to control card spread. The paragraph concludes with the challenge of rotating cards while maintaining their natural appearance.

15:03

🎲 Utilizing 3x3 Matrix for Card Rotation and Clumping

The creator explains using a 3x3 matrix to rotate each grass card randomly around the z-axis. They discuss generating a random 2D direction and using vertex normals to store this information. The paragraph also covers using action scripts and geometry scripting for processing the grass cards and ensuring consistent random directions across all LODs. The focus then shifts to creating clumps in the grass, using a custom tool in Unreal Engine to generate a clump map that adds to the grass's final appearance.

20:04

🌬️ Grass Clumping and Wind Interaction

This paragraph focuses on how the grass clumps are influenced by the wind and the landscape. The creator discusses using a lerp to control the grass's tilt according to the landscape normal and a texture to randomize the clump effect. They also explain how the wind texture's airflow vector can be used to modulate the wind effect on the grass, making it act like a sail. The paragraph concludes with the idea of using mathematical approaches to achieve a resting pose for the grass cards.

25:05

🌱 Maximizing Pixel Coverage with Camera-Facing Techniques

The creator discusses methods to maximize pixel coverage of the grass, such as using billboards or camera-facing cards. They explore different techniques to achieve a natural look while maintaining performance, including using view space and camera space for shadow passes. The paragraph also covers the use of a shadow pass switch node for creative effects and the importance of managing vertex processing to avoid unnecessary costs.

30:06

🎨 Final Touches and Normal Reconstruction for Realistic Grass

The paragraph details the final steps in creating the grass shader, including handling normals for both stylized and realistic rendering. The creator discusses the challenges of reconstructing world space normals from scratch and the decision to use a forward normal with a slight shift toward Z. They also cover the use of mip maps for opacity control, the application of a normal map in world space, and the importance of managing the vertex count and LODs for performance.

35:08

🛠️ Shader Optimization and Future Workflow

The creator summarizes the shader's components, including base color, roughness, specular, and opacity mask. They discuss configuring the two-sided foliage shader and the importance of keeping the vertex count low for performance. The paragraph concludes with the creator's reflections on the project, their decision not to use nanite or virtual shadow maps, and a teaser for the upcoming third video on creating foliage assets in Blender.

Mindmap

Keywords

💡World Position Offset

World Position Offset is a technique used in 3D graphics to displace or offset the vertices of a mesh from their original positions based on their world coordinates. In the video, it is used creatively to achieve natural-looking grass animation by controlling the orientation and features of the grass mesh. The script mentions 'World position offset tricks' as a central theme in creating the grass effect.

💡Niagara

Niagara is a visual scripting system used in Unreal Engine for creating particle systems, effects, and other dynamic behaviors. The video references using Niagara to build a 2D wind system, which dynamically generates a tiling wind texture for the grass, contributing to the realistic animation.

💡Vertex Normals

Vertex normals are vectors that determine the direction in which a surface is facing. They are crucial for determining how a 3D model is lit and shaded. In the context of the video, vertex normals are used to store a random 2D direction for each grass card, allowing for random rotation and orientation of the grass blades.

💡3x3 Matrix

A 3x3 Matrix is a two-dimensional array of numbers, often used in computer graphics to represent transformations such as rotation, scaling, and shearing. The script discusses constructing three axes and using a 3x3 Matrix to rotate each grass card, which is a key technique for achieving varied and natural-looking grass orientations.

💡Clump Map

A Clump Map is a texture or a procedural method used to define areas where objects, such as grass blades, clump together. In the video, the creator generates a Clump Map to add randomness and clumping to the grass, enhancing the natural appearance by using a noise texture to influence the orientation and positioning of the grass blades.

💡Billboards and Camera-Facing Cards

Billboards and camera-facing cards are techniques used in 3D graphics to make objects always face the viewer or the camera. The video discusses using these techniques to maximize pixel coverage and create the illusion of denser grass, which is essential for the grass to look natural from various viewing angles.

💡Subsurface Scattering

Subsurface scattering is a shading technique that simulates the way light penetrates and scatters beneath a surface, which is particularly useful for creating realistic skin, leaves, or grass. The script touches on using subsurface scattering or a two-sided foliage shading model to achieve more realistic lighting on the grass.

💡Mipmaps

Mipmaps are pre-computed, downscaled textures that are used to optimize rendering at a distance. They are used to reduce visual detail as the viewer moves away from an object. The video script describes manually tweaking mipmaps to control the grass's transparency and shadow appearance at various distances.

💡Vertex Shader and Pixel Shader

Vertex Shader and Pixel Shader are types of shaders used in 3D graphics. A vertex shader operates on the vertices of a model, while a pixel shader operates on the pixels rendered on the screen. The script mentions the complexity of the vertex shader when dealing with the grass, which is responsible for much of the computational cost.

💡LOD (Level of Detail)

LOD refers to the technique of displaying a simplified version of a 3D model as the camera moves further away from it. This helps optimize performance by reducing the number of polygons rendered at a distance. The video emphasizes the importance of aggressive LOD management to maintain performance while using detailed grass models.

💡Shadow Pass

A shadow pass is a rendering pass used to determine which parts of a scene are in shadow. The script discusses using a shadow pass switch node to manipulate the appearance of the grass during shadow rendering, such as making the grass appear completely opaque to increase shadow coverage and enhance the sense of density.

Highlights

The video is a part of a three-part series focusing on creating realistic animated grass using Blender and Unreal Engine.

The presenter used Niagara to build a 2D wind system and dynamically generate a tiling wind texture in the first video of the series.

A simple method to animate grass using a texture and achieve spherical projection trick is showcased.

The video dives into advanced techniques to create natural and fluffy looking animated grass.

The Ghost of Tsushima game's grass rendering inspired the presenter to experiment with world position offset.

A custom grass mesh with flat cards oriented towards the positive x-axis was used for the tutorial.

The presenter used a UV map for grass textures and baked pivots, height, and random values into the UV space for more control.

World position offset tricks are employed to control grass mesh features such as band orientation.

A per-instance fade amount node is used to frame cards at a distance and smooth instance distance fading.

Instance scale is controlled using the Z component of a vector transformed from local to world space.

A 3x3 matrix is used to rotate each grass card randomly around the Z-axis using vertex normals for a random 2D direction.

The landscape normal is used to orient instances, allowing grass to match the landscape orientation.

A clump map is created to influence the tilt and position of grass cards, adding to the natural look.

The wind direction is used to modulate how much wind affects each grass card, creating a more dynamic animation.

A mathematical approach is taken to bend the grass cards into a resting pose, using sine and cosine functions.

Billboards or camera-facing cards are discussed as a method to maximize pixel coverage and perceived grass density.

Desert LODs are used for a smoother level of detail transition at a distance, despite the extra cost.

The presenter discusses the use of shadow pass switch nodes for creative shadow effects and performance optimization.

The video concludes with a discussion on the trade-offs between using world position offsets and the potential performance costs.

Transcripts

play00:07

hey what's up YouTube this is the second

play00:09

video of this three-part Series where I

play00:11

explain how I created this realistic

play00:13

looking Rass using blender and under

play00:15

engine in the first video I explained

play00:17

how I use Niagra to build a 2d wind

play00:19

system and dynamically generate a tiling

play00:21

wind texture I also showed a very simple

play00:24

way to animate grass using the texture

play00:26

and Achieve spherical repr projection

play00:28

trick in today's video I'm going to dive

play00:30

much much deeper I'm going to Showcase a

play00:33

whole bunch of very very cool tricks I

play00:35

use to create that natural and very

play00:37

fluffy looking animated grass now a

play00:39

couple of months ago I released a video

play00:41

explaining a crap ton of Industry grade

play00:43

techniques when it comes to rendering

play00:44

grass some of which I will be rusing in

play00:47

today's video so you might want to give

play00:49

that video a watch first if you haven't

play00:51

already all right let's get

play00:58

started

play01:00

now I've had an idea that has been

play01:02

bugging me for a while now you see this

play01:04

ghost of tsushima torque was very

play01:06

inspiring to me I like a lot what they

play01:08

did with their grass now I'd love to be

play01:10

more knowledgeable when it comes to UI

play01:12

and its rendering pipeline to be able to

play01:14

try similar things using geometry

play01:16

shaders and whatnot but for now I'm not

play01:18

and I can't but there's still a lot you

play01:20

can do with that good old world position

play01:21

offset so I wanted to see how far I

play01:24

could go with it hence why the grass

play01:26

mesh I'll be using in today's video

play01:27

looks like this now this will be the

play01:29

subject of a dedicated video so I'll be

play01:31

brief here but yes it's quite bizarre

play01:34

looking not the typical grass mesh you

play01:36

tend to use I have this flat cards right

play01:38

they are straight purposely undeformed

play01:41

and they are all oriented towards the

play01:42

positive x-axis I use the first UV map

play01:45

to well map my grass textures nothing

play01:48

fancy I also used my data Baker blender

play01:50

addon to bake this cards pivots in UVS

play01:53

it's quite a common technique and I made

play01:55

a video on the subject so feel free to

play01:56

check it out I also baked the normalized

play01:59

height in UV in the vertical axis and a

play02:01

random value per card in the horizontal

play02:04

axis very useful so that's the mesh I

play02:06

exported to you and the idea was to try

play02:08

and see if it was possible to build most

play02:10

of the grass mesh features band

play02:12

orientation and all using nothing but

play02:15

World position ofet tricks and do that

play02:17

in the hope that I could reach a much

play02:19

more natural look by having a complete

play02:21

control over these features and their

play02:23

randomization so let's have a

play02:28

look as as usual my favorite wall

play02:31

position of the trick of all times is to

play02:33

reconstruct a wall position from scratch

play02:35

and convert it to an offset so let's do

play02:38

that Zer subtracted by World position

play02:40

that collapses all vertices to the world

play02:42

origin because all vertices are now at 0

play02:45

0 0 as simple as that so let's add the

play02:48

vertices local position then subtract

play02:51

the baked pavots in local space to

play02:52

Center cards on zerin at that point

play02:55

scale and rotation can be applied to

play02:57

well scale and rotate cards around their

play02:59

p points so I'm first going to use a

play03:01

perir instance fade amount node this 0

play03:04

to1 value is based on the instance start

play03:06

and anle distance settings that's going

play03:09

to frame cards at a distance and smooth

play03:11

out otherwise very harsh instance

play03:13

distance gning next let's apply the

play03:16

instance scale here I'm going to assume

play03:18

instances are uniformly scaled and that

play03:20

the scale Z component is used to control

play03:22

that uniform scale so let's create an

play03:25

Vector transform it from local to World

play03:27

space then get that vector's length and

play03:29

that the instant scale along the

play03:31

z-axis and maybe add an extra parameter

play03:34

to have further control over that scale

play03:36

cool it's working next let's offset

play03:39

cards so they recover their original

play03:41

World position that's just a matter of

play03:43

adding the big pivots transform from

play03:45

local to World space and here's another

play03:48

neat trick instead of offsetting cards

play03:50

using their pivots in World space I can

play03:52

use instance position in worldspace

play03:55

cards are going to be centered on that

play03:56

single instance position not very

play03:58

interesting but then I can lure between

play04:00

these two positions and control how much

play04:02

cards are spread apart right keep in

play04:05

mind that may mess with occlusion

play04:06

cutting so you might want to increase

play04:08

the mesh bounds a bit depending on the

play04:10

amount of offset applied on average just

play04:12

to be on the safe side neat for now

play04:15

let's set this to one so that's a base I

play04:17

can already somewhat work with cards are

play04:19

correctly located at their pivot Points

play04:21

scaled based on the instance Z scale and

play04:24

they all remain straight regardless of

play04:26

the instance rotation so that's great

play04:28

but obviously they all face the same

play04:30

direction and are pretty boring looking

play04:32

still so first I'd like to rotate

play04:38

cards applying rotations can be tricky

play04:41

I'd like to rotate cars around the taxis

play04:43

randomly I suppose but although possibly

play04:45

tilt CS towards a certain direction the

play04:48

side likely need to apply a rotation

play04:50

around the X and Y axis as well and

play04:52

rotations are a bit tricky to stack it's

play04:54

not impossible but that's a lot of

play04:56

trigonometry just to oron cards

play04:58

fortunately there's a better and simpler

play05:00

solution I'm going to construct three

play05:02

axis and use a 3X3 Matrix to rotate each

play05:05

card and this method is actually going

play05:07

to help me do crazy cool things but

play05:10

let's start simple for now I'm going to

play05:12

assume the z-axis is still the Z World

play05:14

axis now I want to rotate cards randomly

play05:17

around that z-axis how to do that well I

play05:19

just need to tell that mesh that x-axis

play05:22

of yours isn't the world x-axis anymore

play05:24

but say that one and your y-axis is now

play05:27

just the cross product between these two

play05:29

and the 3X3 matrix multiplication will

play05:32

result in vertices matching that new

play05:34

coordinate system as simple as that now

play05:37

I could mathematically generate a random

play05:39

2D direction to create a unique x-axis

play05:41

spare card but that comes at a cost a

play05:44

better solution could be to compute that

play05:46

AIS ahead of time and vertex color could

play05:48

be used for this UVS as well you could

play05:50

bake a random 2D Direction per card in

play05:53

UVS right but I used another method I

play05:55

used vertex normals I'll explain this in

play05:58

a minute but I'm actually going to

play05:59

generate my own normal in World space so

play06:02

the normal stored in each vertex is kind

play06:04

of irrelevant th why not make use of

play06:07

that normal to store a random 2D

play06:08

direction for free right to do this I

play06:11

updated my data Baker blender addon it

play06:14

now can generate a random 2D or 3D

play06:16

Direction and bake it in vertx color or

play06:19

normal

play06:21

sweet as I note I also try to do this

play06:24

using an action script and geometry

play06:26

scripting but I hit some kind of road

play06:28

block but still I'm going to to mention

play06:29

it real quick so let's have a look at

play06:31

the action script first it's made to

play06:33

work with static mhes I get the selected

play06:36

assets Loop through each static mesh

play06:39

construct a dynamic mesh then for each

play06:41

LS copy that LOD then I use the split

play06:45

mesh by components function so that

play06:47

essentially does that each card becomes

play06:49

a unique Dynamic mesh right so then for

play06:52

each card I generate a random 2D

play06:54

Direction and store that direction in

play06:56

the vertex normals next I open that c

play06:59

card to at first an empty Dynamic mesh

play07:01

so that reconstruct the grass mesh card

play07:04

by card right and once all cards are

play07:06

processed and merged into that single

play07:08

Dynamic mesh I replace the original

play07:10

static mesh ass set with it at that LOD

play07:12

index and RSE and repeat for all lods I

play07:16

also make sure to use a stream when

play07:17

generating that random Direction so all

play07:19

lods generate the same random direction

play07:22

for a given grass card super important

play07:24

all right let's have a look at it in

play07:26

action then so that's the mesh I'm

play07:27

starting with normals are oriented the

play07:30

same way as

play07:31

expected right click and click Generate

play07:33

random 2D

play07:37

normal and VOA see each card stores a

play07:40

unique 2D Direction in the vertex

play07:41

normals and that direction is consistent

play07:44

across all

play07:45

[Music]

play07:47

lods until it is not because a given LOD

play07:51

May simply delete cards so that array of

play07:53

components may not be consistent between

play07:56

lods and thus there's no easy way to

play07:58

make sure the same normal is shared

play07:59

between cards of different lods if that

play08:02

makes sense plus because this approach

play08:04

navely splits components while a single

play08:07

grass card may be made of multiple

play08:09

meshes right and thus would need to have

play08:11

the same normal and yet these meshes

play08:13

won't because they will be treated as

play08:15

different components and I didn't find

play08:17

an easy way to automate this you could

play08:19

manually paint poly groups and split by

play08:21

poly groups but that's not such a

play08:23

pleasant user experience so in the end I

play08:25

did that in blender to make sure allies

play08:27

share the same data all right back to my

play08:30

worldall position of seig again then now

play08:32

that the vertex normal still that random

play08:34

2D Direction per card I can use it as a

play08:37

new x-axis and again the remaining y-

play08:39

axis is simply the cross product between

play08:41

these two unit orthogonal vectors one

play08:44

last step just make sure to turn on two

play08:46

sided here and Tada randomly rotated

play08:48

cars

play08:54

neat now let's say I want to allo oron

play08:58

cards according to the L

play08:59

landcape assuming this setting is set to

play09:02

True these instances should be oriented

play09:04

to match the landscape normal right so a

play09:06

given instance Z Vector transformed from

play09:09

local to World space gives me the lscape

play09:11

normal at that instance World position

play09:13

just keep in mind that a vector

play09:14

transform applies both the rotation and

play09:17

scale so here I need to normalize it to

play09:19

get a unit Vector unless that instance

play09:21

isn't scaled in Z but let's be on the

play09:23

safe side and normalize it anyway so

play09:26

let's use that unit Vector as the new

play09:28

z-axis however at this point I need to

play09:30

use one more cross product the reason

play09:32

for this is simple I know have this sled

play09:35

up Vector right and this flat 2D

play09:37

Direction so to build the remaining axis

play09:39

a single cross product between these two

play09:41

vectors give me this third vector and

play09:44

you can see that those three vectors are

play09:46

not orthogonal so that 3x3 Matrix isn't

play09:49

going to result in just a rotation but

play09:51

is going to deform the mesh in an

play09:53

undesired way so I first need to do a

play09:55

cross product between these two that's

play09:57

the first axis then then do a second

play09:59

cross product between that one and the

play10:01

vector that's my second axis and the

play10:04

vector can be used as is as the third

play10:06

axis those three vectors are not

play10:08

orthogonal cool feed them to that 3x3

play10:11

Matrix make sure to normalize cross

play10:13

products when using nonorthogonal

play10:14

vectors though and voila cards now do

play10:17

indeed match the landscape orientation

play10:19

great I can then use a l and control if

play10:22

I want straight up or smed cards and

play10:24

even exaggerate the effect the landscape

play10:26

has on those cards orientation very cool

play10:32

let's keep iterating on that Vector

play10:34

though because this Z Vector is

play10:36

normalized and as long as it doesn't

play10:38

equal that Vector here that 3x3 Matrix

play10:41

is well defined and stable so I can

play10:43

shift this Z Vector in X and Y as much

play10:46

as I want to til cards more and more so

play10:49

I could very well use a texture of some

play10:51

kind to shift that a vector in X and Y

play10:53

and tilt cards in arbitrary directions

play10:56

and create clums of

play10:58

grass

play11:01

turns out creating clums played a key

play11:04

role in the final look so to create what

play11:06

I call a clamp map I tried different

play11:08

things I first used blender to generate

play11:10

a ping height map then beg the normals

play11:13

to get the X and Y Direction but that

play11:15

was tedious and the result wasn't too

play11:17

convincing I then tried to artistically

play11:20

paint arbitrary directions using CR and

play11:22

its NE warp mode but I still didn't get

play11:25

the result I wanted and it was toed to

play11:27

paint as well so next I I Tred to build

play11:29

a tool in a new engine to generate that

play11:31

Clump map for me it's nothing too

play11:33

complicated but turns out it worked

play11:35

really well it's made with an editor

play11:37

utility widget here I have a bunch of

play11:40

single property view widgets just have

play11:43

to call set object on yourself and make

play11:45

them point to a viable within this

play11:47

blueprint and that's it UI creates a

play11:49

widget for you to tweak that viable neit

play11:52

I Alo made a simple button Nothing Fancy

play11:55

on click event I call this function here

play11:57

I do a bunch of safety checks nothing

play11:59

important create the Rend Target get the

play12:01

set path draw a bunch of stuff on that

play12:03

Rend Target and then call this create

play12:05

static texture function and W that tool

play12:08

generates a texture and saves it in the

play12:10

current asset browser

play12:13

directory so let's have a look at this

play12:15

draw clamp function really quick it's

play12:17

nothing too complex here I create a r

play12:19

Target then I create a dynamic instance

play12:21

of what I called a brush material I then

play12:23

call B draw to start drawing on the

play12:25

fromont Target on a loop a bit more

play12:27

efficiently and using a for loop I draw

play12:29

that brush dozens or hundreds of times

play12:32

each time I vary the brush parameters

play12:34

and where it's drawn at so it's like the

play12:37

tool does a single brush stroke maybe

play12:39

here then maybe there there and so on

play12:41

and so on using an additive process but

play12:43

it doesn't draw just a simple spherical

play12:45

gradient well almost but not quite I

play12:48

compute the 2D position Delta between

play12:50

the brush position in UV space and UVS

play12:53

that Delta is then safely normalized to

play12:55

derive a radial Direction UVS are also

play12:58

started with a noise node to create

play13:00

something a bit more intricate something

play13:03

that has a bit more flow to it right

play13:05

then that radial direction is masked

play13:06

using a billionaire sphere mask and the

play13:08

reason for this billionaire mask is

play13:10

quite simple but important again I'm

play13:12

going to use this Clump map this to the

play13:15

noise texture to shift that Z Vector

play13:17

here the one used to til cards right so

play13:20

to create clumps I want to orient cards

play13:22

toward the single point and that's what

play13:24

this radial direction is going to do

play13:26

it's going to shift that Z Vector toward

play13:28

that point the thing is that may result

play13:30

in cards Crossing each other at the

play13:31

center point and that doesn't look too

play13:33

great hence the Bonaire mask to fade in

play13:36

the effect but also to fade it out near

play13:38

the center point and prevent that from

play13:40

happening now one more important thing

play13:42

that brush material is following a

play13:44

principle I explained in the previous

play13:45

video it's duplicated and offsets three

play13:48

times to make it tile and ensure that

play13:50

the clump map itself does tile so that

play13:53

brush is drawn and randomized a few

play13:55

hundred times and I end up with that

play13:56

kind of very organic noisy looking

play13:58

texture and it works surprisingly well

play14:00

to create clamps to add a bit of flow to

play14:03

the grass and whatnot let's see how it

play14:05

can be applied to the grass Shader I

play14:07

could use the absolute worldall position

play14:09

to project that texture in w space right

play14:11

but that could deform the mesh quite

play14:13

unpleasantly because two vertices at two

play14:16

slightly different world positions could

play14:18

sample an to slightly different

play14:19

direction from that Clum map so I'd like

play14:22

to get a single quote unquote Clump

play14:24

sample pair card well easy enough use

play14:27

the be pivots inwards space as texture

play14:29

coordinates and that's it then add this

play14:32

X and Y offset to the Z Vector before

play14:34

it's normalized and voila cool but even

play14:37

better I can randomize the texture

play14:39

Coates and make that Clum map look a bit

play14:41

more chaotic and here again there are so

play14:44

many ways to do this here I'm simply

play14:46

going to offset the world space texture

play14:48

coordinates with that 2D random

play14:50

Direction each card stores in the vertex

play14:52

normals as simple as that you may also

play14:54

add the pivots in local space same but

play14:57

different so zero of set and the Clum

play14:59

texture is sampled as is and is

play15:01

specially coherent if that makes sense

play15:03

and the more offset added the more

play15:04

random it looks basically and it's cheap

play15:06

to compute keep in mind that randomizing

play15:08

texture cornetes like that usually comes

play15:11

at a cost if I'm not mistaken it's my

play15:13

understanding that this is generally not

play15:15

a very friendly thing to do for your GPU

play15:18

cash but oh well anyway voila grass

play15:20

clums it adds a bit of chaos to the

play15:22

picture and I kind of like it speaking

play15:24

of clamps it's one thing to influence

play15:26

the Tilt but what about the position

play15:28

well that's precisely what this lurp is

play15:30

for remember so I can very well control

play15:33

that lurp with a noisy looking texture

play15:34

of some kind and add even more

play15:36

Randomness to the picture now here the

play15:38

effect is kind of limited because the

play15:40

Clum position is basically instance

play15:42

position in an ideal world it would be

play15:44

an arbitrary position and this could be

play15:46

done using a 2d distance field something

play15:48

to

play15:50

[Music]

play15:52

try at this point you may think this Z

play15:55

Vector could be used to til cards away

play15:57

from the wind and you're absolutely

play15:59

right same exact principle I'm going to

play16:02

use the same setup to sample the wind

play16:03

texture and have the ability to break

play16:05

the special Coran a bit and add some

play16:08

Randomness to the wind

play16:14

animation but I'm also going to do

play16:16

something cool remember cards all face

play16:18

the same direction at first and I rotate

play16:20

them myself with this Matrix here this I

play16:23

simply just know the direction each card

play16:25

is facing plus the value sampled from

play16:27

the Twin texture isn't just a scalar

play16:29

value it's not just how much wind to

play16:31

apply it's actual to the air flow the

play16:33

wind velocity so I can safely normalize

play16:36

that wind velocity and get the wind

play16:38

direction and use a DOT product with the

play16:40

direction cards are facing to modulate

play16:43

how much wind to apply this might be

play16:45

stupid but I figured a grass blade is

play16:47

quite a flat piece of geometry so I

play16:49

suppose it kind of acts as a sail and

play16:51

much less reacts to the wind when it's

play16:53

not facing it although realistically

play16:55

it's probably negligible in the ground

play16:57

scheme of things I'm not sure if that's

play16:59

even something that can be observed

play17:01

still it's quite cheap to implement and

play17:03

it brings some extra Randomness to the

play17:05

wind animation so why not it's fun to

play17:07

try

play17:11

things next I can use the topd gradient

play17:14

I back in

play17:16

UV and a l to fade in that offset along

play17:19

the grass length and create some kind of

play17:27

curvature

play17:30

alternatively I can simply multiply each

play17:32

of these two offsets to create

play17:33

individual controls for the curvature

play17:35

for the clump offset and for the window

play17:37

set why

play17:41

[Music]

play17:47

not for things are happening we are

play17:50

making good

play17:54

progress now assuming there's no wind

play17:56

and no Clump the grass still looks quite

play17:58

naturally straight and rigid I'd like to

play18:00

bend those cards and make them have a

play18:02

nice resting pose right and again there

play18:04

are many solutions to do this you could

play18:07

bake a 2d curvature map similar to what

play18:09

epic did for the grass in fortnite you

play18:11

could maybe bake more Target in vertex

play18:13

colors or UVS but I personally went with

play18:16

a mathematical approach it uses a sign

play18:18

and a cosine but it didn't measurably

play18:20

impact performance so why not one thing

play18:23

to keep in mind and I really should do

play18:24

more research on that subject shaders

play18:27

and gpus are complicated nothing scales

play18:30

linearly meaning at times you may use a

play18:32

sign and not even pay its cost occupancy

play18:35

may be low for any reason the GPU may be

play18:38

waiting for a texture to be fetched from

play18:39

memory or something and this have

play18:41

nothing else to do but math for free

play18:44

while welting as long as it's not

play18:46

dependent on what the GPU is waiting for

play18:48

in the first place right don't quote me

play18:50

on that though I'm for sure not an

play18:51

expert and it's definitely out of the

play18:53

scope of today's video anyway so back to

play18:56

my mathematical band this HS code is

play18:58

pretty much identical to the band

play19:00

modifier I shared on my Twitter a while

play19:02

ago it does just that it bends the mesh

play19:04

around the x-axis and that's why the

play19:07

grass mesh is exported with cards all

play19:09

facing towards the x-axis only once

play19:12

cards are bent do I apply the rotation

play19:19

Matrix now this hrsl code not only bends

play19:23

the mesh but also outputs the bend

play19:25

direction if that makes sense and that's

play19:27

my starting point to generate a worldall

play19:29

space normal but more on that later on

play19:31

let's stick to the worldall position of

play19:33

set for now so this band amount is

play19:35

driven by some noise texture to create

play19:37

some variation

play19:43

right I also use the wind's X and Y

play19:46

magnitude to decrease band amount and

play19:49

that creates a super interesting effect

play19:50

I think grass is naturally curved when

play19:53

standing still but is straighten the

play19:55

stronger the wind

play19:57

Force

play20:01

plus the more wind the less that other

play20:03

offet participates in the overall Z

play20:05

Vector computation proportionally right

play20:08

because of the normalization here so the

play20:10

grass may be initially tilted to point

play20:12

towards a certain direction because of

play20:14

the landscape or the clump effect but it

play20:16

will reorient itself to face the wind

play20:19

the stronger the wind blows very cool

play20:21

all right we are getting

play20:24

[Music]

play20:27

there super important thing when it

play20:29

comes to grass is what I call the

play20:31

perceived grass density ring on cards is

play20:34

good for performance but it obviously

play20:36

comes with a d side cards are visible

play20:39

until they are not thus costing vertex

play20:41

processing for no pixel

play20:44

coverage using Billboards or camera

play20:46

facing cards obviously solve this issue

play20:49

pixel coverage is maximized regardless

play20:51

of the view Direction Right but it's

play20:53

quite an old school technique and Bill

play20:55

BS can be quite apparent and OD looking

play20:59

well let's try to make the most of this

play21:01

technique anyway what would be the ideal

play21:03

solution here I want for each grass card

play21:05

to remain curved and bent and randomly

play21:08

rotated and i' want to maximize pixel

play21:10

coverage meaning make each triangle face

play21:13

the camera as much as possible all right

play21:15

let's start simple let's get rid of that

play21:18

rotation Matrix and the B hlsl node as

play21:20

well for now and let's use a matrix to

play21:23

rotate these cards toward the camera

play21:25

easy enough let's transform a z Vector

play21:27

from view towards space and derive an

play21:29

XYZ coordinate system from it okay the

play21:31

billboard effect is quite apparent

play21:33

indeed let's first get rid of the most

play21:35

Shing part of it the

play21:38

Tilt so let's get rid of the Z component

play21:41

here and normalize the resulting 2D

play21:43

Vector however that 2D Vector can now be

play21:46

null when looking straight up or down

play21:48

see if so the direction to use instead

play21:50

is a y Vector converted from view to w

play21:55

space so do that if the square length is

play21:58

close enough to zero use that y Vector

play22:02

instead cool the billboard effect is now

play22:04

only two dimensional that looks a bit

play22:07

better then I apply the band effect see

play22:10

that's kind of cool the mesh kind of

play22:12

rolls on itself to face the

play22:16

camera now The Wider the grass cards the

play22:18

more apparent and unappealing this

play22:20

effect is going to look but here I have

play22:22

quite thin cards for the most part so

play22:24

it's

play22:25

okay hold on let's press pose for second

play22:28

view space means the point of view of

play22:30

whatever rers the geometry thus during

play22:33

the shadow pass that's from the lights

play22:35

POV and thus Y cards face the light

play22:38

during the shadow path and the camera

play22:40

during the main path not ideal but to be

play22:43

honest it's not even that noticeable

play22:45

with plenty of grass

play22:47

around you may still want to consider

play22:49

using camera space instead that ensures

play22:52

Vector transform is made from the

play22:53

camera's POV even during the shadow path

play22:56

there's no right answer here both of

play22:58

their pros and cons for this specific

play23:00

effect got to pick your poison on one

play23:03

hand you have a different but stable

play23:05

Shadow when using a view transform on

play23:07

the other hand you have a consistent but

play23:09

unstable Shadow when using a camera

play23:11

transform by unstable I mean Shadows

play23:14

kind of disappear when cards are

play23:15

perpendicular to the lights Direction

play23:17

and cards flicker a bit at that point as

play23:19

well again that's only something that

play23:21

can be really noticed with individual

play23:23

cards and not that much of an issue with

play23:25

tons of grass blades around so I

play23:28

wouldn't worry about it too much you can

play23:30

Al of course use a shadow pass switch to

play23:32

have further control over what's

play23:34

happening during the shadow pass maybe

play23:36

disable the camera facing logic onar or

play23:38

something up to you but enough about

play23:40

Shadows now that cards face the camera

play23:43

let's rotate them once more hm I'm kind

play23:46

of back to square one cards are

play23:48

obviously no longer facing the camera

play23:50

because they are made to do so before

play23:52

they are rotated however it needs to be

play23:54

done that way because the camera facing

play23:56

logic needs to be applied apped before

play23:58

the bend effect else you get something

play24:00

that looks really

play24:03

bizarre and that bend logic needs to be

play24:05

applied on x-axis aligned meshes so

play24:08

before cards are rotated so this SE on

play24:10

paper applied in the correct order but

play24:13

break the camera facing logic hm quite a

play24:15

puzzle so what's the solution well again

play24:18

the issue is that cars are made to look

play24:20

at the camera before they are rotated so

play24:23

what if I could take that rotation into

play24:25

account when Computing the camera facing

play24:27

Matrix instead of using the actual 2D

play24:30

view Vector I'm going to use that same

play24:32

Vector but rotated by the inverse of

play24:34

that upgoing c rotation so that once the

play24:37

card rotation is applied that view

play24:39

Vector is indeed the actual view Vector

play24:42

that sounds complicated but it's not if

play24:44

I rotate those cards with a matrix let's

play24:47

un rotate the view Vector with an

play24:48

inverse Matrix and because I work in Tod

play24:51

space here it can be simplified to just

play24:53

this so I'm going to un rotate that view

play24:55

Vector with a c forward Vector used here

play24:58

and that's

play24:59

it voila this maximizes pixel coverage

play25:02

while still allowing cars to be randomly

play25:04

bent and rotated now you might think

play25:07

this looks too weird and indeed it does

play25:09

a bit but that's only really because

play25:11

we're looking at a single grass mesh

play25:13

here and so it becomes quite apparent

play25:15

but in context the effect is pretty much

play25:17

invisible yet it plays a huge role in

play25:20

increasing the perceived grass density

play25:23

this is without the camera facing effect

play25:25

and this is with without with quite a

play25:29

visible difference in Grass density but

play25:31

same Vex count and it's not that

play25:33

expensive to compute neat and that's

play25:35

prettyy much it for the wall position of

play25:37

set control the scale Bend position

play25:40

clamping and orientation clamping with

play25:42

textures to randomize these features and

play25:44

you can get something that looks quite

play25:46

natural speaking of scale let's add one

play25:49

last thing to this W position of set

play25:54

logic my stylized grass Shadow made use

play25:57

of runtime viral textures to do plenty

play25:59

of cool things for instance they were

play26:01

used to match the landscape color but

play26:03

for realistic grass I don't feel like

play26:05

that's an absolute necessity although

play26:07

it's common practice in AAA is to at

play26:09

least give a bit of tint to the grph

play26:11

based on the landscape color again it's

play26:13

up to you I also used the runtime vual

play26:16

texture to do a landscape projection and

play26:18

the same trick could be used here as

play26:20

well but I decided against it it doesn't

play26:22

contribute that much visually on a is do

play26:25

come at a cost plus a shadow that makes

play26:27

you of aties is usually a bit more

play26:29

Troublesome to migrate to other projects

play26:32

it was definitely an issue for people

play26:34

who tried to reuse my style as grass

play26:35

Shader so this time I decided to not use

play26:38

AES but that made me miss one very cool

play26:41

trick if you remember the grass layer I

play26:44

painted onto the landscape was Al

play26:46

embedded into a nity to create some kind

play26:48

of mask and smoothly shrink cards Bing

play26:50

onto other layers dirt and whatnot and

play26:53

to create a smoother and maybe more

play26:55

natural looking transition and I kind of

play26:58

wanted to do that still for my realistic

play27:00

glass Shader I like a lot what this

play27:02

technique adds to the overall look but

play27:04

how to do that without air is well a

play27:06

good old texture will do just fine this

play27:09

method is unscalable and isn't likely to

play27:11

work for a large open world right but

play27:13

for most use cases it's still a viable

play27:15

option so I built a tool similar to my

play27:18

SC capture tool I released on my Paton

play27:20

but simpler basically it lets you select

play27:22

a landscape and a material and that

play27:24

material is meant to put the painted

play27:26

layer you want to capture click that

play27:28

button and voila that's my landscape

play27:31

grass layer baked into a texture it can

play27:33

then be projected in World space in the

play27:35

grass Shader using that offet and size

play27:38

super easy and obviously that can be

play27:40

used to drive the card scale and

play27:42

smoothly shwing grass bleeding on the

play27:43

dirt layer and do other cool things

play27:46

that's without and that's with without

play27:49

with

play27:53

[Music]

play27:54

cool normals oh boy buckle up it's it's

play27:57

one thing to compute an offset for

play27:59

vertices but fixing normals is usually

play28:01

even more complicated the more ofet shig

play28:04

guns you do the more complex that

play28:06

usually is and at one point I find it

play28:08

easier to just rebuild a world space

play28:10

normal from scratch rather than fixing

play28:12

up an existing one plus remember I

play28:15

encoded a random Direction in normal so

play28:17

I kind of shot myself in the foot here

play28:19

I'll definitely have better luck

play28:21

rebuilding a world space normal from the

play28:23

ground up but what kind of world space

play28:25

normal though because I feel like there

play28:27

are schools of ss if I may say so for

play28:30

stylized rendering the common method is

play28:32

to have upward normals to unify the way

play28:34

cards and the underlying ground are lit

play28:36

and have something that looks a bit

play28:38

easier on the eye for realistic

play28:40

rendering the way to go at least on

play28:42

paper is to work with the default vertex

play28:44

normals if that makes sense and then

play28:46

rely on a Shader to make the light bleed

play28:48

through the geometry and prevent back

play28:50

faces from being incorrectly lit and

play28:52

looking too dark in UI you may do this

play28:55

in many ways you could create your own

play28:56

solution use subsurface cattering or

play28:59

best use the two-sided foliage shading

play29:01

model plus that Shader I believe

play29:03

automatically set some variables for

play29:05

Lumen to properly work with two-sided

play29:07

cards but I'm not entirely sure on that

play29:09

something I read a long time ago anyway

play29:11

H there's nothing preventing you from

play29:13

both tweaking normals and using some

play29:15

kind of subsurface cattering right and

play29:18

to be honest I don't think there's one

play29:19

right answer even for realistic grass

play29:22

both methods of their pros and cons

play29:24

fortunately I'll be able to choose

play29:26

between one or the other EAS and see

play29:28

which one works best all right let's

play29:30

give it a go first things first this is

play29:32

a bit too much to work with so I'm going

play29:34

to create a much simpler test SC I'm

play29:36

going to use a single mesh with just

play29:38

four cars and four directions encoded in

play29:41

normals then I'm going to disable the

play29:43

camera facing logic make sure the

play29:45

material uses World space normals and

play29:47

disable two sided here just to make sure

play29:50

faces are correctly oriented before I go

play29:52

any further and turns out they are not

play29:54

so I must have messed up this 3x3 Matrix

play29:57

oopsy see let's flip this axis and that

play29:59

one better Alo that likely means I need

play30:02

to flip that right Vector here as well

play30:04

so let's

play30:05

check yep cards are rotating the wrong

play30:08

way now so let's do

play30:12

that okay fixed sorry about

play30:17

that next I'm going to switch to the

play30:20

world normal buffer and let's add a

play30:21

sphere while I'm at it just to have a

play30:23

reference to work with okay I'm first

play30:25

going to get the bent of Vector this

play30:28

node

play30:29

outputs this node works on x-axis

play30:32

aligned meshes if you remember so the

play30:34

normal is a 3D Vector but lies on a 2d

play30:36

plane right to choosing between an

play30:38

upward and a forward normal is just a

play30:40

matter of swizzling components I'm going

play30:43

to take the absolute value for the Z

play30:44

component though I had a bug on this

play30:46

fixed it and at this point I'm too tired

play30:48

to ask why so that's the upward vector

play30:51

and that's the forward Vector so let's

play30:54

use a LP to select one or the other and

play30:56

let's plug that in the matal normal pin

play30:58

oh an error that's just because this

play31:00

local position here is only available

play31:02

for vertices not pixels basically so the

play31:05

pixel Shader complains about it just

play31:07

have to use a Vertex interpolator to fix

play31:10

the issue which is a good thing actually

play31:11

because I definitely wouldn't want to

play31:13

compute this per pixel okay so working

play31:16

with x-axis align cards at first means

play31:18

the normal should face positive x-axis

play31:20

at first and that's correct and as the

play31:23

cards curve normals gradually shift

play31:25

towards the Z direction as expected

play31:27

using end up War normal same thing

play31:29

except that we start here on the sphere

play31:31

and end up around there same Arc but

play31:33

different starting point so that works

play31:36

great next I need to rotate those

play31:38

normals the exact same way I rotate

play31:40

cards right so do the very same

play31:42

transform Matrix and

play31:45

done this card is correct and LS to the

play31:48

Z Vector this one is good that one is as

play31:51

well and that one too now let's add some

play31:54

fake wind to tilt cards and make sure

play31:56

it's behaving as

play32:00

expected and that seems to work normals

play32:03

shift toward the right direction great

play32:06

now let's see what happens if I choose a

play32:07

forward

play32:09

normal that card seems good normal start

play32:12

here and end up around here with the

play32:14

Tilt so the shift is correct however

play32:16

that one doesn't seem to work and the

play32:18

reason is simple that normal is a lined

play32:21

with a tilt axis so that Matrix results

play32:23

in no Visible Changes bummer and this

play32:26

was a huge puzzle I spent way too much

play32:28

time trying to find Anan solution I

play32:31

ended up finding a worko a huge cheat if

play32:34

I'm being honest but it works I'm going

play32:36

to lurp the war normal towards the til

play32:38

to the direction the greater the Tilt if

play32:40

that makes sense and that's going to

play32:42

ensure the wind and clim features have

play32:44

an effect on the normals and th the

play32:46

lighting regardless of what normal I

play32:47

choose upward or forward normal and that

play32:50

regardless of the cards forward axis as

play32:52

well quite a mouseful and I'm not even

play32:54

done there's one more tricky part adding

play32:57

a normal map normal maps are usually in

play32:59

Tangent space so relative to a 2d

play33:02

surface and so applying a tangent space

play33:04

normal map when you have nothing but a

play33:06

world space normal can be tricky usually

play33:09

i' use a transform Vector to go from one

play33:11

space to the other but sometimes that

play33:13

doesn't go according to plan the reason

play33:15

for this is I think because tangents are

play33:18

computed based on UVS and vertex normals

play33:21

and so messing with normals can break

play33:23

tangents I suppose it's something I've

play33:25

experienced with my waterfall cool as

play33:27

well when tweaking normals so here I

play33:29

might have shot myself in the foot by

play33:31

doing Shady stuff with the vertex

play33:33

normals but nothing to worry about let's

play33:35

think about it for a second that normal

play33:37

map is baked in Tangent space meaning

play33:39

relative to this planer surface and so

play33:42

the z-axis points that way x-axis that

play33:45

way and y axis that way well it's just a

play33:47

matter of swizzling vectors to reorient

play33:50

that XYZ system and then rotating the

play33:52

resulting normal according to my

play33:54

reconstructed wall normal meaning I'm

play33:56

going going to say hey tangent space

play33:58

normal map that z-axis of yours is no

play34:01

that one your y AIS is one obtained

play34:03

using a cross product like so and your

play34:05

x-axis is the result of this second

play34:07

cross product now this could be done a

play34:09

bit more carefully with safe

play34:10

normalization and so on but oh well I

play34:13

battle tested it and haven't noticed any

play34:15

issues and at this point I'm too lazy

play34:17

and voila I successfully remapped this

play34:20

tangent space normal to World space

play34:22

according to the cards orientation Bend

play34:24

and the Tilt inherited from the wind and

play34:27

effect on top of having extra artistic

play34:29

controls do I want upward or forward

play34:32

normals one looks better in blow

play34:34

daylight the other a bit better at

play34:35

sunris and sunset well can't have both I

play34:38

suppose although why not after all let's

play34:40

mainly use a forward normal but slightly

play34:43

shifted toward Z to get the best of both

play34:45

worlds o quite a puzzle that normal

play34:48

reconstruction almost got the best of me

play34:50

but I'm glad I got it working moving

play34:55

on r regarding opacity first I use theer

play34:59

elodes to have a smoother transition

play35:01

between elodes because they have to be

play35:02

carefully managed here due to the costly

play35:05

Vex Shadow Tri count must be drastically

play35:07

reduced at a distance and desert lods

play35:09

are great to make the level of detail

play35:11

transition a bit less apparent desert

play35:13

lods come at a small extra cost though

play35:15

something to be aware of next I use

play35:18

desert mask opacity quite uncommon for

play35:20

grass I suppose but I feel like that

play35:22

helped me get smoother edges and Achieve

play35:25

that fluffy look there's one thing to

play35:27

keep in mind though that's my grass

play35:29

opacity texture and me maps are going to

play35:31

turn that into a mush of great values

play35:33

especially in my case I was probably too

play35:36

aggressive with packing so at a distance

play35:38

cards are going to be somewhat

play35:39

transparent because of that dessert

play35:41

masked opacity kicking

play35:43

in there are two solutions probably more

play35:46

but I know two first you can toy with

play35:48

these options to tweak how me maps are

play35:50

generated that may help although UI has

play35:53

this option I'm not sure what it does

play35:55

under the hood exactly but it seems to

play35:57

ensure certain values are maintained

play35:59

across the Meep chain see there's quite

play36:01

a difference in brightness and that

play36:03

helps to prevent meeps from reaching

play36:05

that desert opacity threshold value

play36:07

second solution you can manually tweak M

play36:09

Maps Photoshop and even allows you

play36:12

to do this here's a method with

play36:14

just have to have a first layer named

play36:16

like so duplicate it reduce its size by

play36:19

half and name it MIP map

play36:22

one rinse and repeat until you reach a

play36:25

size of 1 pixel by one pixel and that

play36:27

the meip chain then export to DDS with

play36:29

the following options import it in UI

play36:31

select leave existing mips in the

play36:33

texture asset and voila you can manually

play36:36

customize each meip so maybe unsure that

play36:38

desert opacity threshold isn't reach in

play36:40

certain mips and done that custom me

play36:44

workflow can also be used to do plenty

play36:46

of cool things you could for instance

play36:48

embed some kind of fade in or Fade Out

play36:50

based on distance in mips say me zero is

play36:53

totally black why not see I didn't add

play36:55

any logic to the the Shader yet I built

play36:58

some kind of automated feding effect

play37:00

that's just a MB zero on the deser

play37:02

opacity doing that effect nothing else

play37:04

quite cool it's Al commonly used to

play37:07

reduce specular highlights in the

play37:08

distance so you could cheat a bit and

play37:10

reduce the value of your specular map

play37:12

and increase the value of your roughness

play37:14

map at a distance plenty of cool tricks

play37:16

to do with meeps especially in VFX and

play37:18

Tech art you can embed extra data in

play37:20

meeps and all Epic did something like

play37:22

this for their win system on fortnite

play37:24

super cool one more Passage trick you

play37:27

can use a shadow pass switch node to do

play37:29

bizarre things for instance you could

play37:32

say hey cards are entirely transparent

play37:34

when rendered in the shadow path or hey

play37:37

cars are completely opaque that's going

play37:39

to increase the shadow coverage quite a

play37:41

bit and make the grass look thicker and

play37:43

more dense but it's now quite apparent

play37:46

that Shadows are casted from the

play37:47

geometry and the geometry alone so you

play37:50

could choose to do this still but in the

play37:52

distance maybe use a switch that is

play37:54

enabled on the material instance used on

play37:57

distant lods that may help to create a

play37:59

dancer grass in the distance that's

play38:02

without and that's with keep in mind

play38:04

that now may make the LOD transition a

play38:06

bit more noticeable next trick at a

play38:09

close wrench you could say do the

play38:11

opposite you could use deser jumpol AA

play38:14

to fake light bleeding through the grass

play38:16

and casting a weaker Shadow super simple

play38:19

yet very effective I was made aware of

play38:21

that trick on Twitter so shout out to

play38:23

you guys super cool that shadow pass

play38:26

switch know could also be used in the

play38:27

wall position of that logic to do crazy

play38:29

things like say double the grass card

play38:32

size during the shadow pass to increase

play38:34

Shadow coverage I'm not sure why you

play38:36

would do this but there are plenty of

play38:38

cool things to

play38:41

try to get a dense enough grass well you

play38:45

need quite a lot of grass plates but

play38:47

it's unlikely you can afford one single

play38:49

grass card or mesh pair grass blade

play38:51

that's probably too much got to find

play38:53

some kind of in between and have cards

play38:55

with more than a few grass blades on

play38:57

them right that tends to look quite flat

play38:59

and old school though but adding some

play39:02

pixel depth offet may help to get rid of

play39:04

that boring flat card look here I simply

play39:07

rendered a random value perir grass

play39:09

blade and I simply use that texture to

play39:12

push pixels away in camera space super

play39:15

simple but it creates the illusion of

play39:16

certain grass blades being further away

play39:18

from the camera and gives a bit of

play39:20

depths to the grass

play39:22

cards now again that texture is going to

play39:25

turn into a mush of values at a distance

play39:27

with mid Maps right and because pixel

play39:30

depth of set creates self shadowing

play39:32

artifacts with Dynamic lighting it's

play39:34

probably best to ensure that at a

play39:36

distance that dep's value from the

play39:37

texture isn't average to a constant

play39:39

value it's not that big of a deal but

play39:42

here personally I gradually FedEd out

play39:44

that depth by fixing mips manually

play39:46

arguably that's not going to make a

play39:48

noticeable difference especially

play39:50

considering Shadow maps have limited

play39:52

range anyway but I thought it was worth

play39:54

mentioning I'm not sure how it be

play39:56

behaves with virtual Shadow map though

play39:58

something to

play40:01

check the rest of the Shader is super

play40:04

straight forward so I'm going to Bree

play40:06

through it first base color nothing

play40:08

fancy I'm just using a simple texture

play40:10

roughness and specular just using two

play40:12

textures as well opacity mask already

play40:15

explained World position of set same and

play40:18

normal and pixel depth of set as well

play40:20

here I configure the two-sided foliage

play40:22

Shader so it needs a subsurface color

play40:24

I'm just reusing the base color really

play40:26

but you could use the texture and the

play40:28

material opacity controls the

play40:30

transmission amount zero is fully

play40:32

translucent and that's it so the pixel

play40:35

Shader is actually quite simple and

play40:37

cheap the vertex Shader however there's

play40:40

quite a lot going on thus yes this grass

play40:43

definitely has a cost so it's really

play40:45

important to keep the vertex count under

play40:47

control and be quite aggressive with

play40:49

lods and prevent as much quad overdraw

play40:52

as possible still with a large amount of

play40:55

instances in a somewhat Long View

play40:57

distance performance remains quite

play40:59

decent I'd say please note I'm not using

play41:01

nanite nor virtual Shadow Marx here they

play41:03

both are great but they come with down

play41:05

sides I'm not yet comfortable with

play41:07

namely they don't cope well with World

play41:09

position offset although it's gotten

play41:11

much better recently and considering the

play41:13

idea behind this whole project was to

play41:15

see how far I could go with World

play41:17

position offsets I chose to stick with

play41:19

what I know and what I'm familiar with

play41:21

and Shadow maps and non Nite meshes are

play41:23

still Rock Solid anyway and I feel like

play41:26

I sort of achieved my initial goal I

play41:28

feel like I managed to recreate most

play41:30

features presented in this Tech talk but

play41:32

at what cost and is it worth it I

play41:35

personally feel like it's a bit much

play41:37

especially the normal reconstruction

play41:39

part where it's leaning a bit too much

play41:41

on the hcky sketchy side of things for

play41:43

my own taste but I'll let you be the

play41:45

judge of that it was a fun thing to try

play41:47

on a very good exercise anyway vo that's

play41:51

pretty much it as promised the third

play41:53

video is coming up soonish I'll cover my

play41:55

workflow for creating foliage Assets in

play41:57

blender and I'm actually working on a

play41:59

blender addon to hopefully facilitate

play42:01

this process I as mention a few other

play42:04

things it should be quite an interesting

play42:06

video in the meantime if you want to get

play42:08

your hands on this project files are

play42:10

available as a tier three reward on my

play42:11

patreon I also release the lscape layer

play42:14

capture tool and clamp map tool I

play42:16

mentioned during the video as tier one

play42:18

reward that's it I hope you found the

play42:20

video useful or entertaining or both and

play42:23

if you did feel free to leave a like and

play42:25

consider subscribing to my YouTube

play42:27

channel we're slowly growing so thanks

play42:29

to you all thanks so much for the

play42:30

incredible support on my patreon as well

play42:33

I just wouldn't be able to do these

play42:34

projects and videos without you so my

play42:37

props to you all you are definitely

play42:39

noticed and much appreciated all right

play42:41

thanks so much for watching I'll see you

play42:43

in the next video take care of yourself

play42:55

bye-bye

play42:56

[Music]

play43:04

[Music]

play43:14

[Music]

Rate This

5.0 / 5 (0 votes)

Related Tags
BlenderUnreal EngineGrass AnimationShader Techniques3D ModelingGame DevelopmentVideo TutorialLandscape RenderingWorld Position OffsetTechnical Art