164
146

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

threejsでGLSLをいじるための基礎知識

Last updated at Posted at 2015-03-25

threejsでShaderMaterialとかを使うと、自分で直接GLSLをいじれる。
そのためのメモ。

##入出力
###VertexShader

  • 入力 なし
  • 出力 gl_Position (vec4) _ 2次元平面上の頂点座標
  • 出力 gl_PointSize (float) _ 点のサイズ

###FragmentShader

  • 入力 gl_FrontFacing (bool) ポリゴンの表裏のブール値
  • 入力 gl_FragCoord (vec4) ウィンドウ座標=canvas上の座標 (x,y,z, 1/w)
  • 入力 gl_PointCoord (vec2) ポイントスプライト時の2次元座標
  • 出力 gl_FragColor (vec4) ピクセルの描画色
  • 出力 gl_FragData[] ([]) glDrawBuffersとかで使う配列データ

これら以外はuniform

##GLSL ES上で扱われる型

  • int (整数)
  • ivec2,ivec3,ivec4 (intのベクトル)
  • bool (ブール)
  • bvec2,bvec3,bvec4 (boolのベクトル)
  • float
  • vec2,vec3,vec4 (floatのベクトル)
  • mat2,mat3,mat4 (行列)
  • sampler2D (2次元テクスチャ)
  • samplerCube (3次元テクスチャ)

##threejsによって既に定義されている変数

変数名 説明
modelMatrix オブジェクト座標からワールド座標へ変換する
viewMatrix ワールド座標から視点座標へ変換
modelViewMatrix modelMatrixとviewMatrixの積算
projectionMatrix カメラの各種パラメータから3次元を2次元に射影し、クリップ座標系に変換する行列
cameraPosition カメラの位置
normalMatrix 頂点法線ベクトルを視点座標系に変換する行列
position 頂点座標
normal 頂点法線ベクトル
uv テクスチャを貼るためのUV座標

バーテックスシェーダーでは全部使える。
フラグメントシェーダーでは,viewMatrixとcameraPositionのみ使える。
フラグメントシェーダー側で使うときはバーテックスシェーダ内でvarying変数に一旦いれたりする。vUv=vu; みたいな感じで。

##threejsからuniform/attributeを渡すとき指定する文字列(type)
よくつかいそうなのは

  • i (整数)
  • f (float)
  • v2 (THREE.Vector2)
  • v3 (THREE.Vector3)
  • v4 (THREE.Vector4)
  • c (THREE.Color)
  • m4 (THREE.Matrix4)
  • t (THREE.Texture)
uniform_type.js
var uniformsExample = {

"uInt" :  { type: "i", value: 1 },     // single integer
"uFloat" : { type: "f", value: 3.14 }, // single float

"uVec2" : { type: "v2", value: new THREE.Vector2( 0, 1 ) },       // single Vector2
"uVec3" : { type: "v3", value: new THREE.Vector3( 0, 1, 2 ) },    // single Vector3
"uVec4" : { type: "v4", value: new THREE.Vector4( 0, 1, 2, 3 ) }, // single Vector4

"uCol" : { type: "c", value: new THREE.Color( 0xffaa00 ) }, // single Color

"uMat4" : { type: "m4", value: new THREE.Matrix4() }, // single Matrix4


"uTex" :     { type: "t", value: THREE.ImageUtils.loadTexture( "texture.jpg" ) }, // regular texture
"uTexCube" : { type: "t", value: THREE.ImageUtils.loadTextureCube( [ "px.jpg", "nx.jpg", // cube texture
                                                                     "py.jpg", "ny.jpg", 
                                                                     "pz.jpg", "nz.jpg" ] ) },

"uIntArray"  : { type: "iv1", value: [ 1, 2, 3, 4, 5 ] },    // integer array (plain)
"uIntArray3" : { type: "iv", value: [ 1, 2, 3, 4, 5, 6 ] },   // integer array (ivec3)

"uFloatArray"  : { type: "fv1", value: [ 0.1, 0.2, 0.3, 0.4, 0.5 ] },    // float array (plain)
"uFloatArray3" : { type: "fv",  value: [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 ] }, // float array (vec3)

"uVec2Array" : { type: "v2v", value: [ new THREE.Vector2( 0.1, 0.2 ), 
                                       new THREE.Vector2( 0.4, 0.5 ) ] }, // Vector2 array

"uVec3Array" : { type: "v3v", value: [ new THREE.Vector3( 0.1, 0.2, 0.3 ), 
                                       new THREE.Vector3( 0.4, 0.5, 0.6 ) ] }, // Vector3 array

"uVec4Array" : { type: "v4v", value: [ new THREE.Vector4( 0.1, 0.2, 0.3, 0.4 ), 
                                       new THREE.Vector4( 0.4, 0.5, 0.6, 0.7 ) ] }, // Vector4 array

"uMat4Array" : { type: "m4v", value: [ new THREE.Matrix4(), new THREE.Matrix4() ] }, // Matrix4 array

"uTexArray" : { type: "tv", value: [ new THREE.Texture(), new THREE.Texture() ] } // texture array (regular)
                                                                                              // texture units start from value

};

