不知道有沒有人看到這個效果會眼熟。這個只是將openg es編程指南里面的多重紋理效果移植到cocos2d上面來。但是,本文多了一個可以設置亮度紋理位置和大小的方法。
這種效果可以用來模擬手電筒吧。
就是利用了shader,讀取兩塊紋理,然后通過一定的算法計算出疊加后的色值,最后渲染出來。
我們了解到,渲染sprite的類是TriangleCommand,這個類只能渲染多個三角形,并且只能渲染一塊紋理。因此,我們要使用CustomCommand來渲染兩塊紋理。
我們在CustomCommand的執(zhí)行回調里面寫這樣的代碼:
//Load the mv
_glProgramState->apply(_modelViewTransform);
float size = sizeof(V3F_C4F_T2F2);
// Load the vertex position
glVertexAttribPointer ( GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT,
GL_FALSE, size, &_verts[0]);
glVertexAttribPointer ( GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT,
GL_FALSE, size, &(_verts[0].color));
// Load the texture coordinate
glVertexAttribPointer ( GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT,
GL_FALSE, size, &(_verts[0].texCoords));
glVertexAttribPointer ( GLProgram::VERTEX_ATTRIB_TEX_COORD1, 2, GL_FLOAT,
GL_FALSE, size, &(_verts[0].texCoords1));
glEnableVertexAttribArray ( GLProgram::VERTEX_ATTRIB_POSITION );
glEnableVertexAttribArray ( GLProgram::VERTEX_ATTRIB_COLOR );
glEnableVertexAttribArray ( GLProgram::VERTEX_ATTRIB_TEX_COORD );
glEnableVertexAttribArray ( GLProgram::VERTEX_ATTRIB_TEX_COORD1 );
//bind texture
GL::bindTextureN(0, _texture->getName());
glUniform1i(_glProgramState->getGLProgram()->getUniformLocation(GLProgram::UNIFORM_NAME_SAMPLER0), 0);
GL::bindTextureN(1, _lightTexture->getName());
glUniform1i(_glProgramState->getGLProgram()->getUniformLocation(GLProgram::UNIFORM_NAME_SAMPLER1), 1);
//draw
glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, quadIndices );
這段代碼就是讀取紋理、坐標、顏色信息,最后繪制出來。這里只是簡簡單單的寫了一下,如果調用多的話,可以利用VAO和VBO來優(yōu)化一下執(zhí)行效率。
這里要提醒的是,不能利用SpriteBatchNode來優(yōu)化。因為SpriteBatchNode只會獲取sprite的單個紋理,而燈光紋理卻是沒有的。SpriteBatchNode的優(yōu)化原理是通過減少頂點提交的次數(shù)來優(yōu)化的,如果你需要的話要也可以根據(jù)這個原理來做一些處理。
而渲染的主要代碼是在shader里面。利用fragment shader處理紋理,然后達成這樣的效果。
void main()
{
vec4 baseColor;
baseColor = texture2D( CC_Texture0, v_texCoord )*v_fragmentColor; vec4 lightColor;
if (v_texCoord1.x>1.0 || v_texCoord1.y>1.0 || v_texCoord1.y < 0.0 || v_texCoord1.x<0.0 )
{
lightColor = vec4(0, 0, 0, 1);
}
else
{
lightColor = texture2D( CC_Texture1, v_texCoord1 );
}
gl_FragColor = baseColor * (lightColor + 0.25);
}
gl_FragColor是最后輸出的紋理色值。baseColor是讀取的墻壁紋理值,最后lightColor是燈光效果紋理值。
這里做了一下修改,將紋理范圍不在0-1的值全部設置成了黑色,也就是將紋理外的顏色變成了黑色,然后參與計算。
最后說一下我在做這個的時候遇到的一個坑,sprite自身的vertex shader里面用到的是p矩陣,然后我也用p矩陣,最后發(fā)現(xiàn)不能設置位置。最后,我發(fā)現(xiàn)Renderer在渲染三角形之前就將所有頂點做了mv變換,但是我這里沒有變換,只好乖乖的用mvp矩陣了。
本文代碼下載地址:https://pan.baidu.com/s/1dEIwRQx