結論のソースコード
let myShader;
let vertCode;
let fragCode;
function preload() {
// 頂点シェーダーは変更しないので事前に読み込む
vertCode = `
precision highp float;
// p5.jsのデフォルトの頂点位置属性
attribute vec3 aPosition;
void main() {
gl_Position = vec4(aPosition, 1.0);
}
`;
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
// 初期シェーダーを設定
fragCode = `
precision highp float;
void main() {
vec3 color = vec3(0.0, 0.0, 1.0);
gl_FragColor = vec4(color, 1.0);
}
`;
myShader = createShader(vertCode, fragCode);
shader(myShader); // なぜかshader()を実行しないとコンパイルされない
}
function draw() {
background(220);
myShader.setUniform("u_time", millis() / 1000.0);
noStroke();
shader(myShader);
quad(-1, -1, -1, 1, 1, 1, 1, -1);
resetShader();
}
function mouseClicked() {
console.log("mouseClicked");
// シェーダーを切り替える
fragCode = `
precision highp float;
uniform float u_time;
uniform vec2 u_mouse;
void main() {
vec3 color = vec3(sin(u_time) * 0.5 + 0.5, 0, 0);
gl_FragColor = vec4(color, 1.0);
あえてエラーを起こすコード
}
`;
const compilingShader = createShader(vertCode, fragCode);
shader(compilingShader); // shaderを実行しないとコンパイルされない
// コンパイルエラーのチェック
const gl = compilingShader._renderer.GL;
const frag_compile_status = gl.getShaderParameter(
compilingShader._fragShader,
gl.COMPILE_STATUS
);
if (frag_compile_status == false) {
print("shaderコンパイルエラー");
} else {
myShader = compilingShader;
}
}
マウスクリック時にエラーの出てしまうシェーダーに切り替えてしまいますが、コンパイルエラーを検出しています。
もしコンパイルエラー検出がなくて、myShader
にそのまま代入してしまうと、他の箇所でmyShader
を使うときにエラーが出てしまいます。
できなかったこと
-
try...catch
- p5js内部では、
console.error
を出しているだけなので、catchできません
- p5js内部では、
-
loadShader
の第四引数- https://p5js.org/reference/p5/loadShader/
- jsコード内でshaderのコードを書くのではなく、ファイルに保存してやる方法
- コンパイルエラーは関係なくファイルロードのエラーの検出なので、コンパイルエラーは検出されない
-
createCanvas
で取得するcanvasオブジェクトから、webgl2
の取得
myCanvas = p5.createCanvas(400, 400, p5.WEBGL);
gl = myCanvas.elt.getContext('webgl2'); // 中身がなかった
利用用途
- ユーザーにシェーダーファイルなどをアップロードさせて、即実行したいときとかに
- AIでシェーダーを書かせたいときに
ちなみにコンパイルエラーのメッセージ内容取得
const messageFrag = gl.getShaderInfoLog(myShader._fragShader);
こんな感じで取得できました
作ったものでは、AIが作ったコードのコンパイルエラーをまたエラーメッセージと一緒にAIへ渡して、コードを修正させてみています。
工夫ができそうです。