1
1

More than 1 year has passed since last update.

【Unity, Shader】ShaderにColor32を送る

Last updated at Posted at 2022-04-14

はじめに

初投稿です。

まずGraphics.DrawMeshInstancedProceduralで色の異なるメッシュを大量に表示したいと思いました。
material.SetBuffer()でMaterialにNativeArrayで大量の色を送るにはfloat4でもいいですが、計算コストおよびメモリ消費削減のためにもColor32のまま送る方法を考えました。既出でしたらすみません。

目次

  1. 結論
  2. 解説
  3. 参考文献

結論

先に結論です。
細かくは説明しませんが、前もって計算しておいたNativeArrayからColor32をとりあえずそのまま送ります。

NativeArray<Color32> ColorsArray;
Material material;

var target = GraphicsBuffer.Target.IndirectArguments;
var colorsBuffer = new GraphicsBuffer(target, ColorsArray.Length, 4);//Color32 なので32bit=4byte
colorsBuffer.SetData(ColorsArray);
material.SetBuffer("colorsBuffer", colorsBuffer);

hlslにColor32はなさそうなので、同じ32bitの型で受け取ります。
uintで受け取ることで、以下のようにfloat4に恐らく高速で0~1のfloat4に置き換えられます。

StructuredBuffer<uint> colorsBuffer;

inline float4 uintToColor(uint u){  //vertでconst uint u=colorsBuffer[instanceID];
  const uint b=255;                 //   o.color =uintToColor(u) のように使う
  return  float4(u & b,u>>8 & b, u>>16 & b, u>>24)/255;
}

解説

SetBufferは型を判断しないので、同じ大きさ(byte)なら受け取ることができます。

そこから4つのbyteを取り出したいですが、byteもcharもないし、そもそもポインタがいります。
そこで、bit演算を行って4つのuintとして取り出します。

uintの中の下8桁に対応するビットを取り出すには11111111(2)=255(10)をand演算&をすれば、
上の24桁が0になるので、0~255までの値が取り出せます。
あとはシフト演算>>で桁を落としてから同様にすれば良いだけですが、

気を付けるべきはメモリの順番で、例えば00010011(2)はメモリでは11001000のように並んでいるので、
下8桁がStructLayoutで最初に並んだ r です。

こうしてあとはfloatにキャストして255で割れば上のuintToColorのように0~1のfloat4にできます。

よりよい方法があればコメントお願いします。

参考文献

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1