如何在Cocos2dx中为Armature对象设置着色器

时间:2014-03-05 02:10:42

标签: cocos2d-x

我有3个问题:

  1. 我知道何时使用spr1->setShaderProgram(glProgram)为Sprite对象设置着色器。但是,我想为Armature对象设置着色器。我怎么能这样做?

  2. 在CCSprite中,我可以使用setBlendFunc,如何在Armature中使用。

  3. 我读了这篇文章http://blog.muditjaju.infiniteeurekas.in/?p=1,我看到了检测2个精灵之间碰撞的想法。但我想编写一个扩展函数,可以检测不同对象之间的冲突,如精灵与精灵,精灵与电枢,电枢与电枢。我怎么能这样做?

  4. 由于

1 个答案:

答案 0 :(得分:0)

今天我遇到了和你一样的情况。幸运的是,我找到了其他人的解决方案。主要的是写一个Armature的子类,比如说ShaderArmature,并用着色器渲染每个骨骼的每个孩子----在我的例子中,着色器用于使骨架变灰。

您可以创建一个ShaderArmature对象并调用其 setgrayState ()以启用灰化和 setUsuaState ()以删除灰度效果。

1,添加ShaderArmature.h& ShaderArmature.cpp位于Armature.h的同一目录中。

  

ShaderArmature.h

//
//  Created by Wangyq on 2017/8/13.
//
//

#ifndef __SHADERARMATURE_H__
#define __SHADERARMATURE_H__

//
//---------shaderArmature.h
///
#include "cocos2d.h"
//#include "extensions/cocos-ext.h"
#include "cocostudio/CocoStudio.h"
//USING_NS_CC_EXT;
USING_NS_CC;
namespace cocostudio{
class CC_STUDIO_DLL ShaderArmature : public Armature
{
public:
    ShaderArmature();
    virtual ~ShaderArmature();

    bool init(const std::string& name) override;

    static ShaderArmature *create(const std::string& name) ;

    virtual void initShader(bool shaderState);
    //    void setBackgroundNotification();

//    draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
    virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated) override;
    //    void listenBackToForeground(Ref *obj);
    void setIceState();
    void setUsuaState();

    void setblurState();
    void setbanishState();
    void setfrozenState();
    void setgrayState();
    void setinvisState();
    void setmirrorState();
    void setpoisonState();
    void setstoneState();
protected:
    std::string _fragSourceFile;
    std::string _vertSourceFile;
    //GLchar * fragSource;
    //GLchar * vertSource;
    GLchar fragSource[2048];
    GLchar vertSource[2048];
    bool bSetShader;
};

}
#endif /* __SHADERARMATURE_H__ */
  

ShaderArmature.cpp

//
//  ShaderArmature.cpp
//  cocos2d_libs
//
//  Created by Wangyq on 2017/8/13.
//
//

#include "ShaderArmature.h"

using namespace cocos2d;


namespace cocostudio {
    ShaderArmature::ShaderArmature(){

    }
    ShaderArmature::~ShaderArmature(){

    }
    bool ShaderArmature::init(const std::string& name)
    {
        return Armature::init(name);
    }
    ShaderArmature *ShaderArmature::create(const std::string& name)
    {
        ShaderArmature *armature = new ShaderArmature;
        if (armature && armature->init(name))
        {
            armature->autorelease();
            return armature;
        }
        else{
            CC_SAFE_DELETE(armature);
            return nullptr;
        }
    }


    void ShaderArmature::initShader(bool shaderState){
        //Traverse every bone to set shader
        for (auto& object : _boneDic)
        {
            if (Bone *bone = dynamic_cast<Bone *>(object.second))
            {
                if (bone == nullptr)
                    continue;

                //-----------------!! IMPORTANT !!-----------------
                //Each bone may have more than one child, like several frames, also need to assign shader to them
                //Without this step, only the first frame will have the shader effect.
                const Vector<DecorativeDisplay*> list = bone->getDisplayManager()->getDecorativeDisplayList();
                for (auto& display : list)
                {
                    Node* node = display->getDisplay();
                    if (node == nullptr)
                        continue;

                    if (shaderState){
                        auto program = new GLProgram();
                        program->initWithByteArrays(vertSource, fragSource);


                        node->setGLProgram(program);

                        program->autorelease();

                        CHECK_GL_ERROR_DEBUG();

                        program->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
                        program->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
                        program->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);

                        CHECK_GL_ERROR_DEBUG();

                        program->link();

                        CHECK_GL_ERROR_DEBUG();

                        program->updateUniforms();

                        CHECK_GL_ERROR_DEBUG();

                    }
                    else{//addNormal shader
                        node->setGLProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));
                    }
                }
            }

        }
    }
    void ShaderArmature::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
    {
        Armature::draw(renderer, transform, flags);
    }

    void ShaderArmature::setIceState(){
        _fragSourceFile = "shader/IceShader.fsh";
        _vertSourceFile = "shader/IceShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }

    void ShaderArmature::setUsuaState(){
        initShader(false);
    }

    void ShaderArmature::setblurState(){
        _fragSourceFile = "shader/Blur.fsh";
        _vertSourceFile = "shader/Blur.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }

    void ShaderArmature::setbanishState(){
        _fragSourceFile = "shader/BanishShader.fsh";
        _vertSourceFile = "shader/BanishShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }

    void ShaderArmature::setfrozenState(){
        _fragSourceFile = "shader/FrozenShader.fsh";
        _vertSourceFile = "shader/FrozenShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }
    void ShaderArmature::setgrayState(){
        _fragSourceFile = "shader/GrayScalingShader.fsh";
        _vertSourceFile = "shader/GrayScalingShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }
    void ShaderArmature::setinvisState(){
        _fragSourceFile = "shader/InvisibleShader.fsh";
        _vertSourceFile = "shader/InvisibleShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }
    void ShaderArmature::setmirrorState(){
        _fragSourceFile = "shader/MirrorShader.fsh";
        _vertSourceFile = "shader/MirrorShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }
    void ShaderArmature::setpoisonState(){
        _fragSourceFile = "shader/PoisonShader.fsh";
        _vertSourceFile = "shader/PoisonShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }

    void ShaderArmature::setstoneState(){
        _fragSourceFile = "shader/StoneShader.fsh";
        _vertSourceFile = "shader/StoneShader.vsh";
        fragSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_fragSourceFile).c_str())->getCString();

        vertSource = (GLchar*)String::createWithContentsOfFile(
            FileUtils::getInstance()->fullPathForFilename(_vertSourceFile).c_str())->getCString();
        initShader(true);
    }
}

2,对于着色器文件,我将它们放在“res / shader”文件夹中。每个着色器由2个文件组成 - .vsh文件&amp;一个.fsh文件。以灰色为例:

  

GrayScalingShader.fsh

#ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform sampler2D u_texture;

void main()
{
    vec4 normalColor = v_fragmentColor * texture2D(u_texture, v_texCoord);

    //float gray = 0.299*0.5*normalColor.r + 0.587*0.5*normalColor.g + 0.114*0.5*normalColor.b;
    //gl_FragColor = vec4(gray*0.8 + normalColor.r*0.2, gray*0.8 + normalColor.g*0.2, gray*0.8 + normalColor.b*0.2, normalColor.a*0.3);
    float gray = dot(normalColor.rgb, vec3(0.299 * 0.5, 0.587 * 0.5, 0.114 * 0.5));
    gl_FragColor = vec4(gray, gray, gray, normalColor.a * 1);
}
  

GrayScalingShader.vsh

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif

void main()
{
    //gl_Position = CC_MVPMatrix * a_position;
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}

希望这会有所帮助。