Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」

5,584 views

Published on

TechBuzzの第9回cocos2d-x勉強会での発表資料
https://atnd.org/events/61374

Published in: Software
  • Be the first to comment

【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」

  1. 1. シェーダ 書いてますか? 2015/01/27(Tue) Ryo Tsuruda
  2. 2. Agenda ● 自己紹介 ● 本日の目的 ● シェーダとは ● シェーダを見てみる ● シェーダを書いてみる ● まとめ
  3. 3. 自己紹介
  4. 4. 自己紹介 ● 名前:りょう ● 趣味:猫とプログラミング ● 仕事:ゲーム作り ○ 今まではサーバ、インフラ、ネイティブアプリなど ※今回の内容は、仕事とは関係なく趣味での発表です
  5. 5. 本日の目的
  6. 6. 本日の目的 ● シェーダとは何か?を知る ● Cocos2d-xでシェーダを書けるようになる ● シェーダの仕組みの理解 やらないこと
  7. 7. 注意事項 ● シェーダのプロではないので、質問など答えら れない場合もあります ● Android/iOSで動作させるための OpenGL ES のプログラマブルシェーダついての説明です ● Cocos2d-x v3.xでのみ動作確認しています
  8. 8. シェーダとは
  9. 9. シェーダとは ● GPUに命令して処理させるもの ● スクリーンに表示させる色を制御するもの 床井研究室 http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090827
  10. 10. シェーダとは 書いたことがある方?
  11. 11. シェーダの例 ● トゥーンシェーダ ● ファーシェーダ ● 他多数
  12. 12. シェーダの例 (cont.)
  13. 13. シェーダの例 (cont.) !?
  14. 14. シェーダの言語 ● シェーダを書くために必要な言語 ○ GLSL(OpenGL Shading Language) ○ GLSL ES (OpenGL for Embedded System) ● 他には、 ○ DirectX : HLSL(High Level Shading Language) ○ NVIDIA : Cg ○ iOS : Metal Shading Language
  15. 15. シェーダの言語 ● Cocos2d-xではどの言語を使っていますか? ○ C++ ? ○ Lua ? ○ JavaScript ? ● どのbindingからも利用できます
  16. 16. シェーダの処理の流れ 1. ノードを作成 (Sprite::create()) 2. バーテックスシェーダ(Vertex Shader) ○ 頂点シェーダとも 3. フラグメントシェーダ(Fragment Shader) ○ ピクセルシェーダとも  4. 画面に表示 複数のシェーダで 処理
  17. 17. シェーダを見てみる
  18. 18. バーテックスシェーダ(Sprite) const char* ccPositionTextureColor_noMVP_vert = STRINGIFY( attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; n#ifdef GL_ESn varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; n#elsen varying vec4 v_fragmentColor; varying vec2 v_texCoord; n#endifn void main() { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; } ); ccShader_PositionTextureColor_noMVP.vert
  19. 19. フラグメントシェーダ(Sprite) const char* ccPositionTextureColor_noMVP_frag = STRINGIFY( n#ifdef GL_ESn precision lowp float; n#endifn varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); } ); ccShader_PositionTextureColor_noMVP.frag
  20. 20. バーテックスシェーダ(解説) attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; void main() { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; } attribute Cocos2d-xからバーテックスシェーダに渡される値 vec4 a_position 頂点情報 (Cocos2d-xでbindingしている変数) vec2 a_texCoord テクスチャのマッピング情報 (Cocos2d-xでbindingしている変数) vec4 a_color 色情報 (Cocos2d-xでbindingしている変数)
  21. 21. バーテックスシェーダ(解説) attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; void main() { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; } varying フラグメントシェーダに渡すための値 lopw / mediump 値の精度(floatとかdoubleと同じ) vec4 v_fragmentColor 色情報 vec4 v_texCoord テクスチャの情報
  22. 22. バーテックスシェーダ(解説) attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; void main() { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; } main() 最初に呼ばれる関数 gl_Position OpenGLで処理するポジション情報 CC_PMatrix 座標情報を調整するための変数 (Cocos2d-xでbindingしている変数)
  23. 23. フラグメントシェーダ(解説) precision lowp float; varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); } precision 精度の定義
  24. 24. フラグメントシェーダ(解説) precision lowp float; varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); } varying フラグメントシェーダから渡される値 vec4 v_fragmentColor 色情報 vec4 v_texCoord テクスチャの情報
  25. 25. フラグメントシェーダ(解説) precision lowp float; varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); } main() 最初に呼ばれる関数 gl_FragColor OpenGLで処理する色情報 CC_Texture0 テクスチャの情報(Cocos2d-xでbindingしている変数) texture2D() テクスチャから指定座標の色情報を抜き出す
  26. 26. Cocos2d-xで定義されている変数 // uniform names const char* GLProgram::UNIFORM_NAME_AMBIENT_COLOR = "CC_AmbientColor"; const char* GLProgram::UNIFORM_NAME_P_MATRIX = "CC_PMatrix"; const char* GLProgram::UNIFORM_NAME_MV_MATRIX = "CC_MVMatrix"; const char* GLProgram::UNIFORM_NAME_MVP_MATRIX = "CC_MVPMatrix"; const char* GLProgram::UNIFORM_NAME_NORMAL_MATRIX = "CC_NormalMatrix"; const char* GLProgram::UNIFORM_NAME_TIME = "CC_Time"; const char* GLProgram::UNIFORM_NAME_SIN_TIME = "CC_SinTime"; const char* GLProgram::UNIFORM_NAME_COS_TIME = "CC_CosTime"; const char* GLProgram::UNIFORM_NAME_RANDOM01 = "CC_Random01"; const char* GLProgram::UNIFORM_NAME_SAMPLER0 = "CC_Texture0"; const char* GLProgram::UNIFORM_NAME_SAMPLER1 = "CC_Texture1"; const char* GLProgram::UNIFORM_NAME_SAMPLER2 = "CC_Texture2"; const char* GLProgram::UNIFORM_NAME_SAMPLER3 = "CC_Texture3"; const char* GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE = "CC_alpha_value"; // Attribute names const char* GLProgram::ATTRIBUTE_NAME_COLOR = "a_color"; const char* GLProgram::ATTRIBUTE_NAME_POSITION = "a_position"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD = "a_texCoord"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD1 = "a_texCoord1"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD2 = "a_texCoord2"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD3 = "a_texCoord3"; const char* GLProgram::ATTRIBUTE_NAME_NORMAL = "a_normal"; const char* GLProgram::ATTRIBUTE_NAME_BLEND_WEIGHT = "a_blendWeight"; const char* GLProgram::ATTRIBUTE_NAME_BLEND_INDEX = "a_blendIndex";
  27. 27. シェーダを書いてみる
  28. 28. 真っ赤にしてみる attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; void main() { gl_Position = CC_PMatrix * a_position; - v_fragmentColor = a_color; + v_fragmentColor = vec4(1.0, 0.0, 0.0, 1.0); v_texCoord = a_texCoord; } バーテックスシェーダ
  29. 29. ?確かに赤いけど、真っ赤ではない
  30. 30. バーテックスシェーダの役割 ● 頂点を決める ○ ポリゴンの頂点をどの位置に表示するか ○ 表示する色を決めるのはフラグメントシェーダ void main() { gl_Position = CC_PMatrix * a_position; - v_fragmentColor = a_color; + v_fragmentColor = vec4(1.0, 0.0, 0.0, 1.0); v_texCoord = a_texCoord; } フラグメントシェーダに色情報を渡 しているだけ
  31. 31. 次こそ、真っ赤にしてみる precision lowp float; varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { - gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } 表示される色を赤色に変更 (他の色情報は破棄)
  32. 32. 真っ赤になった シェーダが違う
  33. 33. 次はどうなるでしょうか? precision lowp float; varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { - gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); + gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, vec2(v_texCoord.x/2.0, v_texCoord.y); } テクスチャから抽出する座標を変更
  34. 34. 見た目が半分なった
  35. 35. シェーダの書き方 ● とにかく試行錯誤 ○ コンパイルエラーを出してくれる ○ 型には厳密 ● 感覚 ○ 少しの調整で大きく変わることもある cocos2d: ERROR: 0:21: No matching function for call to texture2D(sampler2D, float) ERROR: 0:21: '/' does not operate on 'float' and 'int'
  36. 36. シェーダの書き方 (cont.) ● 動的コンパイル ○ アプリのビルド時ではなく、実行時にコンパイル ○ コンパイルしたデータはキャッシュすること ○ リソースではなく、文字列としてコードに埋める ■ I/O待ちが発生するためCocos2d-xはこうしている ● デバッグ難しい ○ 実行して、コンパイルエラーをチェックしている ○ WebGLを試せるWebサービスなどで動作チェック ○ http://glslsandbox.com ● 実機で確認 ○ GPUを使っているので、実機での確認必須
  37. 37. 自作シェーダの適用 // スプライトの作成 auto sprite = Sprite::create("HelloWorld.png"); this->addChild(sprite); // シェーダの読込みと適用 auto glProgram = GLProgram::createWithFilenames("shader.vert", "shader.frag"); auto glProgramState = GLProgramState::getOrCreateWithGLProgram(glProgram); sprite->setGLProgramState(glProgramState); // uniformに値を代入 glProgramState->setUniformVec2("touchPosition", touchPosition); uniform プログラムからバーテックスシェーダやフラグメントシェーダに渡される値
  38. 38. グレイスケール(vert) attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord; varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; void main(void) { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; }
  39. 39. グレイスケール(frag) precision lowp float; varying vec4 v_fragmentColor; varying vec2 v_texCoord; // Gray scale(RGB) const vec3 grayScale = vec3(0.298912, 0.586611, 0.114478); void main(void) { vec4 color = texture2D(CC_Texture0, v_texCoord); float grayScaleColor = dot(color.rgb, grayScale); gl_FragColor = vec4(vec3(grayScaleColor), color.a); }
  40. 40. グレイスケール
  41. 41. ブラー(vert) varying vec2 v_texCoord; varying vec2 v_blurTexCoords[14]; uniform float u_rate; void main() { gl_Position = CC_PMatrix * a_position; v_texCoord = a_texCoord; v_blurTexCoords[ 0] = v_texCoord + vec2(-0.028 * u_rate, 0.0); v_blurTexCoords[ 1] = v_texCoord + vec2(-0.024 * u_rate, 0.0); v_blurTexCoords[ 2] = v_texCoord + vec2(-0.020 * u_rate, 0.0); v_blurTexCoords[ 3] = v_texCoord + vec2(-0.016 * u_rate, 0.0); v_blurTexCoords[ 4] = v_texCoord + vec2(-0.012 * u_rate, 0.0); v_blurTexCoords[ 5] = v_texCoord + vec2(-0.008 * u_rate, 0.0); v_blurTexCoords[ 6] = v_texCoord + vec2(-0.004 * u_rate, 0.0); v_blurTexCoords[ 7] = v_texCoord + vec2( 0.004 * u_rate, 0.0); v_blurTexCoords[ 8] = v_texCoord + vec2( 0.008 * u_rate, 0.0); v_blurTexCoords[ 9] = v_texCoord + vec2( 0.012 * u_rate, 0.0); v_blurTexCoords[10] = v_texCoord + vec2( 0.016 * u_rate, 0.0); v_blurTexCoords[11] = v_texCoord + vec2( 0.020 * u_rate, 0.0); v_blurTexCoords[12] = v_texCoord + vec2( 0.024 * u_rate, 0.0); v_blurTexCoords[13] = v_texCoord + vec2( 0.028 * u_rate, 0.0); }
  42. 42. ブラー(frag) varying vec2 v_texCoord; varying vec2 v_blurTexCoords[14]; void main() { gl_FragColor = vec4(0.0); gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 0])*0. 0044299121055113265; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 1])*0.00895781211794; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 2])*0.0215963866053; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 3])*0.0443683338718; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 4])*0.0776744219933; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 5])*0.115876621105; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 6])*0.147308056121; gl_FragColor += texture2D(CC_Texture0, v_texCoord )*0.159576912161; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 7])*0.147308056121; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 8])*0.115876621105; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[ 9])*0.0776744219933; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[10])*0.0443683338718; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[11])*0.0215963866053; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[12])*0.00895781211794; gl_FragColor += texture2D(CC_Texture0, v_blurTexCoords[13])*0. 0044299121055113265;
  43. 43. ブラー
  44. 44. ノイズ(vert) attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord; #ifdef GL_ES varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; #else varying vec4 v_fragmentColor; varying vec2 v_texCoord; #endif void main(void) { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; }
  45. 45. ノイズ(frag) varying vec4 v_fragmentColor; varying vec2 v_texCoord; uniform vec2 resolution; const float intensity = 0.05; vec3 noise(vec2 uv) { vec2 p = abs(sin(uv * 13.0 + uv.x * CC_Time[1] * sin(uv.y))); return vec3(sin (0.2 * CC_Time[1] + sin(p * 0.5) * CC_Time[1] / cos(50.0)) * 10.0,0.3+0.5 * abs(sin (CC_Time[1] * tan(5.0)))); } void main(void) { gl_FragColor.xyz = intensity * noise(gl_FragCoord.xy / sin(resolution.xy * CC_Time[1] * 0.01)) + (1. - intensity) * texture2D(CC_Texture0,v_texCoord.xy).xyz; gl_FragColor.w = 1.; }
  46. 46. ノイズ
  47. 47. 旗(vert) attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord; #ifdef GL_ES varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; #else varying vec4 v_fragmentColor; varying vec2 v_texCoord; #endif void main(void) { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; }
  48. 48. 旗(frag) #ifdef GL_ES precision mediump float; #endif varying vec2 v_texCoord; void main( void ) { float len = length(v_texCoord); vec2 uv = vec2(v_texCoord.x - (v_texCoord.x / len) * cos(len - CC_Time[1]) * 0.05, v_texCoord.y - (v_texCoord.y / len) * sin(len * 12.0 - CC_Time[1] * 7.0) * 0.05); gl_FragColor = texture2D(CC_Texture0, uv); }
  49. 49.
  50. 50. 波(vert) attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord; #ifdef GL_ES varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; #else varying vec4 v_fragmentColor; varying vec2 v_texCoord; #endif void main(void) { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; }
  51. 51. 波(frag) #ifdef GL_ES precision highp float; #endif uniform vec2 resolution; uniform vec2 touchPosition; varying vec2 v_texCoord; void main(void) { vec2 tc = v_texCoord; vec2 p = vec2(tc.x-touchPosition.x, tc.y-touchPosition.y); float len = length(p); vec2 uv = tc + (p / len) * cos(len * 14.0 - CC_Time[1] * 8.0) * 0.04; vec3 col = texture2D(CC_Texture0, uv).xyz; gl_FragColor = vec4(col, 1.0); }
  52. 52.
  53. 53. GLES Sandboxより(vert) attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord; #ifdef GL_ES varying lowp vec4 v_fragmentColor; varying mediump vec2 v_texCoord; #else varying vec4 v_fragmentColor; varying vec2 v_texCoord; #endif void main(void) { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; }
  54. 54. GLES Sandboxより(frag) http://glslsandbox.com/e#22390.2
  55. 55. 画像が別物に
  56. 56. まとめ
  57. 57. まとめ ● 次のステップに向けて ○ 今回は超基本なので、本格的なものは勉強が必要 ○ 数学の知識が必要となることが多いです ● 差別化 ○ シェーダを自作すると、大きな差別化を図れる ○ コンソール出身の方が作るゲームには自作シェーダが 多いのではないでしょうか

×