Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
128
Help us understand the problem. What is going on with this article?
@kitasenjudesign

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

More than 3 years have passed since last update.

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が格納されている場所

https://github.com/mrdoob/three.js/tree/master/src/renderers/shaders
* THREE.ShaderChunk = 共通で使われるGLSLのコード片
* THREE.UniformsUtils = uniformsの定義を操作するユーティリティ関数群
* THREE.UniformsLib = 共通で使われるuniforms定義
* THREE.ShaderLib = 各マテリアルで使用するシェーダー定義

128
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
128
Help us understand the problem. What is going on with this article?