Cocos2d-x   发布时间:2022-05-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰

认识着色器

理解OpenGL渲染管线,对于学习OpenGL非常重要。下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段)

此图是从wiki中拿过来的,OpenGL的渲染管线主要包括:

  1. 准备顶点数据(通过VBO、VAO和Vertex attribute来传递数据给OpenGL)

  2. 顶点处理(这里主要由Vertex Shader来完成,从上图中可以看出,它还包括可选的Tessellation和Geometry shader阶段)

  3. 顶点后处理(主要包括Clipping,顶点坐标归一化和viewport变换)

  4. Primitive组装(比如3点组装成一个3角形)

  5. 光栅化成一个个像素

  6. 使用Fragment shader来处理这些像素

  7. 采样处理(主要包括Scissor Test,Depth Test,Blending,Stencil Test等)。

OpenGL Shader Language,简称GLSL,它是一种类似于C语言的专门为GPU设计的语言,它可以放在GPU里面被并行运行。
opengl es的着色器有.fsh和.vsh两个文件。这两个文件在被编译和链接后就可以产生可执行程序与GPU交互。
.vsh 是 vertex shader,用与顶点计算,可以理解控制顶点的位置,在这个文件中我们通常会传入当前顶点的位置,和纹理的坐标。
例如:
attribute vec4 position; 
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

precision mediump float;
uniform float overTurn;

void main()
{
gl_Position = position;
    if (overTurn>0.0) {
        textureCoordinate = vec2(inputTextureCoordinate.x,overTurn-inputTextureCoordinate.y);
    }
    else
        textureCoordinate = vec2(inputTextureCoordinate.x,inputTextureCoordinate.y);
}

首先,每一个Shader程序都有一个main函数,这一点和c语言是一样的。

这里面有两种类型的变量,一种是attribute,另一种是varying.

attribute是从外部传进来的,每一个顶点都会有这两个属性,所以它也叫做vertex attribute(顶点属性)。

而varying类型的变量是在vertex shader和fragment shader之间传递数据用的。

这里的变量命名规则保持跟c一样就行了,注意gl_开头的变量名是系统内置的变量,所以大家在定义自己的变量名时,请不要以gl_开头。

而CC_MVPMatrix是一个mat4类型的变量,它是在cocos2d-x内部设置进来的。

即:

attribute:外部传入vsh文件的变量 每帧的渲染的可变参数 变化率高 用于定义每个点。

varying:用于 vsh和fsh之间相互传递的参数。

precisionmediump float 定义中等精度的浮点数。

uniform 外部传入vsh文件的变量 变化率较低 对于可能在整个渲染过程没有改变 只是个常量。

在main()当overTurn大于0的时候,函数里面做的事情就是将纹理y轴反转。

vertex shader是作用于每一个顶点的,如果vertex有三个点,那么vertex shader会被执行三次。

.fsh 是片段shader。在这里面我可以对于每一个像素点进行重新计算。

varying highp vec2 textureCoordinate;
precision mediump float;
uniform sampler2D videoFrame;

vec4 memoryRender(vec4 color)
{
    float gray;
    gray = color.r*0.3+color.g*0.59+color.b*0.11;
    color.r = gray;
    color.g = gray;
    color.b = gray;
    
    color.r += color.r*1.5;
    color.g = color.g*2.0;
    
    if(color.r > 255.0)
    color.r = 255.0;
    if(color.g > 255.0)
    color.g = 255.0;
    
    return color;
}

void main()
{
    vec4 pixelColor;

    pixelColor = texture2D(videoFrame,textureCoordinatE);
    
    gl_FragColor = memoryRender(pixelColor);
}

varyinghighpvec2textureCoordinate就是从vsh中传过来了纹理坐标。

uniformsampler2DvideoFrame是我们真正的纹理贴图。

texture2D(videoFrame,textureCoordinatE) 将纹理中的每个像素点颜色取出到pixelColor。

可以用memoryRender(pixelColor)将取到像素点重新加工。

fragment shader中也有一个main函数,同时我们看到这里也声明了一个与vertex shader相同的变量textureCoordinate。前面我们讲过,这个变量是用来在vertex shader和fragment shader之间传递数据用的。所以,它们的参数类型必须完全相同。如果一个是vec3,一个是vec4,shader编译的时候是会报错的。

而gl_FragColor我们知道它肯定是一个系统内置变量了,它的作用是定义最终画在屏幕上面的像素点的颜色。

总结:

对于着色器的编程并不是很困难,完全是C的语法。但是debug比较麻烦,对于类型的约束也很严格,必须是相同类型的才能进行算术运算。我们理解了这两个文件之后,就可以发挥我们的想象对纹理图片做出各种的处理。

另有人总结:

vsh 负责搞定像素位置,填写gl_Posizion 变量,偶尔搞定一下点大小的问题,填写 gl_PixelSize。

