Unity6でWebGL版の強化が入ったらしく,どうやらCompute Shaderが使えるようになったみたいです.これは期待大.早速試してみるとエラーでつまったので,その解決方法を記しておきたいと思います.
問題のコード
今回はテストということで,ただ単にrender textureの色を赤色にするだけのコードです.
コードは,適当にRawImageなどを作ってアタッチしてあげれば大丈夫です.
ただし,このコードは一部間違っているので,参考にする際はこれを見てください.
using UnityEngine;
using UnityEngine.UI;
public class ComputeShaderExample : MonoBehaviour
{
public ComputeShader computeShader;
private RenderTexture renderTexture;
void Start()
{
renderTexture = new RenderTexture(256, 256, 0);
renderTexture.enableRandomWrite = true;
renderTexture.Create();
computeShader.SetTexture(0, "Result", renderTexture);
int threadGroupsX = renderTexture.width / 8;
int threadGroupsY = renderTexture.height / 8;
computeShader.Dispatch(0, threadGroupsX, threadGroupsY, 1);
GetComponent<RawImage>().texture = renderTexture;
}
void OnDestroy()
{
if (renderTexture != null)
renderTexture.Release();
}
}
#pragma kernel CSMain
RWTexture2D<float4> Result;
[numthreads(8, 8, 1)]
void CSMain (uint3 id : SV_DispatchThreadID) {
Result[id.xy] = float4(1, 0, 0, 1);
}
発生した問題1
早速上のコードをビルドしてブラウザで見てみると…

こんな感じのエラーが出ます.
htdocs.framework.js:9 IndexOutOfRangeException: Invalid kernelIndex (0) passed, must be non-negative less than 0.
もちろん,KernelIndexも調べてみましたが,0未満ではありませんでした.
原因・解決1
Unity 6なので,新しすぎて情報がなくて苦労しましたが,以下の動画で説明してくれていました(これ見たらこの記事意味ないかも…).
結論としては,Graphics APIの設定が間違えていました.
Unity 6では新たにWebGPUに対応したらしく,Compute ShaderはWebGL 2では利用できないようです.なので,Graphic APIをWebGPUに変える必要があります.ただし,現段階(2024/11/11)では正式対応ではなく,デフォルトでは隠れていて使用できないようです.しばらくしたら,デフォルトで選択できるようになるそうです.
以下に利用する手順を示しておきます.
WebGPUを使えるようにする
まず,ProjectSettings.assetを書き換えます.場所は,プロジェクトが置かれているフォルダ->ProjectSettings->ProjectSettings.asset
です.見つけたら適当なエディタで開いて,以下の画像のようにwebGLEnableWebGPU
をTrue(1)
にしてあげます.

Graphics APIをWebGPUにする
次はUnityのeditorに戻って,APIの設定を変更します.場所はおなじみのPlayer settingで変更します.
場所は,Build Project->Player Settings->Other Settings->Graphics APIs
です.開けたら以下の手順で設定します.
- Auto Graphics APIのチェックを外す
- WebGPUをAPIsのリストに追加
- WebGPUをWebGL2の上に持ってくる.

問題2
先程のInvalid kernelIndex
エラーは消えましたね.
しかし,Texture Formatの問題が残っています.

エラー内容としては以下です.
The layout's binding format (TextureFormat::RGBA8Unorm) doesn't match the shader's binding format (TextureFormat::RGBA32Float).
原因・解決法2
Render Textureのインスタンスを作成する際,カラーフォーマットを指定しないと,プラットフォームに合わせて,自動で選んでくれるようです.なので,明示的にカラーフォーマットを指定して合わせてあげます.修正しコードを以下に示します.
using UnityEngine;
using UnityEngine.UI;
public class ComputeShaderExample : MonoBehaviour
{
public ComputeShader computeShader;
private RenderTexture renderTexture;
void Start()
{
// renderTexture = new RenderTexture(256, 256, 0);ここを以下のように変更.
renderTexture = new RenderTexture(256, 256, 0, RenderTextureFormat.ARGBFloat);
renderTexture.enableRandomWrite = true;
renderTexture.Create();
computeShader.SetTexture(0, "Result", renderTexture);
int threadGroupsX = renderTexture.width / 8;
int threadGroupsY = renderTexture.height / 8;
computeShader.Dispatch(0, threadGroupsX, threadGroupsY, 1);
GetComponent<RawImage>().texture = renderTexture;
}
void OnDestroy()
{
if (renderTexture != null)
renderTexture.Release();
}
}
#pragma kernel CSMain
RWTexture2D<float4> Result;
[numthreads(8, 8, 1)]
void CSMain (uint3 id : SV_DispatchThreadID) {
Result[id.xy] = float4(1, 0, 0, 1);
}
結果
今度はいい感じに動きました.

おわりに
情報が少なくて自分は苦労したので,同じ様に困っている方の参考になれば幸いです.
今回使用したプロジェクトは,一応GitHubに置いておいたので,ご自由にお使いください.

コメント