こんにちは、ナレコム前川です。
今回は、Amazon Sumerian の公式チュートリアルの Custom Shader を進めていきたいと思います。
ここで学ぶことは
・Custom Shader について
・Material について
・Scripting について
の3つです。
それでは、進めていきましょう。
1. シーンの作成
① ダッシュボードからDefault Lightingを選択。
① ダッシュボードからDefault Lightingを選択。
② シーン名を「Custom Shader」に設定し、作成。
③ Create Entity から Box を追加。
これでシーンの設定は終了です。
2. Shader Script の追加
これから Box に Script を追加していきます。
① Box を選択し、Script Component を追加。
① Box を選択し、Script Component を追加。
② + ボタンから Custom Script を選択。
1var setup = function (args, ctx) {23 // The vertex shader source as a string4 var vertexShader = [5 'attribute vec3 vertexPosition;',6 'uniform mat4 viewProjectionMatrix;',7 'uniform mat4 worldMatrix;',8 'void main(void) {',9 ' gl_Position = viewProjectionMatrix * (worldMatrix * vec4(vertexPosition, 1.0));',10 '}'11 ].join('\n');1213 // The fragment shader source as a string14 var fragmentShader = [15 'void main(void){',16 ' gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);',17 '}'18 ].join('\n');1920 // The shader definition provides fragment and vertex shader source, as21 // well as a list of attributes, defines, uniforms, etc., that the engine22 // needs to use your shader.23 var shaderDefinition = {24 attributes: {25 vertexPosition: sumerian.MeshData.POSITION26 },27 uniforms: {28 viewProjectionMatrix: sumerian.Shader.VIEW_PROJECTION_MATRIX,29 worldMatrix: sumerian.Shader.WORLD_MATRIX30 },31 vshader: vertexShader,32 fshader: fragmentShader33 };3435 // Create a Material from the shader definition.36 ctx.material = new sumerian.Material(shaderDefinition);3738 // Save the current material for later.39 ctx.oldMaterial = ctx.entity.meshRendererComponent.materials[0];4041 // Put the material on the entity.42 ctx.entity.meshRendererComponent.materials[0] = ctx.material;43};4445var update = function (args, ctx) {4647};4849var cleanup = function (args, ctx) {50 // Put the old material back on the entity51 ctx.entity.meshRendererComponent.materials[0] = ctx.oldMaterial;52};5354var parameters = [];⑤ 保存して、エディタを閉じる。
再生ボタンをクリックして、シーンを実行してみてください。
実行すると影のない真っ白な Box が表示されると思います。
※ Mac を使用している方は、以下のコードを使用する必要があります。
1// The vertex shader source as a string2var vertexShader = [3'attribute vec3 vertexPosition;',4'uniform mat4 viewProjectionMatrix;',5'uniform mat4 worldMatrix;',6'void main(void) {',7' gl_Position = viewProjectionMatrix * (worldMatrix * vec4(vertexPosition, 1.0));',8'}'9].join('\n');1011// The fragment shader source as a string12var fragmentShader = [13'void main(void){',14 ' gl_FragColor = vec4(1,1,1, 1);',15'}'16].join('\n');1718// The shader definition provides fragment and vertex shader source, as19// well as a list of attributes, defines, uniforms, etc., that the engine20// needs to use your shader.21var shaderDefinition = {22defines: {23 PI: Math.PI // <-- add define here24},25attributes: {26 vertexPosition: sumerian.MeshData.POSITION,27},28uniforms: {29 viewProjectionMatrix: sumerian.Shader.VIEW_PROJECTION_MATRIX,30 worldMatrix: sumerian.Shader.WORLD_MATRIX,31},32vshader: vertexShader,33fshader: fragmentShader34};3. Shader を Plasma Shader にアップデート
vertexShader、_fragmentShader、および shaderDefinition を次のものに置き換えます。
vertexShader
1var vertexShader = [2 'attribute vec2 vertexUV0;', // <-- add UV coords3 'attribute vec3 vertexPosition;',4 'uniform mat4 viewProjectionMatrix;',5 'uniform mat4 worldMatrix;',6 'varying vec2 texCoord0;', // <-- add varying7 'void main(void) {',8 ' texCoord0 = vertexUV0;', // <-- assign the vertex UV coordinate to the varying9 ' gl_Position = viewProjectionMatrix * (worldMatrix * vec4(vertexPosition, 1.0));',10 '}'11].join('\n');fragmentShader
1var fragmentShader = [2 'uniform float time;', // <-- add3 'uniform vec2 k;', // <-- add4 'varying vec2 texCoord0;', // <-- add5 'void main(void){',6 ' float v = 0.0;', // <-- add all of these magic formulas7 ' vec2 c = texCoord0 * k - k/2.0;',8 ' v += sin(c.x + time);',9 ' v += sin((c.y + time)/2.0);',10 ' v += sin((c.x+c.y + time)/2.0);',11 ' c += k/2.0 * vec2(sin(time/3.0), cos(time/2.0));',12 ' v += sin(sqrt(c.x*c.x+c.y*c.y+1.0) + time);',13 ' v = v/2.0;',14 ' vec3 col = vec3(1, sin(PI*v), cos(PI*v));',15 ' gl_FragColor = vec4(col*.5 + .5, 1);',16 '}'17].join('\n');shaderDefinition
1var shaderDefinition = {2 defines: {3 PI: Math.PI // <-- add define here4 },5 attributes: {6 vertexPosition: sumerian.MeshData.POSITION,7 vertexUV0: sumerian.MeshData.TEXCOORD0 // <-- grab the UV coords from the mesh8 },9 uniforms: {10 viewProjectionMatrix: sumerian.Shader.VIEW_PROJECTION_MATRIX,11 worldMatrix: sumerian.Shader.WORLD_MATRIX,12 time: 0, // <-- add the time uniform13 k: [20,20] // <-- pass the vec2 value directly, as an array14 },15 vshader: vertexShader,16 fshader: fragmentShader17};最後に update 関数を編集します。
1var update = function (args, ctx) {2 // Pass the current time via uniforms to the shader.3 // This will override the "time" uniform on the shader.4 ctx.material.uniforms.time = ctx.world.time; // <-- add this!5};4. シーンを実行する
それでは、シーンを実行してみてください。
シーンが再生されると setup 関数が呼ばれ、Box に Shader が追加されます。
実行すると、以下のようになると思います。
今回のチュートリアルは以上です。
お疲れ様でした。