シェーダーの話
シェーダーについて調べるページ
サンプルコード HSP ver3.7ベータ4
;HSP3.7b4にて動作確認
#include "hgimg4.as" ;hgimg4
screen 0,640,480
setcls CLSMODE_SOLID, $000000 ; 画面クリア設定
gpreset
//カメラ位置
setpos id_camera,0,100,200
gplookat id_camera,0,0,0
//モデル読込
gpload id_model,"res/wave.gpb"//格子に波のテクスチャを張ったモデルを読込
//マテリアルID取得
gpnodeinfo id_mat,id_model2, GPNODEINFO_MATERIAL,"obj1"//モデルのメッシュに対応するマテリアル
//時間管理の変数
time=0.0f
//メイン処理-----------------------------------------
*main
redraw 0
gpmatprm1 id_mat,"u_time",time/2000;頂点シェーダーのuniform変数[u_time]へパラメータを渡す
time++
gpdraw ; 3D描画更新
redraw 1
await 1000/60
goto *main
//--------------------------------------------------
頂点シェーダー(textured_wave.vert)
#ifndef DIRECTIONAL_LIGHT_COUNT
#define DIRECTIONAL_LIGHT_COUNT 0
#endif
#ifndef SPOT_LIGHT_COUNT
#define SPOT_LIGHT_COUNT 0
#endif
#ifndef POINT_LIGHT_COUNT
#define POINT_LIGHT_COUNT 0
#endif
#if (DIRECTIONAL_LIGHT_COUNT > 0) || (POINT_LIGHT_COUNT > 0) || (SPOT_LIGHT_COUNT > 0)
#define LIGHTING
#endif
///////////////////////////////////////////////////////////
// Atributes
attribute vec4 a_position;
#if defined(SKINNING)
attribute vec4 a_blendWeights;
attribute vec4 a_blendIndices;
#endif
attribute vec2 a_texCoord;
#if defined(LIGHTMAP)
attribute vec2 a_texCoord1;
#endif
#if defined(LIGHTING)
attribute vec3 a_normal;
#if defined(BUMPED)
attribute vec3 a_tangent;
attribute vec3 a_binormal;
#endif
#endif
///////////////////////////////////////////////////////////
// Uniforms
uniform mat4 u_worldViewProjectionMatrix;
uniform float u_time;
#if defined(SKINNING)
uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
#endif
#if defined(LIGHTING)
uniform mat4 u_inverseTransposeWorldViewMatrix;
#if defined(SPECULAR) || (POINT_LIGHT_COUNT > 0) || (SPOT_LIGHT_COUNT > 0)
uniform mat4 u_worldViewMatrix;
#endif
#if defined(BUMPED) && (DIRECTIONAL_LIGHT_COUNT > 0)
uniform vec3 u_directionalLightDirection[DIRECTIONAL_LIGHT_COUNT];
#endif
#if (POINT_LIGHT_COUNT > 0)
uniform vec3 u_pointLightPosition[POINT_LIGHT_COUNT];
#endif
#if (SPOT_LIGHT_COUNT > 0)
uniform vec3 u_spotLightPosition[SPOT_LIGHT_COUNT];
#if defined(BUMPED)
uniform vec3 u_spotLightDirection[SPOT_LIGHT_COUNT];
#endif
#endif
#if defined(SPECULAR)
uniform vec3 u_cameraPosition;
#endif
#endif
#if defined(TEXTURE_REPEAT)
uniform vec2 u_textureRepeat;
#endif
#if defined(TEXTURE_OFFSET)
uniform vec2 u_textureOffset;
#endif
#if defined(CLIP_PLANE)
uniform mat4 u_worldMatrix;
uniform vec4 u_clipPlane;
#endif
///////////////////////////////////////////////////////////
// Varyings
varying vec2 v_texCoord;
#if defined(LIGHTMAP)
varying vec2 v_texCoord1;
#endif
#if defined(LIGHTING)
#if !defined(BUMPED)
varying vec3 v_normalVector;
#endif
#if defined(BUMPED) && (DIRECTIONAL_LIGHT_COUNT > 0)
varying vec3 v_directionalLightDirection[DIRECTIONAL_LIGHT_COUNT];
#endif
#if (POINT_LIGHT_COUNT > 0)
varying vec3 v_vertexToPointLightDirection[POINT_LIGHT_COUNT];
#endif
#if (SPOT_LIGHT_COUNT > 0)
varying vec3 v_vertexToSpotLightDirection[SPOT_LIGHT_COUNT];
#if defined(BUMPED)
varying vec3 v_spotLightDirection[SPOT_LIGHT_COUNT];
#endif
#endif
#if defined(SPECULAR)
varying vec3 v_cameraDirection;
#endif
#include "lighting.vert"
#endif
#if defined(SKINNING)
#include "skinning.vert"
#else
#include "skinning-none.vert"
#endif
#if defined(CLIP_PLANE)
varying float v_clipDistance;
#endif
void main()
{
vec4 position = getPosition();
position[1] += sin(position[0] + u_time* 100);
gl_Position = u_worldViewProjectionMatrix * position;
#if defined(LIGHTING)
vec3 normal = getNormal();
// Transform the normal, tangent and binormals to view space.
mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz, u_inverseTransposeWorldViewMatrix[1].xyz, u_inverseTransposeWorldViewMatrix[2].xyz);
vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * normal);
#if defined(BUMPED)
vec3 tangent = getTangent();
vec3 binormal = getBinormal();
vec3 tangentVector = normalize(inverseTransposeWorldViewMatrix * tangent);
vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * binormal);
mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x, tangentVector.y, binormalVector.y, normalVector.y, tangentVector.z, binormalVector.z, normalVector.z);
applyLight(position, tangentSpaceTransformMatrix);
#else
v_normalVector = normalVector;
applyLight(position);
#endif
#endif
v_texCoord = a_texCoord;
#if defined(TEXTURE_REPEAT)
v_texCoord *= u_textureRepeat;
#endif
#if defined(TEXTURE_OFFSET)
v_texCoord += u_textureOffset;
#endif
#if defined(LIGHTMAP)
v_texCoord1 = a_texCoord1;
#endif
#if defined(CLIP_PLANE)
v_clipDistance = dot(u_worldMatrix * position, u_clipPlane);
#endif
}
.materialファイルの覚書
①ユニフォーム変数への値の受け渡し定義(デフォルト抜粋)
u_worldViewProjectionMatrix = WORLD_VIEW_PROJECTION_MATRIX sampler u_diffuseTexture u_ambientColor = 0.6, 0.6, 0.6 u_cameraPosition = CAMERA_WORLD_POSITION u_inverseTransposeWorldViewMatrix = INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX u_specularExponent = 1②techniqueのdefine部分
technique { pass { defines = DIRECTIONAL_LIGHT_COUNT 1;BILL_Y 1;BILL_X 1 ←ユーザー定義を使用したい場合には「定義名 値」を「;」セミコロンで区切る } }シェーダー側では、
#if defined(BILL_Y) && (BILL_X) ←定義名が有効かどうか判断するプリコンパイル ~~プログラム #endifGLSLは、列優先の行列
Unityの「シェーダー」は行優先行列らしい。
https://hsp.tv/play/pforum.php?mode=all&num=100811
https://edom18.hateblo.jp/entry/2019/01/04/153205
(引用)
行列の掛ける順番の意味
最後に、行列の掛ける順番について。
3Dグラフィクスでは行列が頻繁に使われ、特に、頂点シェーダからフラグメントシェーダに値を渡す際、一般的な合成行列を掛けて渡します。
具体的には以下の行列です。
モデル座標変換行列
ビュー座標変換行列
プロジェクション変換行列
そしてそれぞれの行列をひとつに「合算」させたものをシェーダに送り、それを各頂点に掛け算してフラグメントシェーダステージに渡す、というのが基本的な動作です。
そしてこれらの行列の頭文字を取ってM(odel) x V(iew) x P(rojection)でMVP行列、なんて呼ばれたりします。
しかしこれ、行オーダーで計算を行うAPI規則に基づくものです。(つまりDirectX)
Unityでは、上で示したように「列オーダー」となります。
そのため掛ける順番がMVPではなくPVMとなる点に注意が必要です。