Unity 2018.3.2f1のWebGL出力で点群を表示できたのでやったことをメモしておく。
(はやくAmazon Sumerianで点群表示をサポートしてほしい)
Unity Editorで点群を表示してみる
表示手順
UnityでPoint Cloudを表示する方法 – NegativeMind – Medium
を参考にして以下のような手順を実施した。
- 以下のスクリプトを作成する。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class PointCloud : MonoBehaviour
{
private Mesh mesh;
int numPoints = 600000;
// Use this for initialization
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateMesh();
}
void CreateMesh()
{
Vector3[] points = new Vector3[numPoints];
int[] indecies = new int[numPoints];
Color[] colors = new Color[numPoints];
for (int i = 0; i < points.Length; ++i)
{
points[i] = new Vector3(Random.Range(-10, 10), Random.Range(-10, 10), Random.Range(-10, 10));
indecies[i] = i;
colors[i] = new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), 1.0f);
}
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
mesh.vertices = points;
mesh.colors = colors;
mesh.SetIndices(indecies, MeshTopology.Points, 0);
}
}
- 以下のシェーダーを作成する
Shader "Custom/VertexColor"
{
SubShader {
Pass {
LOD 200
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct VertexInput {
float4 v : POSITION;
float4 color: COLOR;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};
VertexOutput vert(VertexInput v) {
VertexOutput o;
o.pos = UnityObjectToClipPos(v.v);
o.col = v.color;
return o;
}
float4 frag(VertexOutput o) : COLOR {
return o.col;
}
ENDCG
}
}
}
- マテリアルを作成して作成したシェーダーを指定する。
- [CreateEmpty]でGameObjectを作成する。
- 作成したGameObjectにMesh Rendererコンポーネント、Mesh Filterコンポーネント、作成したスクリプト、作成したマテリアルを割り当てる。
- 実行する。
スクリプトについて
以下のように指定しているのでUInt32のMAXまで点群が設定可能。それを超える場合はゲームオブジェクト(メッシュ)の分割が必要。
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
WebGLで点群を表示してみる
上記のままでWebGLビルドしても点群が表示されない。
多分以下の問題。
MeshTopology.Point Geometry not displaying in WebGL Builds - Unity Forum
以下のようにすることでWebGLで表示できた。
- リンク先にあった以下のシェーダーを作成する。
Shader "Custom/PointCloud_GL"
{
Properties
{
_PointSize("PointSize", Float) = 5
_HeightTex("Height Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
LOD 200
GLSLPROGRAM
#pragma multi_compile __ HEIGHTMAP_ON
#ifdef VERTEX
out vec4 Color;
uniform sampler2D _HeightTex;
uniform float _PointSize;
float ToneMap(float rawValue)
{
float contrast = 3.8;
float exposure = 0.001;
float a = exposure * pow(rawValue, contrast);
return a / (1.0f + a);
}
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_PointSize = _PointSize * (1.0 / gl_Position.w);
#ifdef HEIGHTMAP_ON
float index = ToneMap(gl_MultiTexCoord0.x);
Color = texture2D(_HeightTex, vec2(index, 0));
#else
Color = gl_Color;
#endif
}
#endif
#ifdef FRAGMENT
in vec4 Color;
void main()
{
vec2 coord = gl_PointCoord - vec2(0.5);
if (length(coord) > 0.5)
{
discard;
}
gl_FragColor = Color;
}
#endif
ENDGLSL
}
}
}
- 上記シェーダーを[Editor] => [Project Settings]の[Always Included Shaders]に登録する。
- スクリプトのStart()に以下を追加する。
#if !UNITY_EDITOR && UNITY_WEBGL
gameObject.GetComponent<MeshRenderer>().material.shader = Shader.Find("Custom/PointCloud_GL");
#endif
- ビルドする。