環境
Unity2022.2.14f1
概要
板ポリを視線奥方向に重ねることで、RayMarchingをしないで視覚化するという手法のテストです。
参考の記事に記載されているように、角ばったものや、3DTextureの視覚化には向かないようです。
雲や霧状のものの表現には使えそうではあります。
コード
using System.Collections; using System.Collections.Generic; using Unity.Collections; using UnityEngine; using static UnityEngine.GraphicsBuffer; public unsafe class TestStackedPlane : MonoBehaviour { [SerializeField] private Material _material = null; [SerializeField] private int _sliceNum = 64; private GraphicsBuffer _gbMatrices = null; private Bounds _bounds; private static int _spMatrices = Shader.PropertyToID("_Matrices"); private static int _spSliceNum = Shader.PropertyToID("_SliceNum"); #if UNITY_EDITOR private void OnValidate() { OnEnable(); } #endif private void OnEnable() { _gbMatrices = new GraphicsBuffer(Target.Structured, UsageFlags.LockBufferForWrite, 1, sizeof(Matrix4x4)); _material.SetBuffer(_spMatrices, _gbMatrices); _material.SetInt(_spSliceNum, _sliceNum); _bounds = new Bounds(Vector3.zero, new Vector3(10000.0f, 10000.0f, 10000.0f)); } private void OnDisable() { if(_gbMatrices != null) _gbMatrices.Dispose(); } private void Update() { var matrices = _gbMatrices.LockBufferForWrite<Matrix4x4>(0, 1); matrices[0] = transform.localToWorldMatrix; _gbMatrices.UnlockBufferAfterWrite<Matrix4x4>(1); Graphics.DrawProcedural(_material, _bounds, MeshTopology.Quads, _sliceNum * 4, 1); } }
Shader "Unlit/StackedPlane" { Properties { _Color("Color", Color) = (1, 1, 1, 1) _SdfTex ("Sdf Texture", 3D) = "white" {} } CGINCLUDE #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap #include "UnityCG.cginc" #define EPSILON 0.00001 float _SliceNum; fixed4 _Color; sampler3D _SdfTex; StructuredBuffer<float4x4> _Matrices; struct appdata { uint vertexId : SV_VertexID; uint instanceId : SV_InstanceID; }; struct v2f { float4 posCS : SV_POSITION; float3 posOS : TEXCOORD0; }; ENDCG SubShader { Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" } ZWrite Off Blend SrcAlpha One LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag v2f vert (appdata v) { v2f o; unity_ObjectToWorld = _Matrices[v.instanceId]; const uint vnum = 4; uint vertexId = v.vertexId % vnum; uint faceId = v.vertexId / vnum; const float2 vertices[] = { float2(-1, -1), float2(-1, 1), float2( 1, 1), float2( 1, -1) }; const float scale = 1.5; o.posOS = float3(vertices[vertexId], ((float)faceId / (float)(_SliceNum - 1)) * 2.0 - 1.0) * scale; o.posOS = mul(o.posOS, UNITY_MATRIX_V); o.posCS = UnityObjectToClipPos(float4(o.posOS, 1.0)); return o; } fixed4 frag (v2f i) : SV_Target { float4 color = float4(_Color.rgb, 0.0); float alpha = 1.0 / (_SliceNum - 1); float dist = tex3D(_SdfTex, i.posOS * 0.5 + 0.5); if(dist < EPSILON) color.a += alpha; return color; } ENDCG } } }
参考
Raymarchingではない3Dアプローチ - Qiita