引用元: https://github.com/mrdoob/three.js/wiki/Uniforms-types

##座標変換と行列の関係性
オブジェクト座標系(ローカル座標系)
 ↓
*modelMatrix
 ↓
ワールド座標系
 ↓
*viewMatrix
 ↓
視点座標系(カメラから見た座標)
 ↓
*projectionMatrix
 ↓
クリップ座標系 = xyzを-1〜+1で表す座標系
 ↓
ウィンドウ座標系 = canvas上の座標系

##基本的なfragmentShader/vertexShader

vertexshader
varying vec2 vUv;// fragmentShaderに渡すためのvarying変数
void main()
{
  // 処理する頂点ごとのuv(テクスチャ)座標をそのままfragmentShaderに横流しする
  vUv = uv;
  // 変換:ローカル座標 → 配置 → カメラ座標
  vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);    
  // 変換:カメラ座標 → 画面座標
  gl_Position = projectionMatrix * mvPosition;
}

fragmentShader
//uniform 変数としてテクスチャのデータを受け取る
uniform sampler2D texture;
// vertexShaderで処理されて渡されるテクスチャ座標
varying vec2 vUv;                                             

void main()
{
  // テクスチャの色情報をそのままピクセルに塗る
  gl_FragColor = texture2D(texture, vUv);
}
js
var materialShaderSimple = new THREE.ShaderMaterial({            
  vertexShader: vartexShaderString
  fragmentShader: fragmentShaderString,
  uniforms: {
    texture: { type: 't', value: ImageUtils.loadTexture("**.png")}                                   }
});

※こちらを参考にしました。 http://izmiz.hateblo.jp/entry/2014/09/27/235743

##GLSL ES組み込み関数
覚えにくいものを抜粋

関数名 説明
sign(x) 符号判別、負:-1,ゼロ:0,正:1
fract(x) 小数の部分だけ返す
mod(x,y) x/yのあまり
clamp(x,y,a) クランプ処理min(max(x,y),a)
mix(x,y,a) 線形補間
smoothstep(edge0,edge1,x) xの要素のうち、edge0以下のものは0.0、edge1以上のものは1.0にする。xがedge0とedge1の間にあるときには、3次エルミート補間を返す。
step(a,x) x<aのとき0, x≧aのとき1
sqrt(x),inverssqrt(x) inversは1/sqrt(x)
normalize(x) 正規化
faceforward(N,I,Nref) 法線ベクトルNを条件により反転
reflect(I,N) 法線ベクトルNの面に対して入射ベクトルIの反射ベクトルを返す
refract(I,N,eta) 屈折率etaの法線ベクトルNの面に対し、
length(x) ベクトルの長さ=絶対値
distance(x,y) x,yの距離
dot(x,y) 内積
cross(x,y) 外積
texture2D(uTexture, texCoords) uTextureのtexCoords座標の色(vec4)を返す

参考:glsl辞典
http://ec.nikkeibp.co.jp/nsp/dl/08513/HTML5GAMES_AppC.pdf

##threejs内でshaderが格納されている場所

  • THREE.ShaderChunk = 共通で使われるGLSLのコード片
  • THREE.UniformsUtils = uniformsの定義を操作するユーティリティ関数群
  • THREE.UniformsLib = 共通で使われるuniforms定義
  • THREE.ShaderLib = 各マテリアルで使用するシェーダー定義
164
146
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
164
146

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?