fsh 负责搞定像素外观,填写 gl_FragColor ,偶尔配套填写另外一组变量。

他们都是一个像素运行一次的,也可能运行多次。为了“这一像素”而努力计算。

程序的版本是cocos2dx 3.0.vs 2012.

代码如下:

#ifndef  __GLTesTing_H_
#define  __GLTesTing_H_

#include "cocos2d.h"

USING_NS_Cc;

class GLTesTingLayer : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();  
    void menuCloseCallBACk(cocos2d::ref* pSender);
    CREATE_FUNC(GLTesTingLayer);
    void graySprite(Sprite * spritE);
    virtual void visit( Renderer* renderer,const kmMat4 &parentTransform,bool parentTransformupdated ) override;
    void onDraw();
private:
    Customcatommand _command;
};
#endif // ! __GLTesTing_H_

GLTesTingLayer
GLTesTingLayer
#include "GLTesTingLayer.h"

cocos2d::Scene* GLTesTingLayer::createScene()
{
    auto scene = Scene::create();
    auto layer = GLTesTingLayer::create();
    scene->addChild(layer);
    return scene;
}

bool GLTesTingLayer::init()
{
    if ( !Layer::init() )  
    {  
        return false;  
    }  

    this->setPosition(0,0);
    Size visibleSize = Director::geTinstance()->getVisibleSize();  
    auto sprite = Sprite::create("HelloWorld.png");  
    sprite->setAnchorPoint(Point(0.5,0.5));  
    sprite->setPosition(Point(visibleSize.width / 2,visibleSize.height / 2));  
    this->addChild(spritE);  
    graySprite(spritE);  

    this->setShaderProgram( ShaderCache::geTinstance()->getProgram(GLProgram::SHADER_NAME_POSITION_COLOR));

    return true;  
}

void GLTesTingLayer::menuCloseCallBACk( cocos2d::ref* pSender )
{

}

void GLTesTingLayer::graySprite( Sprite * sprite )
{
    if(spritE)  
    {   
        GLProgram * p = new GLProgram();  
        p->initWithFilenames("gray.vsh","gray.fsh");  
        p->bindAttribLOCATIOn(GLProgram::ATTRIBUTE_NAME_POSITION,GLProgram::VERTEX_ATTRIB_POSITION);  
        p->bindAttribLOCATIOn(GLProgram::ATTRIBUTE_NAME_COLOR,GLProgram::VERTEX_ATTRIB_COLOR);  
        p->bindAttribLOCATIOn(GLProgram::ATTRIBUTE_NAME_TEX_COORD,GLProgram::VERTEX_ATTRIB_TEX_COORDS);  
        p->link();  
        p->updateUniforms();  
        sprite->setShaderProgram(p);  
    }  

}

void GLTesTingLayer::visit( Renderer* renderer,bool parentTransformupdated )
{
    Layer::visit( renderer,parentTransform,parentTransformupdated );
    _command.init(_globalZOrder);
    _command.func = CC_CALLBACK_0(GLTesTingLayer::onDraw,this);
    Director::geTinstance()->getRenderer()->addCommand(&_command);
}

void GLTesTingLayer::onDraw()
{
    auto glProgram = this->getShaderProgram();
    glProgram->use();
    glProgram->setUniformsForBuilTins();
    glPointSize( 10.0f);
    glColor4f( 0.0f,1.0f,0.0f,1.0f);
    auto size = Director::geTinstance()->getWinSize();

    float vertercies[] = { 100,100,200,300,100 };
    float color[] = { 1,1,1 };
    GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR );
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,2,GL_FLOAT,GL_falSE,vertercies );
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,GL_TRUE,color);
    // 绘制三角形  
    glDrawArrays(GL_TRIANGLES,3 );
    //通知cocos2d-x 的renderer,让它在合适的时候调用这些OpenGL命令  
    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,3);
    checK_GL_ERROR_DEBUG();

}

GLTesTingLayer.cpp
GLTesTingLayer.cpp

内有利用shader使得sprite变灰的代码。

下面是变灰所用到的vsh和fsh文件。

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

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
                                
void main()    
{                            
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}

gray.vsh
gray.vsh
gray.fsh
varying vec4 v_fragmentColor;    
varying vec2 v_texCoord;    
uniform sampler2D CC_Texture0;    
        
void main()            
{
    vec4 v_orColor = v_fragmentColor * texture2D(CC_Texture0,v_texCoord);
    float gray = dot(v_orColor.rgb,vec3(0.299,0.587,0.114));
    gl_FragColor = vec4(gray,gray,v_orColor.a);
}                

gray.fsh
转自:http://www.cnblogs.com/slysky/p/3949718.html

大佬总结

以上是大佬教程为你收集整理的opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰全部内容,希望文章能够帮你解决opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。