zoukankan      html  css  js  c++  java
  • 用shader使图片背景透明

    转自:http://blog.csdn.net/dawn_moon/article/details/8631783

    好吧,终于抽时间写这篇文章了。

    手头上有很多人物行走图,技能特效图等,但这些图都有个纯黑色背景,怎么样将内容显示出来,让背景透明呢?前段时间搞了一下,感谢群里的童鞋们,提供了思路和方法。

     

    这里用shader处理了像素,使黑色背景透明,直接上代码

    ShaderSprite.h

    #ifndef __TestShader__ShaderSprite__
    #define __TestShader__ShaderSprite__
    
    #include "cocos2d.h"
    USING_NS_CC;
    
    class ShaderSprite : public CCSprite {
        
    public:
        static ShaderSprite* create(const char* pszFileName);
        virtual bool initWithTexture(CCTexture2D *pTexture, const CCRect& rect);
        virtual void draw(void);
    };
    
    #endif /* defined(__TestShader__ShaderSprite__) */

    ShaderSprite.cpp

    #include "ShaderSprite.h"
    
    static CC_DLL const GLchar *transparentshader =
    #include "tansparentshader.h"
    
    ShaderSprite* ShaderSprite::create(const char *pszFileName)
    {
        ShaderSprite *pRet = new ShaderSprite();
        if (pRet && pRet->initWithFile(pszFileName)) {
            pRet->autorelease();
            return pRet;
        }
        else
        {
            delete pRet;
            pRet = NULL;
            return NULL;
        }
    }
    
    bool ShaderSprite::initWithTexture(CCTexture2D *pTexture, const CCRect& rect)
    {
        do{
    //        CCLog("override initWithTexture!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            CC_BREAK_IF(!CCSprite::initWithTexture(pTexture, rect));
            
            // 加载顶点着色器和片元着色器
            m_pShaderProgram = new  CCGLProgram();
            m_pShaderProgram ->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, transparentshader);
            
            CHECK_GL_ERROR_DEBUG();
            
            // 启用顶点着色器的attribute变量,坐标、纹理坐标、颜色
            m_pShaderProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
            m_pShaderProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
            m_pShaderProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
            
            CHECK_GL_ERROR_DEBUG();
            
            // 自定义着色器链接
            m_pShaderProgram->link();
            
            CHECK_GL_ERROR_DEBUG();
            
            // 设置移动、缩放、旋转矩阵
            m_pShaderProgram->updateUniforms();
            
            CHECK_GL_ERROR_DEBUG();
            
            return true;
            
        }while(0);
        return false;
    }
    
    void ShaderSprite::draw(void)
    {
    //    CCLog("override draw!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
        
        CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
        
        CC_NODE_DRAW_SETUP();
        
        //
        // 启用attributes变量输入,顶点坐标,纹理坐标,颜色
        //
        ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
        ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst);
        
        m_pShaderProgram->use();
        m_pShaderProgram->setUniformsForBuiltins();
        
        // 绑定纹理到纹理槽0
        ccGLBindTexture2D(m_pobTexture->getName());
    
    
        
    #define kQuadSize sizeof(m_sQuad.bl)
        long offset = (long)&m_sQuad;
        
        // vertex
        int diff = offsetof( ccV3F_C4B_T2F, vertices);
        glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
        
        // texCoods
        diff = offsetof( ccV3F_C4B_T2F, texCoords);
        glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
        
        // color
        diff = offsetof( ccV3F_C4B_T2F, colors);
        glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
        
        
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        
        CHECK_GL_ERROR_DEBUG();
    
        CC_INCREMENT_GL_DRAWS(1);
        CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
    }

    片段着色器代码

    tansparentshader.h

    "                                                       
    
    #ifdef GL_ES                                            
    
    precision lowp float;                                   
    
    #endif                                                  
    
    varying vec4 v_fragmentColor;                           
    
    varying vec2 v_texCoord;                                
    
    uniform sampler2D u_texture;                            
    
    void main()                                             
    
    {                                                       
    
        float ratio=0.0;                                    
    
        vec4 texColor = texture2D(u_texture, v_texCoord);   
    
        ratio = texColor[0] > texColor[1]?(texColor[0] > texColor[2] ? texColor[0] : texColor[2]) :(texColor[1] > texColor[2]? texColor[1] : texColor[2]);                                      
    
    if (ratio != 0.0)                                          
    
    {                                                          
    
        texColor[0] = texColor[0] /  ratio;                    
    
        texColor[1] = texColor[1] /  ratio;                    
    
        texColor[2] = texColor[2] /  ratio;                    
    
        texColor[3] = ratio;                                   
    
    }                                                          
    
    else                                                       
    
    {                                                          
    
        texColor[3] = 0.0;                                     
    
    }                                                          
    
    gl_FragColor = v_fragmentColor*texColor;                   
    
    }";

    注意shader编程没有隐士数据类型转换,所以都显示为float了。

    然后ratio是指在rgb中找最大的,如果ratio为0直接将alpha设为0,否则alpha设为ratio,然后各rgb除以ratio,这里是为了做渐变,否则变化太生硬。

    上图:

    好了,上面两张图是一样的。只是屏幕背景一个是白色,一个是黑色。图片背景透明了。

      

  • 相关阅读:
    iOS企业账号打包发布App到自己服务器上
    DBus 接口
    Ubuntu下安装gazebo
    Ubuntu下添加开机启动脚本
    Ubuntu录屏软件Kazam
    使用ceres编译报错 error: ‘integer_sequence’ is not a member of ‘std‘
    LINUX中查看、添加、删除PATH以及永久添加PATH
    Ubuntu完美解决Github网站打不开问题
    PointNet原理详解
    目标检测算法RCNN,Fast RCNN,Faster RCNN
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/3527554.html
Copyright © 2011-2022 走看看