cocos3.0+ shader

本文详细介绍了如何在Cocos2d-x中创建和使用自定义Shader,包括修改现有Fragment Shader实现灰度效果的具体步骤,并提供了如何将自定义Shader集成到项目的完整流程。

cocos2d的shader都是共用的, 存放在 GLProgramCache 中。 当setGLProgram() 的时候是从GLProgramStateCache 中寻找是否有这个shader的State, 有就返回,这个也是共用的,任意一个GLProgramState修改了, 都会影响到使用这个shader的对象

添加shader的方法:

先编写shader: (直接复制cocos/renderer/ 下的 . frag或者 .vert ) frag是PS阶段的shader .vert是VS,然后按照自己的修改。
注意 这些shader在加载的时候,cocos2d会自动添加几个必须的属性变量:

const GLchar *sources[] = {
 #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
        (type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
 #endif
        "uniform mat4 CC_PMatrix;\n"
        "uniform mat4 CC_MVMatrix;\n"
        "uniform mat4 CC_MVPMatrix;\n"
        "uniform vec4 CC_Time;\n"
        "uniform vec4 CC_SinTime;\n"
        "uniform vec4 CC_CosTime;\n"
        "uniform vec4 CC_Random01;\n"
        "uniform sampler2D CC_Texture0;\n"
        "uniform sampler2D CC_Texture1;\n"
        "uniform sampler2D CC_Texture2;\n"
        "uniform sampler2D CC_Texture3;\n"
        "//CC INCLUDES END\n\n",
        source,
    };

这段代码在:
bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source) 中,所以你在编写自己的shader时候要注意不要和上面的变量重名
编写方式:
现在ccShaders.h中添加shader的编码保存的变量:(拿做的灰度效果为例:)

extern CC_DLL const GLchar *ccPositionTextureColor_noMVP_gray_frag; 

我直接修改 ccShader_PositionTextureColor_noMVP.frag 这个文件的
源文件:

const char* ccPositionTextureColor_noMVP_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform int n_isGray;

void main()
{
 if (n_isGray == 1)
 {
  float alpha = texture2D(CC_Texture0, v_texCoord).a;
  float grey = dot(texture2D(CC_Texture0, v_texCoord).rgb, vec3(0.299, 0.587, 0.114));
  gl_FragColor = vec4(1, grey, grey, 0.0);
 }
 else
 {
  gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
 }

}
);

修改后:

const char* ccPositionTextureColor_noMVP_gray_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

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

红色部分是修改掉的 注意 const char* ccPositionTextureColor_noMVP_gray_frag = STRINGIFY( 注意要和你在ccShaders.h中声明的变量一致!
然后在ccShaders.cpp中引用 编写好的shader文件 :

#include "ccShader_PositionTextureColor_noMVP_gray.frag"

这样编写部分就结束

现在开始添加到默认shader里面:

先到 CCGLProgram.h   GLProgram 中添加添加我们这个shader的名字:(这个名字只是对外使用的键值)
static const char* SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY;  
在.cpp中加上: 
const char* GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY = "ShaderPositionTextureColor_noMVP_gray";

然后到CCGLProgramCache.cpp 中的 最上面有一堆枚举, 添加一个自己shader的枚举 比如我添加的 kShaderType_PositionTextureColor_noMVP_gray,

然后在 void GLProgramCache::loadDefaultGLPrograms() 中写加载我们shader的代码:

 p = new GLProgram();
 loadDefaultGLProgram(p,
    kShaderType_PositionTextureColor_noMVP_gray);
_programs.insert( std::make_pair( GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY, p ) );

到void GLProgramCache::loadDefaultGLProgram(GLProgram *p, int type) 中,配置我们shader用的VS 和PS阶段的 的相关代码:(因为做灰度只需要改动pos部分,所以可以直接用cocos2d现有的VS阶段的代码ccPositionTextureColor_noMVP_vert)

case kShaderType_PositionTextureColor_noMVP_gray:
   p->initWithByteArrays(ccPositionTextureColor_noMVP_vert,   ccPositionTextureColor_noMVP_gray_frag);
   break;

这样shader就添加好了, 使用方法:

GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY);
  sprite->setGLProgram(program);

还原的话就

GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);
sprite->setGLProgram(program);

你可以脱离这套共用GLProgramState的方式 直接用: (这样你就可以控制这个shader某一个值,而不影响其他使用这个shader的对象了)

GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY); 
GLProgramState* state = GLProgramState::create(program);
sprite->setGLProgramState(state):

本人没学过opengel今天ui那边需要灰度,才开始看的, 写得不好,大家就将就看吧~
还要说一个地方

std::string GLProgram::logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc) const
{
    std::string ret;
    GLint logLength = 0, charsWritten = 0;

    //infoFunc(object, GL_INFO_LOG_LENGTH, &logLength);        //编译错误的话,到这里就崩溃了~~  不知道为什么, 
 glGetShaderiv(object, GL_INFO_LOG_LENGTH, &logLength);     //我直接改成调用opengel函数, 
    if (logLength < 1)
        return "";

    char *logBytes = (char*)malloc(logLength);
   // logFunc(object, logLength, &charsWritten, logBytes);
 glGetShaderInfoLog(object, logLength, &charsWritten, logBytes);
    ret = logBytes;

    free(logBytes);
    return ret;
}

转载至:http://note.youdao.com/share/?id=f72378178898d34affe13a6dddd75df3&type=note

### 在 Cocos Creator 3.0 中实现文本或精灵的描边效果 #### 使用自定义 Shader 实现描边效果 对于希望在 Cocos Creator 3.0 中为文本或精灵添加描边效果的需求,可以利用自定义Shader来达成这一目标。通过编写特定的着色器代码,能够有效地控制渲染过程中的颜色混合方式,从而创建出理想的描边视觉效果[^3]。 下面是一个简单的例子展示如何构建一个具有描边特性的文字组件: ```glsl // 描边材质脚本 (stroke-material.glsl) precision mediump float; uniform vec4 u_color; uniform sampler2D u_mainTex; varying vec2 v_uv; void main() { // 原始纹理采样 vec4 originalColor = texture2D(u_mainTex, v_uv); // 计算边缘检测因子 float edgeFactor = step(0.5, length(vec2(dFdx(v_uv.x), dFdy(v_uv.y)))); // 应用描边逻辑:当像素位于边界时应用不同的颜色 gl_FragColor = mix(originalColor * u_color, vec4(1., 0., 0., 1.), edgeFactor); } ``` 此片段展示了基本原理,在实际项目中可能还需要调整参数以适应不同场景下的需求。为了使上述代码生效,需将其关联至相应的UI元素上作为其使用的材质资源之一。 另外一种更灵活的方法是借助第三方插件如 Spine 来间接完成类似的任务。虽然 Spine 主要用于骨骼动画制作,但它所提供的挂点机制允许开发者向现有角色模型附加额外的对象,这同样适用于创造独特的装饰性特征,例如围绕对象周围的轮廓线[^2]。 然而值得注意的是,由于版本差异的存在,某些特性可能会有所变化;因此建议查阅官方文档确认最新API接口以及最佳实践指南[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值