Amazon Sumerian Tutorial 48:Custom Shader

こんにちは、ナレコム前川です。

今回は、Amazon Sumerian の公式チュートリアルの Custom Shader を進めていきたいと思います。

ここで学ぶことは

・Custom Shader について

・Material について

・Scripting について

の3つです。

それでは、進めていきましょう。

1. シーンの作成

① ダッシュボードからDefault Lightingを選択。

① ダッシュボードからDefault Lightingを選択。

② シーン名を「Custom Shader」に設定し、作成。

③ Create Entity から Box を追加。

③ 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 が追加されます。

実行すると、以下のようになると思います。

今回のチュートリアルは以上です。

お疲れ様でした。

この記事を書いた人

aws-recipe-user