Azure Kinect × Unity で Point Size を変更する方法

3D Sensor Advent Calendar 2019 の20日目の記事です。

# はじめに
同じ壁に当たる人が多そうなので記事にしてみます。

# 困ったこと
AzureKinectで取得したポイントクラウドのPointSize粒々のスケール)を変更できませんでした。
具体的には、VertexShaderのPSIZEの値を変更しても画面で何も変化が起きない…。困った…。

カメラが近づくとこんな感じにスカスカ。
PointSizeが1に固定されている感じ。
![K4A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215186/d3c458c6-b390-a8fd-3958-40314b279037.png)



# 出来たこと
AzureKinectで取得したDepth画像のPointSizeを変更することができました。

こんなかんじ。分かりやすいようにPointSizeを5に設定してます。
![K4A_NoGreenBack - AzureKinectSample - PC, Mac & Linux Standalone - Unity 2019.2.11f1 Personal_ _OpenGL ES 3.2_ 2019_12_20 21_39_10 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215186/aa155991-7bef-65e4-4cd9-e275d2ce3bbf.png)

PointSizeを1から2に変えただけでも全然違う。
![K4A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215186/93386ac0-119d-bcc1-36fd-7dad219f7512.png)

# どうやったか

うーん。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">vertexの粒の大きさはPSIZEで変更できる認識で会っていたけどDX11以降では無効化される謎仕様変更で効いていなかった。Quest向けにOpenGLに変えたらいけた…。</p>&mdash; そいちろ@LookingGlass&amp;AzureKinect (@asidys230) <a href="https://twitter.com/asidys230/status/1187357282062852096?ref_src=twsrc%5Etfw">October 24, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


同じ悩みを抱えている人がいました。
[DX11 PSIZE Bug, PLEASE HELP! - Unity Forum](https://forum.unity.com/threads/dx11-psize-bug-please-help.383220/)
>DX11 doesn't support point mode rendering anymore according to the documentation, so I'm surprised it works at all. The idea behind that is that it is replaced by geometry shaders. So you'll have to generate a quad at every vertex yourself using a geometry shader.

あんまりよく分かってないけど、とりあえずDX11以降は素直には効いてくれなさそう。

つまり、犯人はこいつ。
![NG.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215186/dc4d4dd1-36ac-0bbf-b9b4-acefa36d367f.jpeg)

こうしたらいけました。
![K4A_NoGreenBack - AzureKinectSample - PC, Mac & Linux Standalone - Unity 2019.2.11f1 Personal_ _OpenGL ES 3.2_ 2019_12_20 22_35_09_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215186/68a0c448-3aa5-1374-7f5b-92f37a4b5ac5.jpeg)

ちなみにShaderはこんな感じ。

```ColorutoutPoint.shader
Shader "Custom/ColoredVertex" {
	Properties{
	 _Size("ShaderSize", Float) = 1.000000
	 _PointSize("PointSize", Float) = 1.0
	}
		SubShader{
		 Pass {
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma target 2.0
		#include "UnityCG.cginc"
		#pragma multi_compile_fog
		#define USING_FOG (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))

		float _Size;
		float _PointSize;

		// uniforms
		// vertex shader input data
		struct appdata {
		  float3 pos : POSITION;
		  half4 color : COLOR;
		  UNITY_VERTEX_INPUT_INSTANCE_ID
		};

	// vertex-to-fragment interpolators
	struct v2f {
	  float psize : PSIZE;
	  fixed4 color : COLOR0;
	  #if USING_FOG
		fixed fog : TEXCOORD0;
	  #endif
	  float4 pos : SV_POSITION;
	  UNITY_VERTEX_OUTPUT_STEREO
	};

	// vertex shader
	v2f vert(appdata IN) {
		IN.pos.xyz = IN.pos.xyz * _Size;
		
	  v2f o;
	  UNITY_SETUP_INSTANCE_ID(IN);
	  UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
	  half4 color = IN.color;
	  float3 eyePos = mul(UNITY_MATRIX_MV, float4(IN.pos,1)).xyz;
	  half3 viewDir = 0.0;
	  o.color = saturate(color);
	  // compute texture coordinates
	  // fog
	  #if USING_FOG
		float fogCoord = length(eyePos.xyz); // radial fog distance
		UNITY_CALC_FOG_FACTOR_RAW(fogCoord);
		o.fog = saturate(unityFogFactor);
	  #endif
		// transform position
		o.pos = UnityObjectToClipPos(IN.pos);
		o.psize = _PointSize;
		return o;
	  }


	// fragment shader
	fixed4 frag(v2f IN) : SV_Target {
	  fixed4 col;
	  col = IN.color;
	  // fog
	  #if USING_FOG
		col.rgb = lerp(unity_FogColor.rgb, col.rgb, IN.fog);
	  #endif
	  return col;
	}
	ENDCG
	 }
	}
}
```


# さいごに
結構ハマってました。
もっとちゃんと根本的に解決したい気持ちはあるけど、とりあえず解決してよかったです。


明日は sirokujira さんの「Stereo Labs ZED Camera についての話」です。