cocos2dx_Shader简单实例入门

本文通过一个简单的Shader示例,展示了如何使用顶点着色器和片段着色器动态调整图片亮度。ShaderSprite类继承自Sprite,通过自定义的GLProgramState实现了亮度随时间变化的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Shader是图形学方面的知识,不太好入门,下文用一个比较简单的例子来体验下shader。

先看创建的代码
ShaderSprite.hpp

#include "CCSprite.h"
class ShaderSprite : public cocos2d::Sprite
{
public:
    void initWithShader(const char* vertexShader, const char* fragmentShader, const char* key);
private:
    virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
    void update(float dt) override;
private:
    cocos2d::GLProgramState* m_pProgramState;
    float u_time;
    
public:
    static const char* ShaderKey;
    static const char* VertexShader;
    static const char* FragmentShader;
};

ShaderSprite.cpp

#include "ShaderSprite.hpp"

using namespace cocos2d;

const char* ShaderSprite::ShaderKey = "shader_key";

const char* ShaderSprite::VertexShader = " \
attribute vec4 a_position;\
attribute vec4 a_color;\
attribute vec2 a_texcoord;\
varying vec2 v_texcoord;\
varying vec4 v_fragmentColor;\
void main(){\
gl_Position = CC_PMatrix * a_position;\
v_fragmentColor = a_color;\
v_texcoord = a_texcoord;\
}\
";

const char* ShaderSprite::FragmentShader = " \
#ifdef GL_ES \n\
precision highp float; \n\
#endif \n\
varying vec2 v_texcoord; \
uniform float u_time; \
void main(){ \
vec4 incolor = texture2D(CC_Texture0, v_texcoord); \
float factor = (sin(u_time)+1.0)/3.0;\
vec4 outcolor = vec4(0.8, 0.8, 0.8, 0.8)*factor + incolor*(1.0-factor); \
gl_FragColor = vec4(outcolor.xyz, incolor.w); \
} \
";

void ShaderSprite::initWithShader(const char* vertexShader, const char* fragmentShader, const char* key)
{
    GLProgram* pProgram = GLProgramCache::getInstance()->getGLProgram(key);
    if (pProgram == nullptr)
    {
        pProgram = GLProgram::createWithByteArrays(vertexShader, fragmentShader);
        GLProgramCache::getInstance()->addGLProgram(pProgram, key);
    }
    
    m_pProgramState = GLProgramState::create(pProgram);
    
    scheduleUpdate();
}

void ShaderSprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    m_pProgramState->setUniformFloat("u_time", u_time);
    setGLProgramState(m_pProgramState);
    
    Sprite::draw(renderer, transform, flags);
}

void ShaderSprite::update(float dt)
{
    u_time += dt;
}

在场景文件中添加以下代码

ShaderSprite* pSprite = new ShaderSprite();
pSprite->initWithFile("HelloWorld.png");
pSprite->setPosition(500, 500);
addChild(pSprite);
pSprite->initWithShader(ShaderSprite::VertexShader, ShaderSprite::FragmentShader, ShaderSprite::ShaderKey);

运行下代码,可以发现图片的亮度的在不断变化,可以找个工程体验一下哦。来分析分析吧。
(忽略上面代码的书写格式和简略的亮度变化方法,嘿嘿)

首先先来看ShadeSprite,继承自Sprite,复写了父类的draw函数。
在draw函数中,setGLProgramState并且调用了父类的draw函数。
我们会发现这个GLProrgamState是影响了效果,
那glprogramstate是啥呢?
/**
GLProgramState holds the ‘state’ (uniforms and attributes) of the GLProgram.
A GLProgram can be used by thousands of Nodes, but if different uniform values
are going to be used, then each node will need its own GLProgramState
*/–来自源码中的解释
//uniform和attribute是OpenGL中的变量类型,简单来说就是glprogramstate就是带有参数的glprogram

那么GLProram是啥呢?
glprogram能够编译链接我们提供的顶点着色器文件和片段着色器。

那顶点着色器和片段着色器是啥呢?
简单来说:顶点着色器就是能够在渲染的时候改变渲染顶点的位置,片段着色器能够改变片段的颜色。具体渲染管线以后再说。

ShaderSprite::VertexShader是顶点着色器,这个顶点着色器只是将持续传进来的位置直接输出,以及将颜色直接传给片段着色器,并无其它操作,大家想调调参数啥的不用动这个。

ShaderSprite::FragmentShader是片段着色器,通过这里面的两行来进行效果的改变。(可以通过动这两行来调效果)
float factor = (sin(u_time)+1.0)/3.0;
vec4 outcolor = vec4(0.8, 0.8, 0.8, 0.8)factor + incolor(1.0-factor);
其实很简单,将传进来的参数u_time对源颜色和vec4(0.8, 0.8, 0.8, 0.8)进行差值计算并输出。

在shaderSprite有一个参数u_time每帧更新,并且赋值给m_pProgramState。这就是shader外部传入参数。

本文给出了一个可运行的效果,大家可以去调效果体验一下,感受下shader的魅力。

其实上面我们能shader中的一些内置变量,内置函数,变量类型,等整理完分享一下。至于着色器原理或者说渲染管线,等我完善下知识再给大家分享,学校学的已经还给老师啦。

本来今天想再去看下事件分发机制的,正好最近效果调的比较多然后同事说分享下shader相关的,就先写了这个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值