ユーザー指定のシェーダを使えるようにしよう

最近シェーダーアートが流行っています。プログラマがシェーダーを自作して、それを特定の3D環境で実行させて美麗な映像デモを作ることです。
こうしたことを実現するには、対象となる3D環境(3Dライブラリ)側が、ユーザーが作成したシェーダーコードを受け付けられなければなりません。

今回は、それをやっていきます。といっても、難しいことはありません。それまでライブラリ内で定義していたシェーダーコードをユーザー側に移すだけです。

// shader.tsから一部抜粋 export function initProgram(gl: WebGLRenderingContext, vertexShaderStr: string, fragmentShaderStr: string) { // <--変更 var vertexShader = compileShader(gl, ShaderType.Vertex, vertexShaderStr) as WebGLShader; var fragmentShader = compileShader(gl, ShaderType.Fragment, fragmentShaderStr) as WebGLShader; const shaderProgram = gl.createProgram() as WebGLProgram; if (shaderProgram == null) { alert('Failed to create WebGL program.'); return null; } gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("Could not initialise shaders"); return null } gl.useProgram(shaderProgram); shaderProgram._attributePosition = gl.getAttribLocation(shaderProgram, "a_position"); gl.enableVertexAttribArray(shaderProgram._attributePosition); return shaderProgram; }
// index.ts import { initWebGL } from "./context.js"; import { initProgram } from "./shader.js"; import { initBuffers } from "./buffer.js"; import { drawScene } from "./render.js"; export default function main(vertices: number[], vertexComponentNumber: number, vertexShaderStr: string, fragmentShaderStr: string) { // <--変更 const canvas = document.getElementById('world') as HTMLCanvasElement; const gl = initWebGL(canvas); if (gl == null) { return false; } const shaderProgram = initProgram(gl, vertexShaderStr, fragmentShaderStr); // <--変更 if (shaderProgram == null) { return false; } const vertexBuffer = initBuffers(gl, vertices, vertexComponentNumber); gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.enable(gl.DEPTH_TEST); drawScene(gl, vertexBuffer, shaderProgram); return true; }
// main.js import main from '../dist/index.js'; const vertexShaderStr = ` // <--追加 precision highp float; attribute vec3 a_position; void main(void) { gl_Position = vec4(a_position, 1.0); } `; const fragmentShaderStr = ` // <--追加 precision highp float; void main(void) { gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); // <--変更。せっかくなので色を青に変えてみましょう。 } `; const vertices = [ 0.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0 ] main(vertices, 3, vertexShaderStr, fragmentShaderStr); // <--変更

image.png

今回はとても簡単でしたね。

この時点のプロジェクトコードはここに公開しています 

3日目:ライブラリっぽくしてみよう

5日目:クラス構文を使ってもっとライブラリっぽくしよう