This is a post processing v2 effect that applies a limited palette dithering effect. If your project requires HDRP, you can use the URP implementation as an example of the required shader graph and camera settings. Palette generation is on a very simple editor script and can easily generate at runtime if needed.
I’ve been at it for a few hours and I can’t figure out how to get the effect working in URP. I think the problem I am having is likely due to linear colour vs gamma colour, giving a washed out effect. I’m also struggling to figure out how to implement post process/fullscreen effects (I don’t think it’s possible to make custom overrides?), as well as using the shader graph (I used both Unity and Amplify) in URP. If you’re interested in using this in your project, I recommend using the builtin renderer with Post Processing v2, and gamma colour space. The downsides of using the “old”, “bad” renderer are kind of lost when you consider the effect you get in the end, like this: https://www.youtube.com/watch?v=rj8jCh_k3ns
If you’re adamant on using URP and want this kind of effect you should make your own shader/effects (and if you do I would really love to see them!) then I can give you some tips on using the rest of the assets in the project. To start, you can deleted Dithered.cs from your project because it’s just used for post processing and gives errors in urp/hdrp. The asset files generated by the editor scripts are 3D textures, essentially lookup textures that use the RGB channels of the input texture as coordinates. The alpha channel of the 3D textures represent the “dominance” of that colour that sum to 1 at the same point. You can compare the alpha channel of the primary 3D texture to a dither texture sample, and if it’s greater use the primary, otherwise use the secondary. This is the unlit shader (called Dithered.shader) as it looks in Amplify Shader Editor. The dither node here seems to only ever output 1 or 0, which is why I use lerp instead of some comparison.
Hey, I’ve been playing around with these effects and they’re really impressive - congrats! I’m having trouble getting them to work in a standalone build though. Have you had any problem with this yourself?
I have not had any problems with standalone, could you be specific with the problem? Two errors that I could see being an issue would be the shader not included in the build for some reason (Project Settings → Graphics → Always Included Shaders) or not being able to generate textures on runtime due to missing compute shader support (like mobile devices). If the problem is with missing compute shader support, you can pre-generate the palettes and used them as saved assets.
Hi, I’ve seen a couple of tutorials for Shader Graph that might have Dither as an “effect” but not a “post-processing” one and nothing like what your asset does. I really loved it! I used it sparingly with the Built-In Renderer and now that I’ve switched to URP I miss it and I feel my game is missing that special retro look I was going for. Any chance there is a solve for URP?
Hi, I’ve added URP support now. It’s a bit clunky, but the end effect is the same, usage instructions in the github readme. Still at https://github.com/Ooseykins/QuickDither and has a .unitypackage available in releases on the sidebar.
Hi, thanks for this. I was having trouble getting an existing canvas with render mode “Screen Space - Camera” to render to the render texture and have it’s ray-casting work as well. (I couldn’t click any UI buttons). I found and built a solution, I thought I’d share in case anyone else stumbled on this thread. The problem was that the raycasting position wasn’t being downscaled to the size of the render texture. To fix:
Create a new script “CustomRaycaster.cs”:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class CustomRaycaster : GraphicRaycaster
{
public Canvas canvas;
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
{
if (canvas.worldCamera != null && canvas.worldCamera.targetTexture != null)
{
//Debug.Log($"p: ({eventData.position.x}, {eventData.position.y}) s({Screen.width}, {Screen.height}) => s({remap.x}, {remap.y})");
eventData.position = Remap(
new Vector2(Screen.width, Screen.height),
new Vector2(canvas.worldCamera.targetTexture.width, canvas.worldCamera.targetTexture.height),
eventData.position);
}
base.Raycast(eventData, resultAppendList);
}
Vector2 Remap(Vector2 from, Vector2 to, Vector2 input)
{
return new Vector2(
Mathf.Lerp(0, to.x, Mathf.InverseLerp(0, from.x, input.x)),
Mathf.Lerp(0, to.y, Mathf.InverseLerp(0, from.y, input.y))
);
}
}
Attach the script to the canvas being used for menus and such. This script replaces Graphic Raycaster on the canvas, so remove the old one.
Set the canvas field (should just be itself)
Done! That should be the only steps.
Thanks again, it was very helpful to see this approach. I learned a lot. =)
I dont know anything about how you made any of this work, but I noticed there is a small problem with the URP shader where the dithering is flipped, I toyed with the project a bit and it seems changing the Comparison node from “Greater or Equal” to “Less or Equal” solves the problem