博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cocos2d-x3.0-shader实现sprite/node变灰
阅读量:4521 次
发布时间:2019-06-08

本文共 5738 字,大约阅读时间需要 19 分钟。

图片/按钮变灰变暗变黑白是游戏UI常用的操作

之前项目使用多套资源实现

如一个按钮对应3张图,普通/选中/禁用状态

然后使用下列方法切换

setEnabled/setBright

selected/unselected

 

然后如果对象不是按钮而是一般的sprite

或包含sprite的node

并没有以上的方法可以调用

同时也出于减少资源的考虑

新项目依靠shader实现显示效果切换

 

程序原理如下

CCNode有以下3个接口

(1,2)setGLProgram/setShaderProgram

(3)setGLProgramState

接口本质都是设置CCNode的成员变量_glProgramState

从而实现显示效果的切换(包括黑白/彩色切换等等)

前两个接口一样,通过GLProgram获取state,是设置shader的主要方法

第三个接口更直接一些直接设置state

 

通过GLProgram设置shader更方便

因为cocos预设了许多可以直接用的效果

这些效果定义在CCGLProgram.h

通过CCGLProgramCache可以使用这些效果

比如我们代码里用到的(变为正常彩色)

auto programNormal = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);

若需要自行设置shader(变为黑白灰色)

auto programGray = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert,        ccUIGrayScale_frag);

实际上从CCGLProgramCache获取的GLProgram就是通过

createWithByteArrays/initWithByteArrays预先加载好的

再进一步看其中的两个参数

ccPositionTextureColor_noMVP_vert
ccUIGrayScale_frag

在目录cocos\renderer中我们可以看到

ccShader_PositionTextureColor_noMVP.vert

打开文件可以看到定义如下

