NaiveSurfaceNetsで穴堀り
環境
Unity2022.2.14f1
概要
以前作ったNaiveSurfaceNetsでボックスを作り、球状に穴を開けるテストです。
基本的に以前のコードのままですが、ComputeShaderに以下の穴を開ける関数と法線を算出する関数を追加しています。
モグラゲームとか作れそうです。
コード
#pragma kernel ChangeSdfVoxels [numthreads(1, 1, 1)] void ChangeSdfVoxels(uint3 id : SV_DispatchThreadID) { uint3 start = SpherePos - SphereRadius; uint3 vpos = start + id; if(vpos.x > SdfVoxelSize - 1 || vpos.y > SdfVoxelSize - 1 || vpos.z > SdfVoxelSize - 1) return; uint index = (vpos.z * SdfVoxelSize * SdfVoxelSize) + (vpos.y * SdfVoxelSize) + (vpos.x); float value = 1.0 - (length(vpos - SpherePos) / (float)SphereRadius); SdfVoxels[index] = max(value, SdfVoxels[index]); } #pragma kernel GenerateNormals [numthreads(1024, 1, 1)] void GenerateNormals(uint3 id : SV_DispatchThreadID) { if(id.x >= IndirectArgs[0] / 3) return; uint vindex = id.x * 3; float3 vec0 = Vertices[Indices[vindex + 1]] - Vertices[Indices[vindex]]; float3 vec1 = Vertices[Indices[vindex + 2]] - Vertices[Indices[vindex]]; float3 normal = normalize(cross(vec0, vec1)); float QUANTIIZE_FACTOR = 32768.0; int3 inormal = (int3) (normal * QUANTIIZE_FACTOR); Normals.InterlockedAdd(normalStride * Indices[vindex + 0] + 0, inormal.x); Normals.InterlockedAdd(normalStride * Indices[vindex + 0] + 4, inormal.y); Normals.InterlockedAdd(normalStride * Indices[vindex + 0] + 8, inormal.z); Normals.InterlockedAdd(normalStride * Indices[vindex + 1] + 0, inormal.x); Normals.InterlockedAdd(normalStride * Indices[vindex + 1] + 4, inormal.y); Normals.InterlockedAdd(normalStride * Indices[vindex + 1] + 8, inormal.z); Normals.InterlockedAdd(normalStride * Indices[vindex + 2] + 0, inormal.x); Normals.InterlockedAdd(normalStride * Indices[vindex + 2] + 4, inormal.y); Normals.InterlockedAdd(normalStride * Indices[vindex + 2] + 8, inormal.z); }
Shader "Unlit/GpuNaiveSurfaceNets2" { Properties { } CGINCLUDE #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { uint vertexId : SV_VertexID; }; struct v2f { float4 posCS : SV_POSITION; float3 normalOS : NORMAL; float3 lightDirOS : TEXCOORD0; }; StructuredBuffer<float3> Vertices; StructuredBuffer<int3> Normals; StructuredBuffer<uint> Indices; sampler2D _MainTex; float4 _MainTex_ST; ENDCG SubShader { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase" } LOD 100 Pass { CGPROGRAM #pragma multi_compile_fwdbase #pragma vertex vert #pragma fragment frag v2f vert (appdata v) { v2f o; float3 vertex = Vertices[Indices[v.vertexId]]; float4 posOS = float4(vertex, 1.0); o.posCS = UnityObjectToClipPos(posOS); #if 0 // flat shading uint vindex = v.vertexId - (v.vertexId % 3); float3 vec0 = Vertices[Indices[vindex + 1]] - Vertices[Indices[vindex]]; float3 vec1 = Vertices[Indices[vindex + 2]] - Vertices[Indices[vindex]]; o.normalOS = normalize(cross(vec0, vec1)); #else float QUANTIIZE_FACTOR = 32768.0; int3 n = Normals[Indices[v.vertexId]]; o.normalOS = normalize(float3(n.x / QUANTIIZE_FACTOR, n.y / QUANTIIZE_FACTOR, n.z / QUANTIIZE_FACTOR)); #endif o.lightDirOS = ObjSpaceLightDir(posOS); return o; } fixed4 frag (v2f i) : SV_Target { float3 normalOS = normalize(i.normalOS); float3 lightDirOS = normalize(i.lightDirOS); float NdotL = dot(normalOS, lightDirOS) * 0.5 + 0.5; fixed4 col = fixed4(1,0,0,1); col.rgb *= NdotL; return col; } ENDCG } } }
参考
SDFの視覚化(NaiveSurfaceNets) - テキトープログラム( ..)φメモ
Question - Calculating Normals of a Mesh in Compute Shader - Unity Forum