Sprite 2d with shadowcasting in 3d space
Isometric stylized water
Lowpoly rigging and skinning
Mixamo integration
Custom render feature with custom postprocessing volume
Adaptation of this built-in shader for URP.
Shader "PostProcess/TiltShift"
{
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
float _Offset;
float _Area;
float _Spread;
float _Samples;
float _Radius;
float2 _PixelSize;
float _CubicDistortion;
float _DistortionScale;
float4 _GoldenRatioAngle;
float4 _BlitTexture_TexelSize;
inline half gradient (half2 uv)
{
half2 h = uv.xy - half2(0.5, 0.5);
half r2 = dot(h, h);
uv = (1.0 + r2 * (_CubicDistortion * sqrt(r2))) * _DistortionScale * h + 0.5;
half2 coord = uv * 2.0 - 1.0 + _Offset;
return pow ( abs (coord.y * _Area), _Spread);
}
half4 Tilt(Varyings input) : SV_Target
{
half2x2 rot = half2x2(_GoldenRatioAngle);
half4 accumulator = 0.0;
half4 divisor = 0.0;
half r = 1.0;
half2 angle = half2(0.0, _Radius * saturate(gradient(input.texcoord)));
for (int i = 0; i < _Samples; i++)
{
r += 1.0 / r;
angle = mul(rot, angle);
half4 bokeh = SAMPLE_TEXTURE2D(
_BlitTexture,
sampler_LinearClamp,
input.texcoord + _PixelSize * (r - 1.0) * angle
);
accumulator += bokeh * bokeh;
divisor += bokeh;
}
return accumulator/divisor;
}
ENDHLSL
SubShader
{
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
// No culling or depth
Cull Off ZWrite Off
Pass
{
Name "TiltPass"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Tilt
ENDHLSL
}
}
}
Custum Postprocessing voulme component
using System;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
[Serializable, VolumeComponentMenuForRenderPipeline ("Postprocess/TiltShift", typeof(UniversalRenderPipeline))]
public class TiltShiftPostprocess : VolumeComponent, IPostProcessComponent
{
public BoolParameter Active = new BoolParameter(true);
public ClampedFloatParameter Offset = new ClampedFloatParameter(0f, 0f, 1f);
public ClampedFloatParameter Area = new ClampedFloatParameter(1f, 0f, 20f);
public ClampedFloatParameter Spread = new ClampedFloatParameter(1f, 0f, 20f);
public ClampedIntParameter Samples = new ClampedIntParameter(32, 4, 64);
public ClampedFloatParameter Radius = new ClampedFloatParameter(2f, 0f, 2f);
public ClampedFloatParameter CubicDistortion = new ClampedFloatParameter(5f, 0f, 20f);
public ClampedFloatParameter DistortionScale = new ClampedFloatParameter(1f, 0f, 1f);
public bool IsActive() => Active.value;
public bool IsTileCompatible() => true;
}
Render Feature code
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class TiltShiftRenderFeature : ScriptableRendererFeature
{
private Material m_Material;
class TiltShiftRenderPass : ScriptableRenderPass
{
private Material m_Material;
// private static readonly int m_tiltId = Shader.PropertyToID("_TiltPass");
private RTHandle m_Tilt;
private RenderTextureDescriptor m_TiltTextureDescriptor;
// Golden Ratio Angle
private Vector4 m_GoldenRatioAngle = Vector4.zero;
private const float m_GoldenRatio = 2.39996323f;
public TiltShiftRenderPass(Material material)
{
m_Material = material;
float goldenCos = Mathf.Cos(m_GoldenRatio);
float goldenSin = Mathf.Sin(m_GoldenRatio);
m_GoldenRatioAngle.Set(goldenCos, goldenSin, -goldenSin, goldenCos);
m_TiltTextureDescriptor = new RenderTextureDescriptor(
Screen.width, Screen.height,
RenderTextureFormat.Default, 0);
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
m_TiltTextureDescriptor.width = cameraTextureDescriptor.width;
m_TiltTextureDescriptor.height = cameraTextureDescriptor.height;
RenderingUtils.ReAllocateIfNeeded(ref m_Tilt, m_TiltTextureDescriptor); // move to configure
}
// In URP 14 have blit problem, need to investigate
// possible solution: https://discussions.unity.com/t/resolved-custom-render-pass-failing-urp-v14-0-6/911141/3
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer commandBuffer = CommandBufferPool.Get();
VolumeStack volumeStack = VolumeManager.instance.stack;
TiltShiftPostprocess tiltData = volumeStack.GetComponent<TiltShiftPostprocess>();
RTHandle cameraTargetHandle = renderingData.cameraData.renderer.cameraColorTargetHandle;
if (cameraTargetHandle == null)
return;
if (tiltData.IsActive())
{
UpdateTiltMaterial(tiltData);
if(m_Material!=null)
{
if(cameraTargetHandle == null)
{
Debug.LogWarning("TiltTex is null");
}
if( cameraTargetHandle == null)
{
Debug.LogWarning("Camera is null");
}
Blit(commandBuffer, cameraTargetHandle, m_Tilt, m_Material, 0);
Blit(commandBuffer, m_Tilt, cameraTargetHandle, null, 1);
}
}
context.ExecuteCommandBuffer(commandBuffer);
CommandBufferPool.Release(commandBuffer);
}
private void UpdateTiltMaterial(TiltShiftPostprocess tiltData)
{
if (m_Material == null)
{
return;
}
// TODO move string to const or Shader Property ID
m_Material.SetFloat("_Offset", tiltData.Offset.value);
m_Material.SetFloat("_Area", tiltData.Area.value);
m_Material.SetFloat("_Spread", tiltData.Spread.value);
m_Material.SetInt("_Samples", tiltData.Samples.value);
m_Material.SetFloat("_Radius", tiltData.Radius.value);
m_Material.SetFloat("_CubicDistortion", tiltData.CubicDistortion.value);
m_Material.SetFloat("_DistortionScale", tiltData.DistortionScale.value);
// Setting up precalulated staff from here https://www.shadertoy.com/view/4d2Xzw
// to not calculate at runtime
m_Material.SetVector("_GoldenRatioAngle", m_GoldenRatioAngle);
}
public void Dispose()
{
// would material be deleted twice?
// #if UNITY_EDITOR
// if (EditorApplication.isPlaying)
// {
// Destroy(m_Material);
// }
// else
// {
// DestroyImmediate(m_Material);
// }
// #else
// Destroy(m_Material);
// #endif
if (m_Tilt!= null)
{
m_Tilt.Release();
}
}
}
TiltShiftRenderPass m_ScriptablePass;
public override void Create()
{
if (m_Material == null || m_Material.shader == null)
{
if (m_Material!=null)
{
CoreUtils.Destroy(m_Material);
}
m_Material = CoreUtils.CreateEngineMaterial("PostProcess/TiltShift");
}
m_ScriptablePass = new TiltShiftRenderPass(m_Material);
m_ScriptablePass.renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(m_ScriptablePass);
}
protected override void Dispose(bool disposing)
{
m_ScriptablePass.Dispose();
#if UNITY_EDITOR
if (EditorApplication.isPlaying)
{
Destroy(m_Material);
}
else
{
DestroyImmediate(m_Material);
}
#else
Destroy(m_Material);
#endif
}
}
Godot Cozy Test Scene
Grass shader modification:
void vertex()
{
//...
worldPos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
void fragment()
{
/// ...
float filter = texture(grass_filter_texture, (worldPos.xz + filter_shift.xz)/ filter_scale).a;
if (filter > density_threshold)
{
discard;
}
/// ...
}
Filter texture. Using alpha channel, but can lower bit depth for to 8 for examle.
Round rect button shader code:
shader_type canvas_item;
uniform vec4 color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 border_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float border_size: hint_range(0.0, 1.0) = 0.1;
uniform float corner_radius = 0.0;
vec4 square(vec2 uv, float width)
{
uv = uv * 2.0 - 1.0;
vec2 abs_uv = abs(uv.xy);
float square = step(width, max(abs_uv.x, abs_uv.y));
return vec4(vec3(square), 1.0);
}
vec4 square_rounded(vec2 uv, float width, float radius){
uv = uv * 2.0 - 1.0;
radius *= width; // TODO: make radius go from 0-1 instead of 0-width
vec2 abs_uv = abs(uv.xy) - radius;
vec2 dist = vec2(max(abs_uv.xy, 0.0));
float square = smoothstep(width - radius, width - radius + 0.01, length(dist));
return vec4(vec3(square), 1.0);
}
void fragment() {
vec4 sq = square_rounded(UV,1, corner_radius);
vec4 sq2 = square_rounded(UV,1.0-border_size, corner_radius+0.1);
vec4 col = color;
col = mix(color, border_color, sq2.r);
col.a *= 1.0 - sq.r;
COLOR = col;
}
Top comments (0)