Skip to content

Instantly share code, notes, and snippets.

@lover-drive
Created February 18, 2022 23:24
Show Gist options
  • Save lover-drive/d0dd68aa0c2442687714512e91fe4a19 to your computer and use it in GitHub Desktop.
Save lover-drive/d0dd68aa0c2442687714512e91fe4a19 to your computer and use it in GitHub Desktop.
URP volumetric fog experiment
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace Zombies.VFX {
public class BlitPass : ScriptableRenderPass {
RenderTargetHandle _source;
RenderTargetHandle _step1;
RenderTargetHandle _temp;
Material _material;
Material _material2;
public BlitPass(RenderPassEvent evt, RenderTargetHandle source, Material material, Material material2) {
renderPassEvent = evt;
_source = source;
_material = material;
_material2 = material2;
_step1.Init("_Volumetric_fog");
}
public override void Execute(ScriptableRenderContext ctx, ref RenderingData renderingData) {
var cmd = CommandBufferPool.Get();
var descriptor = renderingData.cameraData.cameraTargetDescriptor;
cmd.GetTemporaryRT(_step1.id, descriptor.width / 2, descriptor.height / 2, 1, FilterMode.Bilinear, UnityEngine.Experimental.Rendering.GraphicsFormat.R16G16B16A16_SFloat);
cmd.GetTemporaryRT(_temp.id, renderingData.cameraData.cameraTargetDescriptor);
cmd.Blit(_source.Identifier(), _step1.Identifier(), _material);
cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget, _temp.Identifier(), _material2);
cmd.Blit(_temp.Identifier(), renderingData.cameraData.renderer.cameraColorTarget);
ctx.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void OnCameraCleanup(CommandBuffer cmd) {
cmd.ReleaseTemporaryRT(_temp.id);
}
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace Zombies.VFX {
public class PositionPass : ScriptableRenderPass {
RenderTargetHandle _destination;
Material _overrideMaterial;
List<ShaderTagId> _shaderTagIds = new List<ShaderTagId> { new ShaderTagId("UniversalForward") };
FilteringSettings _filteringSettings;
RenderStateBlock _renderStateBlock;
public PositionPass (RenderPassEvent evt, RenderTargetHandle destination, Material overrideMaterial) {
renderPassEvent = evt;
_destination = destination;
_overrideMaterial = overrideMaterial;
_filteringSettings = new FilteringSettings(RenderQueueRange.opaque);
_renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {
var descriptor = renderingData.cameraData.cameraTargetDescriptor;
cmd.GetTemporaryRT(_destination.id, 1024, 1024, 1, FilterMode.Trilinear, UnityEngine.Experimental.Rendering.GraphicsFormat.R16G16B16A16_SFloat);
}
public override void Execute(ScriptableRenderContext ctx, ref RenderingData renderingData) {
var cmd = CommandBufferPool.Get();
CoreUtils.SetRenderTarget(cmd, _destination.Identifier(), ClearFlag.All, Color.clear);
ctx.ExecuteCommandBuffer(cmd);
DrawingSettings drawingSettings = CreateDrawingSettings(_shaderTagIds, ref renderingData, SortingCriteria.CommonOpaque);
drawingSettings.overrideMaterial = _overrideMaterial;
ctx.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref _filteringSettings, ref _renderStateBlock);
CommandBufferPool.Release(cmd);
}
public override void OnCameraCleanup(CommandBuffer cmd) {
cmd.ReleaseTemporaryRT(_destination.id);
}
}
}
Shader "Volumetric fog blender"
{
Properties
{
_MainTex("MainTex", 2D) = "white" {}
_FogColor ("Fog color", Color) = (0.35,0.4,0.45,1.0)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent-1"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Cull Back
ZTest LEqual
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#define ATTRIBUTES_NEED_TEXCOORD0
#define VARYINGS_NEED_POSITION_WS
#define VARYINGS_NEED_TEXCOORD0
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 4.5
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#define GAUSSIAN_BLUR_UNROLL 1
#include "GaussianBlur.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float4 texCoord0 : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 texCoord0 : TEXCOORD0;
float fogCoord : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.texCoord0 = input.texCoord0;
output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
sampler2D _MainTex;
sampler2D _Position;
sampler2D _CameraDepthTexture;
float4 _MainTex_TexelSize;
float4 _Volumetric_fog_TexelSize;
texture2D _Volumetric_fog;
SamplerState sampler_Volumetric_fog;
sampler2D _CameraDepthAttachment;
float4 _FogColor;
float3 GetMainLightColor (float3 positionWS) {
VertexPositionInputs vertexInput = (VertexPositionInputs)0;
vertexInput.positionWS = positionWS;
Light light = GetMainLight(GetShadowCoord(vertexInput));
return light.color * light.shadowAttenuation;
}
float3 GetAdditionalLightsColor (float3 positionWS) {
uint numAdditionalLights = GetAdditionalLightsCount();
// uint numAdditionalLights = 2;
float3 output = float3(0,0,0);
for (uint i = 0; i < numAdditionalLights; i++) {
Light light = GetAdditionalLight(i, positionWS, 1);
output += light.color * light.shadowAttenuation * light.distanceAttenuation;
// output += 1;
}
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
// float4 targetPosition = tex2D(_Position, input.texCoord0);
// if (targetPosition.a == 0) return _FogColor * .05;
// float3 fog = 0;
// float num = 0;
// float4 color = tex2D(_MainTex, input.texCoord0);
// for (float t = 0; t < 1; t += .01) {
// num++;
// float3 position = lerp(_WorldSpaceCameraPos, targetPosition.rgb, t);
// // fog += GetAdditionalLightsColor(position);
// fog += GetMainLightColor(position) + GetAdditionalLightsColor(position);
// }
// fog /= num;
float3 color = tex2D(_MainTex, input.texCoord0);
// float3 fog = tex2D(_Volumetric_fog, input.texCoord0);
// float3 color = tex2D(_MainTex, input.texCoord0);
float3 fog = GaussianBlurSingle(_Volumetric_fog, sampler_Volumetric_fog, _Volumetric_fog_TexelSize, input.texCoord0, 5, 15);
// float depth = tex2D(_CameraDepthTexture, input.texCoord0).r * 1000;
fog = (1 - saturate(tex2D(_CameraDepthTexture, input.texCoord0).r * 100)) * fog;
return float4(color + fog * _FogColor, 1);
// return float4(color + fog * _FogColor, 1);
}
ENDHLSL
}
}
}
Shader "Volumetric fog builder"
{
Properties
{
_MainTex("MainTex", 2D) = "white" {}
_FogColor ("Fog color", Color) = (0.35,0.4,0.45,1.0)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent-1"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
Cull Back
ZTest LEqual
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#define ATTRIBUTES_NEED_TEXCOORD0
#define VARYINGS_NEED_POSITION_WS
#define VARYINGS_NEED_TEXCOORD0
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 4.5
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float4 texCoord0 : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 texCoord0 : TEXCOORD0;
float fogCoord : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.texCoord0 = input.texCoord0;
output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
sampler2D _MainTex;
sampler2D _Position;
sampler2D _CameraDepthAttachment;
float4 _FogColor;
float3 GetMainLightColor (float3 positionWS) {
VertexPositionInputs vertexInput = (VertexPositionInputs)0;
vertexInput.positionWS = positionWS;
Light light = GetMainLight(GetShadowCoord(vertexInput));
return light.color * light.shadowAttenuation;
}
float3 GetAdditionalLightsColor (float3 positionWS) {
uint numAdditionalLights = GetAdditionalLightsCount();
float3 output = float3(0,0,0);
for (uint i = 0; i < numAdditionalLights; i++) {
Light light = GetAdditionalLight(i, positionWS, 1);
output += light.color * light.shadowAttenuation * light.distanceAttenuation;
// output += 1;
}
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float4 targetPosition = tex2D(_Position, input.texCoord0);
if (targetPosition.a == 0) return float4(.05, .05, .05, 0);
float3 fog = 0;
float num = 0;
float4 color = tex2D(_MainTex, input.texCoord0);
for (float t = 0; t < 1; t += .01) {
float3 position = _WorldSpaceCameraPos + lerp(0, targetPosition.rgb, t);
fog += GetMainLightColor(position) + GetAdditionalLightsColor(position);
}
fog /= 100;
return float4(fog, targetPosition.a);
}
ENDHLSL
}
}
}
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace Zombies.VFX {
public class VolumetricFogFeature : ScriptableRendererFeature {
PositionPass _positionPass;
RenderTargetHandle _positionMap;
[SerializeField] Material _copyPositionMaterial;
[SerializeField] Material _blitMap;
[SerializeField] Material _blitMap2;
BlitPass _blit;
public override void Create() {
_positionMap.Init("_Position");
_positionPass = new PositionPass(RenderPassEvent.BeforeRenderingPostProcessing, _positionMap, _copyPositionMaterial);
_blit = new BlitPass(RenderPassEvent.BeforeRenderingPostProcessing, _positionMap, _blitMap, _blitMap2);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
renderer.EnqueuePass(_positionPass);
renderer.EnqueuePass(_blit);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment