【cococos 2 d】shaderを使用
32709 ワード
組み込みshaderの使用
cococos 2 d-xのshaderの作成と使用については、この記事のcococos 2 d-x shaderソースコード解析を参照してください.
まず、次に使用するいくつかの画像リソースをアップロードします.画像はネット上から来ています.この文章から参考にしてください.http://www.cocoachina.com/bbs/read.php?tid=1693873
ソース画像jpg
法線マップwater_normal.jpg
内蔵shaderを使用するのは簡単で、1つのkey値でGLProgramCacheバッファからGLProgramに直接取り出し、ノードに設定すればいいです.デフォルトshaderのkey値はGLProgramで定義されます
ここで使用する
ccPositionTextureColor_noMVP_vert頂点シェーダにCC_を乗算しないMVPMatrix行列は、デフォルトではこの行列に乗ります.これは2.xローカル座標を世界座標に変換するための習慣.そして3.x頂点はshaderに入る前から変換されているので、このマトリクスに乗らなくてもいいです.バンドだけです.noMVPのシェーダはCC_に乗らないMVPMatrix行列
ccPositionTexture_GrayScale_fragは色ごとに数値を乗算し、グレーの効果を達成します.
実行結果
カスタムシェーダーの使用
まず、完全なコードを先に
このプログラムは、クリップシェーダを使用する必要がある水波効果を実現し、頂点シェーダはデフォルトの
GLProgramStateのデフォルトではGLProgramStateCacheバッファを使用して管理されます.このような利点は、同じGLProgramStateを繰り返し作成する必要がないことです.欠点は、GLProgramStateが変更されると、このシェーダを使用するすべてのノードが影響を受けることです.次に、2つのスプライトが2つのシェーダを使用し、1つのノードがGLProgramStateのGLProgramを変更するテストを行います.
実行結果
sprite 2のGLProgramを変更した後、spriteのGLProgramも変更されたことがわかります.同じGLProgramStateを使用しているからです.以下、GLProgramStateCacheを使用しない別の方法に変更します.
実行結果
sprite 2のGLProgramを変更した後、spriteはGLProgramStateが互いに独立しているため、影響を受けないことがわかります.
luaでshaderを使用する
luaでshaderを使うのは基本的にc++と同じで、内蔵shaderを使う方法です
カスタムシェーダーの使用方法
cococos 2 d-xのshaderの作成と使用については、この記事のcococos 2 d-x shaderソースコード解析を参照してください.
まず、次に使用するいくつかの画像リソースをアップロードします.画像はネット上から来ています.この文章から参考にしてください.http://www.cocoachina.com/bbs/read.php?tid=1693873
ソース画像jpg
法線マップwater_normal.jpg
内蔵shaderを使用するのは簡単で、1つのkey値でGLProgramCacheバッファからGLProgramに直接取り出し、ノードに設定すればいいです.デフォルトshaderのkey値はGLProgramで定義されます
auto sprite = Sprite::create("colormap.jpg");
sprite->setPosition(visibleSize / 2);
addChild(sprite);
auto program = ShaderCache::getInstance()->programForKey(GLProgram::SHADER_NAME_POSITION_GRAYSCALE);
sprite->setShaderProgram(program);
ここで使用する
SHADER_NAME_POSITION_GRAYSCALE
は、頂点シェーダおよびフラグメントシェーダがそれぞれccPositionTextureColor_noMVP_vert
およびccPositionTexture_GrayScale_frag
である画像をグレー表示する機能である.ccPositionTextureColor_noMVP_vert頂点シェーダにCC_を乗算しないMVPMatrix行列は、デフォルトではこの行列に乗ります.これは2.xローカル座標を世界座標に変換するための習慣.そして3.x頂点はshaderに入る前から変換されているので、このマトリクスに乗らなくてもいいです.バンドだけです.noMVPのシェーダはCC_に乗らないMVPMatrix行列
//ccPositionTextureColor_noMVP_vert
const char* ccPositionTextureColor_noMVP_vert = STRINGIFY(
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
#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()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
);
ccPositionTexture_GrayScale_fragは色ごとに数値を乗算し、グレーの効果を達成します.
//ccPositionTexture_GrayScale_frag
const char* ccPositionTexture_GrayScale_frag = STRINGIFY(
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main(void)
vec4 c = texture2D(CC_Texture0, v_texCoord);
gl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b);
gl_FragColor.w = c.w;
);
);
実行結果
カスタムシェーダーの使用
まず、完全なコードを先に
auto sprite = Sprite::create("colormap.jpg");
sprite->setPosition(visibleSize / 2);
addChild(sprite);
// ,
auto fragSource = (GLchar*)(String::createWithContentsOfFile(FileUtils::getInstance()->fullPathForFilename("water.fs"))->getCString());
// , GLProgram
//
auto glProgram = GLProgramCache::getInstance()->getProgram("water_frag_shader");
if (!glProgram)
{
// 1
//glProgram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource);
// 2
glProgram = new GLProgram();
glProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource);
glProgram->link();
glProgram->updateUniforms();
glProgram->autorelease();
//
GLProgramCache::getInstance()->addProgram(glProgram, "water_frag_shader");
}
// , GLProgramState
// 1,
//sprite->setShaderProgram(glProgram);
// 2, 1
//auto glProgramState = GLProgramState::getOrCreateWithGLProgram(glProgram);
//sprite->setGLProgramState(glProgramState);
// 3,
auto glProgramState = GLProgramState::create(glProgram);
sprite->setGLProgramState(glProgramState);
// , uniform
auto normalMapTexture = TextureCache::getInstance()->addImage("water_normal.jpg");
glProgramState->setUniformTexture("u_normalMap", normalMapTexture);
このプログラムは、クリップシェーダを使用する必要がある水波効果を実現し、頂点シェーダはデフォルトの
ccPositionTextureColor_noMVP_vert
シェーダを使用します.シェーダプログラムを作成するには4つのステップに分かれ、最初のステップはシェーダソースコードを読み込みます.第2歩、GLProgramを作成して、ここで2つの方式を列挙して、実は第2の方式は第1の方式の内部の実現で、この2つの方式は同じで、GLProgramを作成した後にそれをGLProgramCacheバッファに追加することができて、このように次回同じGLProgramを使う時直接バッファから取ればいいです;第3のステップでは、GLProgramStateを作成し、ノードに設定します.ここには3つの方法がリストされています.同じように、前の2つの方法は同じです.第3の方法はgetOrCreateWithGLProgram方法を使用してGLProgramStateを取得しないので、GLProgramStateCacheバッファをスキップします.最後のステップは必須ではありません.シェーダプログラムでuniform変数が使用可能な場合は、GLProgramState->setUniform*()で値を設定します.GLProgramStateのデフォルトではGLProgramStateCacheバッファを使用して管理されます.このような利点は、同じGLProgramStateを繰り返し作成する必要がないことです.欠点は、GLProgramStateが変更されると、このシェーダを使用するすべてのノードが影響を受けることです.次に、2つのスプライトが2つのシェーダを使用し、1つのノードがGLProgramStateのGLProgramを変更するテストを行います.
void HelloWorld::testMutilShader()
{
Size visibleSize = Director::getInstance()->getVisibleSize();
// Sprite
auto sprite = Sprite::create("colormap.jpg");
sprite->setPosition(visibleSize / 2);
addChild(sprite);
auto fragSource = (GLchar*)(String::createWithContentsOfFile(FileUtils::getInstance()->fullPathForFilename("water.fs"))->getCString());
auto glProgram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource);
sprite->setShaderProgram(glProgram);
auto normalMapTexture = TextureCache::getInstance()->addImage("water_normal.jpg");
sprite->getGLProgramState()->setUniformTexture("u_normalMap", normalMapTexture);
// Sprite
auto sprite2 = Sprite::create("colormap.jpg");
sprite2->setPosition(visibleSize / 4);
addChild(sprite2);
sprite2->setShaderProgram(glProgram);
// Sprite GLProgram
auto newProgram = ShaderCache::getInstance()->programForKey(GLProgram::SHADER_NAME_POSITION_GRAYSCALE);
sprite2->getGLProgramState()->setGLProgram(newProgram);
}
実行結果
sprite 2のGLProgramを変更した後、spriteのGLProgramも変更されたことがわかります.同じGLProgramStateを使用しているからです.以下、GLProgramStateCacheを使用しない別の方法に変更します.
void HelloWorld::testMutilShader2()
{
Size visibleSize = Director::getInstance()->getVisibleSize();
// Sprite
auto sprite = Sprite::create("colormap.jpg");
sprite->setPosition(visibleSize / 2);
addChild(sprite);
auto fragSource = (GLchar*)(String::createWithContentsOfFile(FileUtils::getInstance()->fullPathForFilename("water.fs"))->getCString());
auto glProgram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource);
auto glProgramState = GLProgramState::create(glProgram);
sprite->setGLProgramState(glProgramState);
auto normalMapTexture = TextureCache::getInstance()->addImage("water_normal.jpg");
sprite->getGLProgramState()->setUniformTexture("u_normalMap", normalMapTexture);
// Sprite
auto sprite2 = Sprite::create("colormap.jpg");
sprite2->setPosition(visibleSize / 4);
addChild(sprite2);
sprite2->setShaderProgram(glProgram);
glProgramState = GLProgramState::create(glProgram);
sprite2->setGLProgramState(glProgramState);
sprite2->getGLProgramState()->setUniformTexture("u_normalMap", normalMapTexture);
// Sprite GLProgram
auto newProgram = ShaderCache::getInstance()->programForKey(GLProgram::SHADER_NAME_POSITION_GRAYSCALE);
sprite2->getGLProgramState()->setGLProgram(newProgram);
}
実行結果
sprite 2のGLProgramを変更した後、spriteはGLProgramStateが互いに独立しているため、影響を受けないことがわかります.
luaでshaderを使用する
luaでshaderを使うのは基本的にc++と同じで、内蔵shaderを使う方法です
local sprite = display.newSprite("colormap.jpg")
:move(display.center)
:addTo(self)
local glProgram = cc.GLProgramCache:getInstance():getGLProgram("ShaderUIGrayScale")
-- local glProgramState = cc.GLProgramState:getOrCreateWithGLProgram(glProgram)
-- sprite:setGLProgramState(glProgramState)
sprite:setGLProgram(glProgram)
カスタムシェーダーの使用方法
local glProgram = cc.GLProgramCache:getInstance():getGLProgram("water_shader")
if not glProgram then
glProgram = cc.GLProgram:createWithFilenames("water.vs", "water.fs")
cc.GLProgramCache:getInstance():addGLProgram(glProgram, "water_shader")
end
sprite:setGLProgram(glProgram)
local normalTexture = cc.TextureCache:getInstance():addImage("water_normal.jpg")
sprite:getGLProgramState():setUniformTexture("u_normalMap", normalTexture)