cocos2d-x

cocos2d-x v3系で新しいシェーダを追加してみた

More than 1 year has passed since last update.

グレンジ Advent Calendar 2017 初日担当の mad_khaki です。
クライアントサイドを中心にサーバ / データ分析 等もやってます。

今回は cocos2d-x v3.2 でシェーダを追加する手順についてまとめました。

1. GLSLで頂点シェーダ書く

ccShader_GrayScale.vert
const char* ccGrayScale_vert = STRINGIFY(
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

\n#ifdef GL_ES\n
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
\n#else\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
\n#endif\n

void main()
{
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}
);

STRINGIFYマクロで文字列化しておく
ccShader_PositionTextureColor_noMVP.vertをそのまま使ってもよい

2. GLSLでフラグメントシェーダ書く

ccShader_GrayScale.frag
const char* ccGrayScale_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

void main()
{
    vec4 color = texture2D(CC_Texture0, v_texCoord);
    float alpha = color.a;
    float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
    gl_FragColor = vec4(gray, gray, gray, alpha);
}
);

STRINGIFYマクロで文字列化しておく
https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB
係数はWikipediaから適当に引っ張ってきた

3. ccShadersに定義を追加する

ccShaders.h
extern CC_DLL const GLchar * ccGrayScale_vert;
extern CC_DLL const GLchar * ccGrayScale_frag;
ccShaders.cpp
#include "ccShader_GrayScale.vert"
#include "ccShader_GrayScale.frag"

4. GLProgramクラスのstaticメンバに追加する

CCGLProgram.h
static const char* SHADER_GRAYSCALE;
CCGLProgram.cpp
const char* GLProgram::SHADER_GRAYSCALE = "ShaderGrayScale";

5. シェーダキャッシュに追加する

enumに追加

CCGLProgramCache.cpp
kShaderType_GrayScale

loadDefaultGLPrograms()に追加

3項で追加した文字列とシェーダの実体(GLProgram)の対応関係をマップで管理

CCGLProgramCache.cpp
GLProgram* p = new GLProgram();
loadDefaultGLProgram(p, kShaderType_GrayScale);
_programs.insert(std::make_pair(GLProgram::SHADER_GRAYSCALE, p));

loadDefaultGLProgram(GLProgram *p, int type)に追加

ここで1項、2項で文字列化されたシェーダがコンパイルされる

CCGLProgramCache.cpp
case kShaderType_GrayScale:
    p->initWithByteArrays(ccGrayScale_vert, ccGrayScale_frag);
    break;

reloadDefaultGLPrograms()に追加

CCGLProgramCache.cpp
p = getGLProgram(GLProgram::SHADER_GRAYSCALE);
p->reset();
loadDefaultGLProgram(p, kShaderType_GrayScale);

6. 実際にシェーダを設定する

CCSprite.cpp
setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_GRAYSCALE));