- Home /
Pixelart camera shader
Hello! Its been a year when i started my journey with unity and gameart. I've learnt a lot, but more about gameart and 3d modelling, than about technical aspects of graphics.
Recently, i've came across this video:
The thing is, while i know how to recreate the effect inside of blender for example - i have no idea where to start with unity. And i would absolutely love to create some small project based on this idea.
Here is my question, since i cant really find any reliable materials covering this topic - anything else i've found on the internet isn't exactly what i would want, or is kinda unreliable. How does this work? Is it entirely based on the idea of using render textures, or is it something else? The shading really reminds me of cell shading, but pixelated. Its also Pixel Perfect - which i cant really seem to achieve with my current knowledge. I would love if someone would share me their thoughts on how this can work - and how can i try to achieve this.
Cheers everyone ;)
Answer by Eno-Khaon · Nov 16, 2021 at 10:58 AM
There is quite a lot that would go into creating these visuals, so I'll address many of the main details here (but still glossing over full implementation of them).
This appears to be reproducible through a combination of elements:
Modified lighting (Shader) to Ceil/Round/Floor (or whichever) the light intensity.
// There's a whole lot more to this, but this is the
// gist of applying intentional color-banding.
float avgLight; // example using a single value for light intensity
// ...
// Example: 5 light intensities, ranging from 0-1
// Only an initial light value of 1.0 will be "lost", transforming
// into the same intensity as the (0.8-0.9999) range
float lightBands = saturate(floor(avgLight * 5.0) / 4.0);
A reduced render resolution for the scene. This can be done in numerous ways, but doing so without changing the base display resolution (i.e. the video's example of 1920x1080 Screen Resolution) would involve setting the main camera's Rect (Camera.rect) to the target size during OnPreRender(), then changing it back to the base resolution at the start of OnRenderImage(RenderTexture, RenderTexture). Specifically, this approach would keep the UI rendering at the screen's native resolution while reducing the 3D render resolution:
void OnPreRender()
{
baseRect = myCam.rect;
scaledRect.Set(baseRect.x, baseRect.y, targetWidth, targetHeight);
myCam.rect = scaledRect;
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
myCam.rect = baseRect;
// rest of general function usage: Blit(), etc.
}
Well, I guess those are really the only two primary elements with respect to this question. The video describes an orthographic camera rather than perspective and the water looks like it probably shows reflections, but the light bands and scaled render resolution are a bit more involved to fully implement (especially if you intend to apply lighting changes to both forward and deferred rendering and/or URP/HDRP).
For reference, a post-processing Shader could be used as a substitute for either/both elements, but would potentially have less versatility for lighting-based effects and would potentially be a more-expensive way to render a lower-resolution version of your scene. It's a valid option, but this is a situation where investing more effort into script and shader-related (lighting) elements could potentially have cleaner/more efficient results overall.
Thank you for a very deep answer! I will research it keeping the ideas you gave me.
What i observed looking at those scenes is the fact, that the shading looks like a cell shading (or if you prefer to call it other way, toon shading) - where we have 2-3 shade tones at best (genshin impact for example, uses max 2 for their characters, while 4 or more for the hair), which helps to deliver a very neat, cartoon'ish effect. I was wondering, if applying the cell shading WHILE playing with the resolution, wouldnt help to deliver pixelarty effect. As for reducing the render resolution, while keeping the base display on legacy settings - your idea is brilliant to be perfectly honest, and i would never in a hundred years would manage to discover it (well, not really, but i guess it would take some more time than simply asking for opinion). Im looking forward for learning more, thank you very much! :)
Answer by Llama_w_2Ls · Nov 16, 2021 at 07:24 AM
It just looks like a 3D scene. You may need to create a scene with lights, objects and terrain in the correct locations (maybe using post processing and light emission for some fancier graphics), and to give it a pixel look, you could try reducing your camera resolution.
Idk how good of an effect it will produce, but setting your camera to render at a lower resolution may produce a pixely look. Have a look at: Set screen resolution
That's exactly what i thought! Especially with cell shaded colors and textures, just reducing the resolution down using render texture should produce a nice, little effect. The problem lies with, well, everything else. While working around pixelation renders in blender, i've learnt it makes the best effect, when i made it look "crispy" and pixel-perfect. Exploring this effect made me realise, there is more to it than just lowering the resolution. Here is the Basic idea of how i do it when im rendering a scene in blender.
Basically, the trick lies in setting up the main light source in the scene extremely high, and then manipulating them resetting the color of lit up side of an object, and its shadow. The number of "samples" in the scene is also set to 1:16 which helps to boost up the effect and make it look tidy and cleaner.
The problem is... I dont think it really can work the same with unity rendering, since these are two different rendering engines. While the logic may be the same, then the options i could tween around are completely different, thus i've thought that asking this question could help me explore the idea a little bit more.
On a side note, i already managed to reduce the resolution down on a testing project, but it was far from satisfactory, but is a good start.
Thank you for your answer – if anyone will be interested in evolving this idea, i will post any progress i make in this certain thread :)
Your answer
Follow this Question
Related Questions
How can i get my quad to only render my texture without stretching it? 1 Answer
Raymarching Bug - Rendering 3D texture in real-time 0 Answers
3D RenderTextures with Depth Not Supported (worked in <=2017.1, broken 2018+) 1 Answer
What are the best shaders for mobile platforms ? 2 Answers
Nothing rendering in Scene view and only UI is rendering in Game view 0 Answers