着色器
转载 http://www.25kx.com/art/2424495
参考:
// ShaderNode.h
#include <iostream>
#include "cocos2d.h"
USING_NS_CC;
class ShaderNode : public CCNode
{
public:
ShaderNode();
bool initWithVertex(const char *vert, const char *frag);
void loadShaderVertex(const char *vert, const char *frag);
virtual void update(float delta);
virtual void setContentSize(const CCSize& var);
virtual void setColor(ccColor4F newColor);
virtual void draw();
static ShaderNode* shaderNodeWithVertex(const char *vert,
const char *frag);
private:
// 标示符
GLuint m_uniformResolution, m_uniformTime, m_uniformTex0;
GLuint m_attributeColor, m_attributePosition;
// 取值
float m_time;
ccVertex2F m_resolution,m_center;
GLuint m_texture;
GLfloat color[4];
};
// ShaderNode.cpp
#include "ShaderNode.h"
ShaderNode::ShaderNode()
{
}
ShaderNode* ShaderNode::shaderNodeWithVertex(const char *vert, const char *frag)
{
ShaderNode* shader = new ShaderNode();
if(shader && shader->initWithVertex(vert,frag))
{
shader->autorelease();
return shader;
}
CC_SAFE_DELETE(shader);
return NULL;
}
void ShaderNode::loadShaderVertex(const char *vert, const char *frag)
{
CCGLProgram* shader = new CCGLProgram();
shader->initWithVertexShaderFilename(vert, frag); //载入着色器程序
// 链接着色器程序之前一定要先绑定attribute变量
//绑定attribute变量
shader->addAttribute("a_position", 0);
shader->addAttribute("a_color", 1);
shader->link();
//获取attribute变量标识
m_attributeColor = glGetAttribLocation(shader->getProgram(), "a_color");
m_attributePosition = glGetAttribLocation(
shader->getProgram(), "a_position");
shader->updateUniforms();
//获取uniform变量标识
m_uniformResolution = glGetUniformLocation(shader->getProgram(), "resolution");
m_uniformTime = glGetUniformLocation(shader->getProgram(), "time");
m_uniformTex0 = glGetUniformLocation(shader->getProgram(), "tex0");
//使用着色器程序
this->setShaderProgram(shader);
shader->release();
}
void ShaderNode::setColor(ccColor4F newColor)
{
color[0] = newColor.r;
color[1] = newColor.g;
color[2] = newColor.b;
color[3] = newColor.a;
}
bool ShaderNode::initWithVertex(const char *vert, const char *frag)
{
// 获取shader程序
loadShaderVertex(vert,frag);
//aaaa.png为透明图片
m_texture = CCTextureCache::sharedTextureCache()->addImage("aaaa.png")->getName();
setContentSize(CCSizeMake(1024,768));
setColor(ccc4f(0.5,0.5,1,1));
m_time = 0;
scheduleUpdate();
return true;
}
void ShaderNode::update(float dt)
{
m_time += dt;
}
void ShaderNode::setContentSize(const CCSize& var)
{
CCNode::setContentSize(var);
m_resolution = vertex2(getContentSize().width,getContentSize().height);
// m_center.x = m_resolution.x/2;
// m_center.y = m_resolution.y/2;
}
void ShaderNode::draw()
{
CC_NODE_DRAW_SETUP();
//传递uniform变量
CCGLProgram* shader = getShaderProgram();
shader->setUniformLocationWith2f(m_uniformResolution, m_resolution.x,
m_resolution.y);
shader->setUniformLocationWith1i(m_uniformTex0, 0);
glUniform1f(m_uniformTime, m_time);
//获取attribute变量
CCSize size = this->getContentSize();
float w = size.width;
float h = size.height;
ccGLBindTexture2D(m_texture); //绑定纹理到槽位
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, w, h, 0); //截取屏幕数据到纹理
glEnableVertexAttribArray(m_attributePosition);
glDisableVertexAttribArray(m_attributeColor);
//传递attribute变量
GLfloat vertices[12] = {
0, 0, //左下0
w, 0, //右下1
w, h, //右上2
0, 0, //左下0
0, h, //左上3
w, h, //右上2
};
glVertexAttribPointer(m_attributePosition, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttrib4fv(m_attributeColor, color);
//绘制
glDrawArrays(GL_TRIANGLES, 0, 6);
}
//shader.fsh
//段着色器
varying vec4 v_color;
//背景纹理
uniform sampler2D tex0;
precision highp float;
//时间
uniform float time;
//分辨率
uniform vec2 resolution;
const float PI = 3.1415926535897932;
//速度
const float speed = 0.2;
const float speed_x = 0.3;
const float speed_y = 0.3;
//几何参数
const float intensity = 3.0;
const int steps = 8;
const float frequency = 4.0;
const int angle = 7;
//反射与凸起参数
const float delta = 20.0;
const float intence = 400.0;
const float emboss = 0.3;
//水波效果
float col(vec2 coord)
{
float delta_theta = 2.0 * PI / float(angle);
float col = 0.0;
float theta = 0.0;
for (int i = 0; i < steps; i++)
{
vec2 adjc = coord;
theta = delta_theta * float(i);
adjc.x += cos(theta)*time*speed + time * speed_x;
adjc.y -= sin(theta)*time*speed - time * speed_y;
col = col + cos((adjc.x*cos(theta) - adjc.y*sin(theta))
*frequency)*intensity;
}
return cos(col);
}
//main函数
void main(void)
{
vec2 p = (gl_FragCoord.xy) / resolution.xy, c1 = p, c2 = p;
float cc1 = col(c1);
c2.x += resolution.x/delta;
float dx = emboss*(cc1-col(c2))/delta;
c2.x = p.x;
c2.y += resolution.y/delta;
float dy = emboss*(cc1-col(c2))/delta;
c1.x += dx;
c1.y += dy;
float alpha = 1.+dot(dx,dy)*intence;
gl_FragColor = texture2D(tex0,c1)*(alpha) *v_color*(alpha);
}
//shader.vsh
//顶点着色器
//水纹颜色
attribute vec4 a_color;
//顶点坐标
attribute vec4 a_position;
varying vec4 v_color;
//坐标变换矩阵
//uniform mat4 u_MVPMatrix;
void main()
{
v_color = a_color;
gl_Position = CC_MVPMatrix * a_position;
}
测试代码:
ShaderNode* shader = ShaderNode::shaderNodeWithVertex("shader.vsh","shader.fsh");
shader->setContentSize(getContentSize());
shader->setColor(ccc4f(1,1,1.0,.5));
this->addChild(shader,2);
除此之外,引擎封装了一个特殊段动作类CCActionGrid3D,里面模拟了一些简单的3d特效。
引擎Demo中的EffectsTest演示了这些3D动作类。
引擎中的水纹效果
在场景中加入
// CCWaves3D::create(时间,晃动网格大小,波动速度,振幅);
CCGrid3DAction *grid = CCWaves3D::create(50, ccp(10, 10),40 , 10);
this->runAction(grid);