在cocos2dx 中添加自定義 shaders --- 改變 HSL 色調,飽和度, 亮度


 訂閱

步驟1

準備 shaders文件- ccShad_Hsl.h

/*
* cocos2d for iPhone: http://www.cocos2d-iphone.org
*
* Copyright (c) 2011 Brian Chapados
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

" \n\
#ifdef GL_ES \n\
precision mediump float; \n\
#endif \n\
\n\
varying vec2 v_texCoord; \n\
uniform sampler2D CC_Texture0; \n\
\n\
uniform float AddHue; \n\
uniform float AddSat; \n\
uniform float AddLig; \n\
uniform float AddRed; \n\
uniform float AddGreen; \n\
uniform float AddBlue; \n\
uniform float AddAlpha; \n\
\n\
float Hue_2_RGB(float v1, float v2, float vH ) \n\
{ \n\
float ret;\n\
if ( vH < 0.0 )\n\
vH += 1.0;\n\
if ( vH > 1.0 )\n\
vH -= 1.0;\n\
if ( ( 6.0 * vH ) < 1.0 )\n\
ret = ( v1 + ( v2 - v1 ) * 6.0 * vH );\n\
else if ( ( 2.0 * vH ) < 1.0 )\n\
ret = ( v2 );\n\
else if ( ( 3.0 * vH ) < 2.0 )\n\
ret = ( v1 + ( v2 - v1 ) * ( ( 2.0 / 3.0 ) - vH ) * 6.0 );\n\
else\n\
ret = v1;\n\
return ret;\n\
}\n\
\n\
void main(void)\n\
{\n\
float Cmax, Cmin;\n\
\n\
float D;\n\
\n\
float H, S, L;\n\
float R, G, B;\n\
\n\
vec4 color = texture2D(CC_Texture0, v_texCoord);\n\
\n\
R = color.r;\n\
G = color.g;\n\
B = color.b;\n\
Cmax = max (R, max (G, B));\n\
Cmin = min (R, min (G, B));\n\
L = (Cmax + Cmin) / 2.0;\n\
\n\
if (Cmax == Cmin)\n\
{\n\
H = 0.0;\n\
S = 0.0;\n\
}\n\
else\n\
{\n\
D = Cmax - Cmin;\n\
if (L < 0.5)\n\
{\n\
S = D / (Cmax + Cmin);\n\
}\n\
else\n\
{\n\
S = D / (2.0 - (Cmax + Cmin));\n\
}\n\
\n\
if (R == Cmax)\n\
{\n\
H = (G - B) / D;\n\
} else {\n\
if (G == Cmax)\n\
{\n\
H = 2.0 + (B - R) /D;\n\
}\n\
else\n\
{\n\
H = 4.0 + (R - G) / D;\n\
}\n\
}\n\
H = H / 6.0;\n\
}\n\
\n\
// modify H/S/L values\n\
H += AddHue;\n\
S += AddSat;\n\
L += AddLig;\n\
\n\
if (H < 0.0)\n\
{\n\
H = H + 1.0;\n\
}\n\
\n\
H = clamp(H, 0.0, 1.0);\n\
S = clamp(S, 0.0, 1.0);\n\
L = clamp(L, 0.0, 1.0);\n\
\n\
// convert back to RGB\n\
float var_2, var_1;\n\
\n\
if (S == 0.0)\n\
{\n\
R = L;\n\
G = L;\n\
B = L;\n\
}\n\
else\n\
{\n\
if ( L < 0.5 )\n\
{\n\
var_2 = L * ( 1.0 + S );\n\
}\n\
else\n\
{\n\
var_2 = ( L + S ) - ( S * L );\n\
}\n\
\n\
var_1 = 2.0 * L - var_2;\n\
\n\
R = Hue_2_RGB( var_1, var_2, H + ( 1.0 / 3.0 ) );\n\
G = Hue_2_RGB( var_1, var_2, H );\n\
B = Hue_2_RGB( var_1, var_2, H - ( 1.0 / 3.0 ) );\n\
}\n\
\n\
R = R * AddRed;\n\
G = G * AddGreen;\n\
B = B * AddBlue;\n\
\n\
gl_FragColor = vec4(R,G,B, color.a * AddAlpha);\n\
\n\
}\n\
";


將它放入E:\HSluZiLong\cocos2d-x-2.2.1\cocos2d-x-2.2.1\cocos2dx\shaders 目錄下

步驟2.

在 ccShaders.h 中加入代碼

extern CC_DLL const GLchar * ccPositionColorHSL_frag;
extern CC_DLL const GLchar * ccPositionColorHSL_vert;

在 ccShaders.cpp 中加入代碼

const GLchar * ccPositionColorHSL_frag =
#include "ccShad_Hsl.h"


在 CCGLProgram.h 中定義

#define KCCShader_Position_hsl"KCCShader_Position_hsl"

在 CCShaderCache.cpp 中 追加枚舉 kCCShaderType_Position_hsl,

在 CCShaderCache.cpp 的 reloadDefaultShaders中加入代碼

p = programForKey(KCCShader_Position_hsl);
    p->reset();
    loadDefaultShader(p, kCCShaderType_Position_hsl);

在 CCShaderCache.cpp 的 loadDefaultShader 中加入代碼

case kCCShaderType_Position_hsl: 
            p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionColorHSL_frag);
p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
            break;

在 CCShaderCache.cpp 的 loadDefaultShaders中加入代碼

p = new CCGLProgram();
    loadDefaultShader(p, kCCShaderType_Position_hsl);
    
    m_pPrograms->setObject(p, KCCShader_Position_hsl);
    p->release();

步驟3.

在 CCSprite 類中 追加 HSL 接口

bool m_use_hsl;
GLfloat m_color_h;
GLfloat m_color_s;
GLfloat m_color_l;
GLfloat m_color_a;
GLuint hLocation;
GLuint sLocation;
GLuint lLocation;
GLuint rLocation;
GLuint gLocation;
GLuint bLocation;
GLuint aLocation;



  1. void initHSL();  
  2. void drawHSL();  
  3. void setHSL(float h, float s, float l);  
  4. void setH(float h);  
  5. void setS(float s);  
  6. void setL(float l);  
  7. float getH(void){ return m_color_h;}  
  8. float getS(void){ return m_color_s;}  
  9. float getL(void){ return m_color_l;}  

  1. void CCSprite::initHSL()  
  2. {  
  3.     if(m_use_hsl == false)  
  4.     {  
  5.         m_use_hsl = true;  
  6.           
  7.         setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(KCCShader_Position_hsl));   
  8.         hLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddHue");  
  9.         sLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddSat");  
  10.         lLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddLig");  
  11.         rLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddRed");  
  12.         gLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddGreen");  
  13.         bLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddBlue");  
  14.         aLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "AddAlpha");  
  15.     }  
  16. }  
  17.   
  18. void CCSprite::drawHSL()  
  19. {  
  20.       
  21.     ccBlendFunc blend = getBlendFunc();  
  22.     ccGLBlendFunc(blend.src, blend.dst);  
  23.   
  24.     getShaderProgram()->use();  
  25.     getShaderProgram()->setUniformsForBuiltins();  
  26.     getShaderProgram()->setUniformLocationWith1f(hLocation, m_color_h);  
  27.     getShaderProgram()->setUniformLocationWith1f(sLocation, m_color_s);  
  28.     getShaderProgram()->setUniformLocationWith1f(lLocation, m_color_l);  
  29.     getShaderProgram()->setUniformLocationWith1f(rLocation, _displayedColor.r/255.f);  
  30.     getShaderProgram()->setUniformLocationWith1f(gLocation, _displayedColor.g/255.f);  
  31.     getShaderProgram()->setUniformLocationWith1f(bLocation, _displayedColor.b/255.f);  
  32.     m_color_a = this->getOpacity() / 255.f;  
  33.     getShaderProgram()->setUniformLocationWith1f(aLocation, m_color_a);  
  34.   
  35.     ccGLBindTexture2D( getTexture()->getName());  
  36.     ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex );  
  37.   
  38. #define kQuadSize sizeof(m_sQuad.bl)  
  39.     long offset = (long)&m_sQuad;  
  40.   
  41.     // vertex  
  42.     int diff = offsetof( ccV3F_C4B_T2F, vertices);  
  43.     glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));  
  44.   
  45.     // texCoods  
  46.     diff = offsetof( ccV3F_C4B_T2F, texCoords);  
  47.     glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));  
  48.   
  49.     // color  
  50.     diff = offsetof( ccV3F_C4B_T2F, colors);  
  51.     glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));  
  52.   
  53.   
  54.     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  
  55.   
  56.     CC_INCREMENT_GL_DRAWS(1);     
  57. }  
  58. void CCSprite::setHSL(float h, float s, float l)  
  59. {  
  60.     initHSL();  
  61.     setH(h);  
  62.     setS(s);  
  63.     setL(l);  
  64. }  
  65. void CCSprite::setH(float h)  
  66. {  
  67.     initHSL();  
  68.     m_color_h = h;  
  69. }  
  70. void CCSprite::setS(float s)  
  71. {  
  72.     initHSL();  
  73.     m_color_s = s;  
  74. }  
  75. void CCSprite::setL(float l)  
  76. {  
  77.     initHSL();  
  78.     m_color_l = l;  
  79.     ccBlendFunc blend = getBlendFunc();  
  80.     if(m_color_l > 0)  
  81.         blend.src = GL_SRC_ALPHA;  
  82.     else  
  83.         blend.src = GL_ONE;  
  84.     blend.dst = GL_ONE_MINUS_SRC_ALPHA;  
  85.     setBlendFunc(blend);  
  86. }  

在 CCSprite.cpp 的 updateBlendFunc中追加代碼

if(m_use_hsl)
{
ccBlendFunc blend = getBlendFunc();
if(m_color_l > 0)
blend.src = GL_SRC_ALPHA;
else
blend.src = GL_ONE;
blend.dst = GL_ONE_MINUS_SRC_ALPHA;
setBlendFunc(blend);
}

在 CCSprite.cpp 的 setTexture中追加代碼

if(this->m_use_hsl)
{
m_use_hsl = false;
initHSL();
}


在 CCSprite.cpp 的 draw 開頭插入代碼

if(m_use_hsl)
{
drawHSL();
return;
}

步驟5.

調用接口

  1. {  
  2.     CCSprite* pSprite = CCSprite::create("Icon.png");  
  3.     // -1 ~ 1  0無變化  
  4.     pSprite->setS(-1);  
  5.     // position the sprite on the center of the screen  
  6.     pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));  
  7.   
  8.     // add the sprite as a child to this layer  
  9.     this->addChild(pSprite, 0);  
  10.     }  


|字號 訂閱

發佈了10 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章