Moebius-style 3D Rendering | Useless Game Dev
Summary
TLDRIn this episode of 'Useless Game Dev,' Leonard explores replicating the unique drawing style of French cartoonist Jean Giraud, known as Moebius, in real-time 3D rendering. He delves into the technical aspects of creating thin black outlines, flat colors, and detailed textures, using edge detection filters like the Sobel filter and manipulating the normal buffer. Leonard adds a hand-drawn feel with noise and crosshatching, culminating in a shader that mimics Moebius' lighting and shading techniques. The episode concludes with a racing game, 'Montrouge Grand Prix,' where viewers can test the shader in a playful environment.
Takeaways
- 🎨 The video is about replicating Moebius' drawing style in real-time 3D rendering, an experiment to see how close one can get to the artist's unique style.
- 🖌️ Moebius' style is characterized by thin black outlines, flat colors, and lots of details, which the video aims to replicate digitally.
- 🔍 To maintain a consistent line width in 3D, a screen-space filter is needed to counteract perspective distortion.
- 👁️ An edge detection filter, specifically a Sobel filter, is used to highlight edges in the 3D scene, simulating the outlines in Moebius' art.
- 📏 The Sobel filter works by applying a convolution matrix to neighboring pixels, highlighting differences and creating a sense of edges.
- 🌐 The filter is applied to both the depth map and the normal map to detect edges and enhance the hand-drawn look.
- 🌀 A slight noise is added to UV sampling to create the effect of wiggly lines, mimicking the imperfections of hand-drawn art.
- 🖼️ Texture information is written to the normal buffer to avoid perspective distortion, with a secret to avoid close-up viewing for maintaining the illusion.
- 🌈 Lighting in Moebius' style is conveyed through lines and crosshatched shading, which is achieved with a special 3D texture.
- ✨ Specular reflections are simulated with distinct white areas outlined in the normal map to catch light effectively.
- 🌈 Colors in the shader are kept simple with full brightness, and post-processing effects are used to adjust saturation and contrast, adding a film grain for an artistic touch.
- 🏎️ The video concludes with a racing game called Montrouge Grand Prix, showcasing the shader in a practical application and inviting viewers to try and beat the creator's score.
Q & A
Who is Moebius, and why is he significant in the context of this video?
-Moebius, also known as Jean Giraud, was a renowned French cartoonist and a major figure in French comic book art. His distinctive drawing style, characterized by thin black outlines, flat colors, and intricate details, serves as the inspiration for the shader effects being created in this video.
What is the primary goal of the video regarding Moebius' style?
-The primary goal is to experiment with replicating Moebius' drawing style in real-time 3D rendering. While it may not achieve the same level of mastery as Moebius' work, the experiment seeks to capture key elements of his style, such as consistent outlines, flat colors, and detailed textures.
What is a Sobel filter, and how is it used in this context?
-A Sobel filter is a type of convolution filter used for edge detection. In this context, it is applied to a 3D scene's depth map and normal map to create consistent outlines around objects by highlighting areas with high contrast or sudden changes in depth.
Why is it necessary to add noise to the UV sampling for the outlines?
-Adding noise to the UV sampling creates wiggly lines, which mimic the hand-drawn quality of Moebius' style. This helps the digital outlines look less perfect and more organic, akin to traditional pen strokes.
How are textures applied to objects without affecting the perspective in this shader?
-Instead of applying textures directly to objects, which would result in uneven lines due to perspective, texture information is written to the normal buffer. This allows the Sobel filter to pick up and outline the textures consistently, preserving the hand-drawn look.
What is the purpose of the special crosshatch texture, and how is it used?
-The crosshatch texture, which has three dimensions of crosshatching (horizontal, vertical, and sideways), is used to simulate shading in the Moebius style. Depending on the brightness of a pixel, different layers of crosshatch are applied to create the illusion of shading and depth.
Why is the crosshatch pattern applied in screen-space rather than object-space?
-Applying the crosshatch pattern in screen-space simplifies the process and ensures consistency across the scene. While applying it in object-space might better follow the contours of objects, it would require more complex calculations that the creator opts to avoid.
How are specular reflections represented in the shader, according to Moebius' style?
-Specular reflections are represented by distinct white areas that are also outlined. This is achieved by calculating the dot product between the surface normal and the main light direction, identifying the most exposed areas, and highlighting them in the normal map so the Sobel filter can outline them.
What role do post-processing effects play in achieving the final visual style?
-Post-processing effects are used to adjust saturation, contrast, and other color settings to achieve the desired look. Additionally, a custom grain effect is added to simulate the texture of paper and mimic the low framerate of old films, contributing to the overall aesthetic.
What is the purpose of the racing game mentioned at the end of the video?
-The racing game, titled 'Montrouge Grand Prix,' serves as a practical demonstration of the shader in action. It provides viewers with an interactive experience to see how the shader performs in a simple 3D environment, with the added challenge of trying to beat the creator's best lap time.
Outlines
🎨 Exploring Moebius' Art Style Through Shaders
In this episode of Useless Game Dev, Leonard introduces the concept of shaders and explores replicating the unique drawing style of Moebius, a renowned French cartoonist, in real-time 3D rendering. The video delves into Moebius' characteristic thin black outlines, flat colors, and detailed drawings. Leonard explains the challenge of achieving uniform lines on 3D objects due to perspective distortion and how a Sobel filter, a type of convolution filter, can be used for edge detection. By applying the Sobel filter to the depth map and normal buffer in a 3D scene, the outlines can be effectively highlighted. He also discusses adding a slight noise to UV sampling for a hand-drawn effect and addresses the issue of rendering texture details that appear uneven up close. By writing texture information to the normal buffer, details can be caught by the Sobel filter, although this requires avoiding close-ups. The video also covers crosshatching for shading, with a special texture prepared to represent different levels of brightness through crosshatched lines. This method allows for various shading techniques that replicate Moebius' artistic style, despite challenges with maintaining quality when applying these effects through filters.
🏎️ Implementing Crosshatching and Real-Time Shaders in Game Design
Continuing the exploration of Moebius' style, Leonard focuses on implementing crosshatching patterns to convey volume and shading on 3D objects. The shader graph utilizes different types of lines (horizontal, vertical, and diagonal) based on pixel brightness to create a layered crosshatching effect. While the ideal approach would have crosshatches follow object curves, practical constraints lead to a screen-space solution that applies crosshatching to the normal buffer, albeit with some quality limitations due to the Sobel filter. Leonard highlights the method for depicting specular reflections using distinct white areas, outlined for emphasis. This is achieved through a dot product calculation between the surface normal and light direction, integrating these highlights into the normal map for Sobel filtering. Moving to color, objects are characterized by single colors or gradients, with brightness managed by the crosshatch effect, enabling all colors to remain at full brightness. Post-processing effects adjust saturation, contrast, and add grain for a paper-like appearance, avoiding Unity’s film grain in favor of a custom solution that simulates the texture of old films. The culmination of these shader techniques is tested in a custom racing game, Montrouge Grand Prix, designed with a distinctive Moebius-like visual style. Players can try the game on itch.io, challenging themselves to beat Leonard's best score, marking an intersection of art and gameplay.
Mindmap
Keywords
💡Shaders
💡Moebius
💡Edge Detection Filter
💡Convolution Filter
💡Depth Map
💡Normal Map
💡UV Sampling
💡Crosshatching
💡Specular Reflections
💡Post-processing Effects
💡Montrouge Grand Prix
Highlights
Introduction to the video about shaders and the promise of a game at the end.
The goal to replicate Jean Giraud's, also known as Moebius', drawing style in real-time 3D rendering.
Moebius' distinct style characterized by thin black outlines, flat colors, and lots of details.
The challenge of maintaining a fixed-width line in 3D perspective using a screen-space filter.
Explanation of the Sobel filter for edge detection in shaders.
How convolution filters work with a weight matrix for different effects.
Applying the Sobel filter to a depth map for outlining objects in a 3D scene.
Utilizing the normal map for additional edge enhancement.
Adding a noise effect to UV sampling to achieve a hand-drawn, wiggly line appearance.
The peculiar issue of inter-dimensional void visibility when zooming on certain objects.
Writing texture information to the normal buffer to maintain detail under perspective distortion.
The technique of using a special three-dimensional cross-hatching texture for shading.
Adjusting crosshatch visibility based on pixel brightness for dynamic shading effects.
The approach to handle shadows with screen-space cross-hatching rather than traditional lighting.
Simulating specular reflections in Moebius' style using the normal map and Sobel filter.
Simplification of object colors with full brightness and the use of gradients.
Post-processing effects for adjusting saturation, contrast, and adding film grain to mimic paper.
Introduction of a custom film grain effect to avoid the movement associated with Unity's built-in grain.
A racing game named Montrouge Grand Prix created to showcase the shader in action.
Invitation to play Montrouge Grand Prix and challenge the creator's best score.
Transcripts
hi you must be here for the video
Well you're in luck because it's about shaders, and if you behave
there might even be a game for you to play at the end
I'm Leonard let's dive right into this episode of Useless Game Dev
Moebius, also knows that Jean Giraud, was a French cartoonist
and a major figure of French comic book arts.
and today we're going to try and replicate his drawing style when rendering real-time 3D
it is obviously never going to be as good as masterpieces drawn by an expert,
but this is more of an experiment to see how far we can go.
Regarding "his style", Moebius had a lot of different phases throughout his career,
but the style people associate with him most is this:
thin black outlines, flat colors, lots of details
Let's get started on the line, and more specifically the outline
The line of Moebius' drawings has most of the time a fixed width, meaning it's probably all drawn with the same pen
If I draw the line directly on a 3D object using a regular texture,
the perspective is going to make it uneven and pixelated up close,
so there must be a screen-space filter to keep everything at the same size.
To do this we're first going to need an edge detection filter
in the form of a Sobel filter, which is a kind of convolution filter.
Let me explain:
In a convolution filter, for every pixel on the screen the result of the filter will be
a weighted sum of the values of the neighboring pixels
to do this you sample the pixels around the target pixel and multiply the values according to a weight Matrix
If the weights are just a simple average, we get a simple blur
If the weights are gaussian weights, we get gaussian blur
This is the weight Matrix for the Sobel filter
As you may already be able to tell, the resulting sum will
highlight the differences between the left and the right sides of the pixel
If the values are same-ish the filtered pixel will be dark.
if however there is a high contrast between the two sides, the filtered pixel would be much brighter
If we test this on a sample image, we see that the Sobel filter highlights vertical edges
we just have to add a second similar filter that highlights horizontal edges
and by taking the maximum value of both we get a pretty nice Edge Detection Filter
In a 3D scene we will apply the Sobel filter on the depth map.
This way when an object is far behind another, there will be a sudden change in depth,
and voila! outlines
Something that also has sudden changes along the edges of an object is
the normal map of the scene. So we can also apply the Sobel filter
to the normal buffer, and we get even better edges
Now it's all supposed to be hand drawn after all, so I'm going to add a slight noise
to the UV sampling in order to get wiggly lines.
Nope that's too much.
Perfect
it's already looking quite good, although for some reason when I zoom on this fern,
I can gaze into the inter-dimensional void
Let's add texture to our objects.
There's a lot of details we want to draw on our objects, and once again,
if we draw them directly on the object the perspective is going to make the line uneven.
So my idea was to write the texture information to the normal buffer
After all we are not really going to apply any traditional lighting to the scene,
and the normals will get caught and outlined by your Sobel filter
The only issue with this, is that when you draw a single line on normal texture
it will actually get outlined by the Sobel filter,
and even if you draw the thinnest lines, when you look up close it doesn't look great.
But let's simply not look too closely at objects, and this will be a little secret
Also we don't want to get too close and risk falling into the void
In Moebius' drawing, lighting is mostly conveyed via the line itself
So you will have bright colors (we'll get to those in a moment),
and the shading is going to be done using crosshatched lines
To achieve this I prepared this special texture with three dimensions of cross hatching:
horizontal, vertical, and sideways.
Each of these layers write independently to the red, green, and blue channels of the texture respectively
which once in unity gives me basically three Textures in one
Pretty neat
with this I can add the crosshatch depending on the brightness of a pixel:
if it's between 100% and 75% brightness : no cross hatch between 75% and 50%: only horizontal lines
between 50% and 25%: horizontal and vertical
and finally between 25% and zero: all three types of lines
the shader graph for this is pretty simple too
In an ideal world the crosshatch pattern would follow the curve of the object it's on.
This is how it should be drawn to convey volume For the shady part of objects
this can be done by adding the crosshatch to the normal buffer, just like we do with texture
It works somewhat, but since it goes through the Sobel filter, the quality ends up being mmmeh.
For shadows however, while it might probably be feasible, erm, not by me
So we're going to stick with screen-space cross hatch for now
We're almost done with the line component of our shader. The last thing we need
is to show specular reflections.
In Moebius' drawing, this is done with very distinct white areas that are outlined as well.
With a simple dot product between the normal of a surface, and the direction of the main light of the scene,
We can get the area of the object that is most exposed to light,
and write that as a special color in our object's normal map so it's caught by the Sobel filter
Line looks alright it handles a 3D scene pretty well it definitely doesn't look as
detailed as it should be, but that would require me having some actual drawing skill so,
no. Let's move on to color.
Objects are simple: they have either a single color, maybe a fancy schmancy gradient,
and same thing for the skybox.
Also since the crosshatch line thing is taking care of the brightness component of colors, all colors can be at full brightness
It's all a bit too colorful now so we'll add post-processing effects to tweak saturation,
contrast, and other color adjustments.
Also throwing in some grain to look a bit more like paper.
I'm not a fan of unity's built-in film grain because it moves a lot, like the image has white noise or something,
So I made my own grain that only changes every 10 frames or so,
to mimic the low framerate of old films.
Our shader looks like it's ready in our sample scene so let's take her out for the spin in a small racing game I made,
dubbed Montrouge Grand Prix
it's a tiny racing game, very simple, go through the hoops to complete a lap, three laps total, fastest wins
It's available for you to play on itch.io, link in the description so go for it
this is my current best score, comment below if you can beat it.
Until then have a good one
5.0 / 5 (0 votes)