Skip to content

Instantly share code, notes, and snippets.

@Ohmnivore
Created May 18, 2023 22:00
Show Gist options
  • Save Ohmnivore/46cdffe3bd55814c4f413d87fa589bbc to your computer and use it in GitHub Desktop.
Save Ohmnivore/46cdffe3bd55814c4f413d87fa589bbc to your computer and use it in GitHub Desktop.
Shader "Ohmnivore/Heightmap"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
float frag(v2f i) : SV_Target
{
float flipped = _ProjectionParams.x;
float nearPlane = _ProjectionParams.y;
float farPlane = _ProjectionParams.z;
float rawDepth = i.vertex.z;
float orthoLinearDepth = flipped > 0.0 ? 1.0 - rawDepth : rawDepth;
return orthoLinearDepth;
}
ENDCG
}
}
}
using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.Universal;
[ExecuteAlways]
public class HeightmapCamera : MonoBehaviour
{
[Serializable]
public struct State
{
public static readonly State Default = new State
{
Size = 10f,
Depth = 16f,
Resolution = new Vector2Int(512, 512)
};
public float Size;
public float Depth;
public Vector2Int Resolution;
}
public State Settings = State.Default;
public RenderTexture RT => m_RT;
[SerializeField]
private RenderTexture m_RT;
private void OnEnable()
{
SetupCamera();
}
private void Update()
{
transform.SetPositionAndRotation(transform.position, Quaternion.Euler(90f, 0f, 0f));
}
private void SetupCamera()
{
var cam = GetComponent<Camera>();
cam.orthographic = true;
cam.orthographicSize = Settings.Size * 0.5f;
cam.nearClipPlane = 0f;
cam.farClipPlane = Settings.Depth;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = Color.black;
cam.allowMSAA = false;
var additionalCam = GetComponent<UniversalAdditionalCameraData>();
additionalCam.antialiasing = AntialiasingMode.None;
additionalCam.renderShadows = false;
additionalCam.dithering = false;
if (m_RT == null &&
m_RT.width == Settings.Resolution.x &&
m_RT.height == Settings.Resolution.y)
{
m_RT = new RenderTexture(Settings.Resolution.x, Settings.Resolution.y, 24, GraphicsFormat.R32_SFloat);
m_RT.filterMode = FilterMode.Point;
cam.targetTexture = m_RT;
m_RT.hideFlags = HideFlags.None;
}
}
}
using UnityEngine.Experimental.Rendering.Universal;
using UnityEngine.Rendering.Universal;
public class HeightmapFeature : RenderObjects
{
RenderObjectsPass Pass;
/// <inheritdoc/>
public override void Create()
{
FilterSettings filter = settings.filterSettings;
if (settings.Event < RenderPassEvent.BeforeRenderingPrePasses)
settings.Event = RenderPassEvent.BeforeRenderingPrePasses;
Pass = new RenderObjectsPass(settings.passTag, settings.Event, filter.PassNames,
filter.RenderQueueType, filter.LayerMask, settings.cameraSettings);
Pass.overrideMaterial = null;
Pass.overrideShader = settings.overrideShader;
Pass.overrideShaderPassIndex = settings.overrideShaderPassIndex;
if (settings.overrideDepthState)
Pass.SetDepthState(settings.enableWrite, settings.depthCompareFunction);
if (settings.stencilSettings.overrideStencilState)
Pass.SetStencilState(settings.stencilSettings.stencilReference,
settings.stencilSettings.stencilCompareFunction, settings.stencilSettings.passOperation,
settings.stencilSettings.failOperation, settings.stencilSettings.zFailOperation);
}
/// <inheritdoc/>
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
var heightmapCamera = renderingData.cameraData.camera.GetComponent<HeightmapCamera>();
if (heightmapCamera != null)
renderer.EnqueuePass(Pass);
}
}
namespace UnityEngine.VFX.Utility
{
/// <summary>
/// Camera parameter binding helper class.
/// </summary>
[VFXBinder("URP/URP Camera")]
public class URPCameraBinder : VFXBinderBase
{
/// <summary>
/// The camera to bind to the VFX.
/// </summary>
public Camera Camera;
[VFXPropertyBinding("UnityEditor.VFX.CameraType"), SerializeField]
ExposedProperty CameraProperty = "Camera";
ExposedProperty m_Position;
ExposedProperty m_Angles;
ExposedProperty m_Scale;
ExposedProperty m_Orthographic;
ExposedProperty m_FieldOfView;
ExposedProperty m_NearPlane;
ExposedProperty m_FarPlane;
ExposedProperty m_OrthographicSize;
ExposedProperty m_AspectRatio;
ExposedProperty m_Dimensions;
ExposedProperty m_DepthBuffer;
ExposedProperty m_ColorBuffer;
/// <inheritdoc/>
public void SetCameraProperty(string name)
{
CameraProperty = name;
UpdateSubProperties();
}
void UpdateSubProperties()
{
// Update VFX Sub Properties
m_Position = CameraProperty + "_transform_position";
m_Angles = CameraProperty + "_transform_angles";
m_Scale = CameraProperty + "_transform_scale";
m_Orthographic = CameraProperty + "_orthographic";
m_FieldOfView = CameraProperty + "_fieldOfView";
m_NearPlane = CameraProperty + "_nearPlane";
m_FarPlane = CameraProperty + "_farPlane";
m_OrthographicSize = CameraProperty + "_orthographicSize";
m_AspectRatio = CameraProperty + "_aspectRatio";
m_Dimensions = CameraProperty + "_pixelDimensions";
m_DepthBuffer = CameraProperty + "_depthBuffer";
m_ColorBuffer = CameraProperty + "_colorBuffer";
}
/// <inheritdoc/>
protected override void OnEnable()
{
base.OnEnable();
UpdateSubProperties();
}
/// <inheritdoc/>
protected override void OnDisable()
{
base.OnDisable();
}
private void OnValidate()
{
UpdateSubProperties();
}
/// <inheritdoc/>
public override bool IsValid(VisualEffect component)
{
return Camera != null
&& component.HasVector3(m_Position)
&& component.HasVector3(m_Angles)
&& component.HasVector3(m_Scale)
&& component.HasBool(m_Orthographic)
&& component.HasFloat(m_FieldOfView)
&& component.HasFloat(m_NearPlane)
&& component.HasFloat(m_FarPlane)
&& component.HasFloat(m_OrthographicSize)
&& component.HasFloat(m_AspectRatio)
&& component.HasVector2(m_Dimensions)
&& component.HasTexture(m_DepthBuffer)
&& component.HasTexture(m_ColorBuffer);
}
/// <inheritdoc/>
public override void UpdateBinding(VisualEffect component)
{
component.SetVector3(m_Position, Camera.transform.position);
component.SetVector3(m_Angles, Camera.transform.eulerAngles);
component.SetVector3(m_Scale, Camera.transform.lossyScale);
component.SetBool(m_Orthographic, Camera.orthographic);
// While field of View is set in degrees for the camera, it is expected in radians in VFX
component.SetFloat(m_FieldOfView, Mathf.Deg2Rad * Camera.fieldOfView);
component.SetFloat(m_NearPlane, Camera.nearClipPlane);
component.SetFloat(m_FarPlane, Camera.farClipPlane);
component.SetFloat(m_OrthographicSize, Camera.orthographicSize);
component.SetFloat(m_AspectRatio, Camera.aspect);
component.SetVector2(m_Dimensions, new Vector2(Camera.pixelWidth, Camera.pixelHeight));
component.SetTexture(m_DepthBuffer, Camera.targetTexture);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format($"URP Camera : '{(Camera == null ? "null" : Camera.gameObject.name)}' -> {CameraProperty}");
}
}
}
@Ohmnivore
Copy link
Author

Hey, I haven't touched this project in a long time but I'll give it my best shot.

  1. What Unity version are you using?
  2. What are the symptoms of the issue? Are there any pixels being rendered to the RenderTexture?
  3. Try with an orthographic top-down camera just in case, since that's the setup I had in my project.
  4. Try disabling the extra depth and stencil settings. The heightmap shader acts like a regular shader except it writes the depth instead of a color. It doesn't require URP's special depth texture or stencil ops.

Here's my camera. Notice I made a separate Renderer for it. I don't remember exactly why.

image

image

image

image

image

@Zeyt8
Copy link

Zeyt8 commented Jun 9, 2024

Making a separate renderer for that camera fixed the issue. Thank you so much for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment