Files
2025-06-09 23:23:13 +08:00

180 lines
6.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using JBooth.MicroVerseCore;
using UnityEngine;
namespace JBooth.MicroVerseCore
{
public class OcclusionData : StampData
{
public RenderTexture terrainMask; // collective mask for all of terrain
public RenderTexture treeSDF; // collective sdf for all trees
public RenderTexture currentTreeMask; // buffer for current tree stamps mask
public RenderTexture currentTreeSDF;
public RenderTexture objectSDF;
public RenderTexture currentObjectMask;
public RenderTexture currentObjectSDF;
public RenderTexture objectMask;
public OcclusionData(Terrain terrain, int maskSize) : base(terrain)
{
this.terrain = terrain;
RenderTextureDescriptor desc = new RenderTextureDescriptor(maskSize, maskSize, RenderTextureFormat.ARGB32, 0, 0);
desc.enableRandomWrite = true;
desc.autoGenerateMips = false;
terrainMask = RenderTexture.GetTemporary(desc);
terrainMask.name = "OcclusionData::mask";
terrainMask.wrapMode = TextureWrapMode.Clamp;
RenderTexture.active = terrainMask;
GL.Clear(false, true, Color.clear);
RenderTexture.active = null;
desc = new RenderTextureDescriptor(maskSize, maskSize, UnityEngine.Experimental.Rendering.GraphicsFormat.R8_UNorm, 0, 0);
objectMask = RenderTexture.GetTemporary(desc);
objectMask.name = "OcclusionData::mask";
objectMask.wrapMode = TextureWrapMode.Clamp;
RenderTexture.active = objectMask;
GL.Clear(false, true, Color.clear);
RenderTexture.active = null;
}
static Shader combineSDFShader = null;
public void RenderTreeSDF(Terrain t, Dictionary<Terrain, OcclusionData> ods, bool others)
{
// we have to blend across edges, so we make the render texture target larger
// than the mask data, blit all nine into a single texture, sdf it, then
// get the middle bit back out, then merge with cumulative texture
if (!ods.ContainsKey(t))
{
return;
}
var myMask = ods[t].currentTreeMask;
if (myMask == null)
return;
UnityEngine.Profiling.Profiler.BeginSample("Render Tree SDF");
int expand = (int)(myMask.width * 0.25f);
var expandedRT = MapGen.NineCombineCurrentTreeMask(t, ods, expand);
UnityEngine.Profiling.Profiler.BeginSample("JumpFloodSDF");
if (currentTreeSDF != null)
{
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(currentTreeSDF);
}
currentTreeSDF = JumpFloodSDF.CreateTemporaryRT(expandedRT, 0, 1.25f, 2);
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(expandedRT);
UnityEngine.Profiling.Profiler.EndSample();
if (others)
{
UnityEngine.Profiling.Profiler.BeginSample("CombineSDF");
if (combineSDFShader == null)
{
combineSDFShader = Shader.Find("Hidden/MicroVerse/CombineSDF");
}
Material mat = new Material(combineSDFShader);
RenderTexture rt = RenderTexture.GetTemporary(currentTreeSDF.descriptor);
rt.name = "MicroVerse::CombinedTreeSDF";
mat.SetTexture("_SourceA", currentTreeSDF);
mat.SetTexture("_SourceB", treeSDF);
Graphics.Blit(null, rt, mat);
if (treeSDF != null)
{
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(treeSDF);
}
treeSDF = rt;
UnityEngine.Profiling.Profiler.EndSample();
}
UnityEngine.Profiling.Profiler.EndSample();
}
public void RenderObjectSDF(Terrain t, Dictionary<Terrain, OcclusionData> ods, bool others)
{
// we have to blend across edges, so we make the render texture target larger
// than the mask data, blit all nine into a single texture, sdf it, then
// get the middle bit back out, then merge with cumulative texture
if (!ods.ContainsKey(t))
{
return;
}
var myMask = ods[t].currentObjectMask;
if (myMask == null)
return;
int expand = (int)(myMask.width * 0.25f);
var expandedRT = MapGen.NineCombineCurrentObjectMask(t, ods, expand);
currentObjectSDF = JumpFloodSDF.CreateTemporaryRT(expandedRT, 0, 1.25f, 2);
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(expandedRT);
if (others)
{
if (combineSDFShader == null)
{
combineSDFShader = Shader.Find("Hidden/MicroVerse/CombineSDF");
}
var mat = new Material(combineSDFShader);
RenderTexture rt = RenderTexture.GetTemporary(currentObjectSDF.descriptor);
rt.name = "MicroVerse::CombinedObjectSDF";
mat.SetTexture("_SourceA", currentObjectSDF);
mat.SetTexture("_SourceB", objectSDF);
Graphics.Blit(null, rt, mat);
if (objectSDF != null)
{
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(objectSDF);
}
objectSDF = rt;
}
}
public void Dispose()
{
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(terrainMask);
terrainMask = null;
RenderTexture.ReleaseTemporary(objectMask);
objectMask = null;
if (treeSDF != null)
{
RenderTexture.ReleaseTemporary(treeSDF);
}
if (currentTreeMask != null)
{
RenderTexture.ReleaseTemporary(currentTreeMask);
}
if (currentTreeSDF != null)
{
RenderTexture.ReleaseTemporary(currentTreeSDF);
}
if (objectSDF != null)
{
RenderTexture.ReleaseTemporary(objectSDF);
}
if (currentObjectMask != null)
{
RenderTexture.ReleaseTemporary(currentObjectMask);
}
if (currentObjectSDF != null)
{
RenderTexture.ReleaseTemporary(currentObjectSDF);
}
currentTreeMask = null;
treeSDF = null;
currentTreeSDF = null;
objectSDF = null;
currentObjectMask = null;
currentObjectSDF = null;
}
}
}