const char* ccPositionTextureColor_noMVP_vert = STRINGIFY(attribute vec4 a_position;attribute vec2 a_texCoord;attribute vec4 a_color;\n#ifdef GL_ES\nvarying lowp vec4 v_fragmentColor;varying mediump vec2 v_texCoord;\n#else\nvarying vec4 v_fragmentColor;varying vec2 v_texCoord;\n#endif\nvoid main(){    gl_Position = CC_PMatrix * a_position;    v_fragmentColor = a_color;    v_texCoord = a_texCoord;});

另外,在目录cocos\ui\shaders中可以看到

ccShader_grayscale.frag

const char* ccUIGrayScale_frag = STRINGIFY(\n#ifdef GL_ES\n\nprecision mediump float;\n\n#endif\n\n\n\nvarying vec4 v_fragmentColor;\n\nvarying vec2 v_texCoord;\n\n\n\nvoid main(void)\n\n{\n    \nvec4 c = texture2D(CC_Texture0, v_texCoord);\n    \ngl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b);\n    \ngl_FragColor.w = c.w;\n\n}\n);

具体的代码由glsg编写在外部

也可以自己手写在游戏内部

原理就是这样

 

具体的变灰操作在cocos2d-x3.7中更加方便

新加入了GLProgram ShaderUIGrayScale

可以直接从Cache中get

 

非常有趣的是

UIScale9Sprite定义了setState方法切换元素的彩色/灰色

我们的代码基本都是从那里学的

但不知道为什么cocos只在UIScale9Sprite中写了这个接口

CCNode中却没有这个接口

不过看过本文,现在变灰已经不是问题了

 

shader非常强大,变灰只是其中的一个功能

更多的还需要继续不断学习!

 

 

以下代码使用cocos2d-x3.5

点击按钮调用clickCallback切换 彩色/灰色

#include "HelloWorldScene.h"#include "../cocos/ui/shaders/UIShaders.h"USING_NS_CC;Scene* HelloWorld::createScene(){    // 'scene' is an autorelease object    auto scene = Scene::create();        // 'layer' is an autorelease object    auto layer = HelloWorld::create();    // add layer as a child to scene    scene->addChild(layer);    // return the scene    return scene;}HelloWorld::HelloWorld()    :m_pTitle(nullptr),    m_pGround(nullptr),    m_pTest(nullptr),    m_pButton(nullptr){}// on "init" you need to initialize your instancebool HelloWorld::init(){    //    // 1. super init first    if ( !Layer::init() )    {        return false;    }        Size visibleSize = Director::getInstance()->getVisibleSize();    Vec2 origin = Director::getInstance()->getVisibleOrigin();    /////    // 2. add a menu item with "X" image, which is clicked to quit the program    //    you may modify it.    // add a "close" icon to exit the progress. it's an autorelease object    auto closeItem = MenuItemImage::create(                                           "CloseNormal.png",                                           "CloseSelected.png",                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));        closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,                                origin.y + closeItem->getContentSize().height/2));    m_pButton = MenuItemImage::create(        "normal.png",        "selected.png",        CC_CALLBACK_1(HelloWorld::clickCallback, this));    m_pButton->setPosition(Vec2(origin.x + m_pButton->getContentSize().width / 2,        origin.y + m_pButton->getContentSize().height / 2));    // create menu, it's an autorelease object    auto menu = Menu::create(closeItem, m_pButton, NULL);    menu->setPosition(Vec2::ZERO);    this->addChild(menu, 1);    /////    // 3. add your codes below...    // add a label shows "Hello World"    // create and initialize a label        m_pTitle = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);        // position the label on the center of the screen    m_pTitle->setPosition(Vec2(origin.x + visibleSize.width / 2,        visibleSize.height / 2 + origin.y));    // add the label as a child to this layer    this->addChild(m_pTitle);    // add "HelloWorld" splash screen"    m_pGround = Sprite::create("Test.jpg");    // position the sprite on the center of the screen    m_pGround->setPosition(Vec2(visibleSize.width / 3 + origin.x, visibleSize.height / 2 + origin.y));    // add the sprite as a child to this layer    this->addChild(m_pGround);    m_pTest = Sprite::create("Test.jpg");    m_pTest->setPosition(Vec2(visibleSize.width*2 / 3 + origin.x, visibleSize.height / 2 + origin.y));    this->addChild(m_pTest);        return true;}void HelloWorld::clickCallback(Ref* pSender){    static bool isGray = false;    isGray = !isGray;    auto programGray = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert,        ccUIGrayScale_frag);    auto programNormal = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);    m_pTest->setGLProgram(isGray ? programGray : programNormal);}void HelloWorld::menuCloseCallback(Ref* pSender){#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)    MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");    return;#endif    Director::getInstance()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)    exit(0);#endif}

转载于:https://www.cnblogs.com/billyrun/articles/5219977.html

你可能感兴趣的文章
day40-socket编程
查看>>
SpringBoot里mybatis查询结果为null的列不返回问题的解决方案
查看>>
为什么留不住优秀的员工
查看>>
Django后台管理admin笔记
查看>>
JavaScript中的变量
查看>>
iptables基本原理和规则配置
查看>>
ArcGIS JS 学习笔记4 实现地图联动
查看>>
ubuntu 12.04 lts安装golang并设置vim语法高亮
查看>>
编程题目:PAT 1004. 成绩排名 (20)
查看>>
使用分层实现业务处理
查看>>
Microsoft Windows平台的NoSQL数据存储引擎
查看>>
浅谈虚拟机
查看>>
Ubuntu系统Linux编译osg库
查看>>
BootstrapTable-导出数据
查看>>
Linux学习笔记 -- 系统目录结构
查看>>
[转载]ExtJs4 笔记(9) Ext.Panel 面板控件、 Ext.window.Window 窗口控件、 Ext.container.Viewport 布局控件...
查看>>
将数组排序组成最小的整数
查看>>
sqlserver学习--1(登陆,时间函数,查看表结构,查看建表语句,IDENTITY() 函数,查询表名称,查询表结构)...
查看>>
MYSQL 日期函数
查看>>
Oracle触发器之替代触发器
查看>>