Skip to content

Instantly share code, notes, and snippets.

@t-takasaka
Last active August 29, 2015 14:04
Show Gist options
  • Save t-takasaka/d221cb7d387456d2a975 to your computer and use it in GitHub Desktop.
Save t-takasaka/d221cb7d387456d2a975 to your computer and use it in GitHub Desktop.
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene(){
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init(){
if(!Layer::init()){ return false; }
m_visibleSize = Director::getInstance()->getVisibleSize();
//ブラーの幅等を計算
calculateGaussianWeights(m_radius / m_step, m_weights);
//スプライトを作成
m_sprite1 = Sprite::create("HelloWorld.png");
m_textureSize = m_sprite1->getTexture()->getContentSizeInPixels();
m_pixelSize = Size(float(m_step) / m_textureSize.width, float(m_step) / m_textureSize.height);
m_sprite1->setPosition(Point(m_textureSize.width / 2, m_textureSize.height / 2));
m_sprite1->retain();
// this->addChild(sprite1);
//シェーダをスプライトに紐付け(横方向にブラー)
GLProgram *shader1 = new GLProgram();
m_sprite1->setShaderProgram(shader1);
shader1->initWithFilenames("shaders/blur.vsh", "shaders/blur.fsh");
shader1->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
shader1->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);
shader1->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
shader1->link();
shader1->updateUniforms();
shader1->setUniformLocationWith2f(shader1->getUniformLocationForName("pixelSize"), m_pixelSize.width, m_pixelSize.height);
shader1->setUniformLocationWith2f(shader1->getUniformLocationForName("direction"), 1.0f, 0.0f);
shader1->setUniformLocationWith1i(shader1->getUniformLocationForName("radius"), m_radius);
glUniform1fv(shader1->getUniformLocationForName("weights"), MAX_RADIUS, (GLfloat*)m_weights);
// this->addChild(sprite1);
//スプライトを作成
m_sprite2 = Sprite::createWithTexture(m_sprite1->getTexture());
m_sprite2->setPosition(Point(m_visibleSize.width / 2, m_visibleSize.height / 2));
m_sprite2->setScale(2.0);
//シェーダをスプライトに紐付け(縦方向にブラー)
GLProgram *shader2 = new GLProgram();
m_sprite2->setShaderProgram(shader2);
shader2->initWithFilenames("shaders/blur.vsh", "shaders/blur.fsh");
shader2->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
shader2->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);
shader2->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
shader2->link();
shader2->updateUniforms();
shader2->setUniformLocationWith2f(shader2->getUniformLocationForName("pixelSize"), m_pixelSize.width, m_pixelSize.height);
shader2->setUniformLocationWith2f(shader2->getUniformLocationForName("direction"), 0.0f, 1.0f);
shader2->setUniformLocationWith1i(shader2->getUniformLocationForName("radius"), m_radius);
glUniform1fv(shader2->getUniformLocationForName("weights"), MAX_RADIUS, (GLfloat*)m_weights);
this->addChild(m_sprite2);
m_texture1 = RenderTexture::create(m_textureSize.width, m_textureSize.height);
m_texture1->retain();
this->scheduleUpdate();
return true;
}
void HelloWorld::update(float delta){
//ブラーの幅を再計算
m_radius = ++m_radius % MAX_RADIUS;
calculateGaussianWeights(m_radius / m_step, m_weights);
//紐付け済みのシェーダを取得して、ブラーの幅を更新
GLProgram *shader1 = m_sprite1->getShaderProgram();
shader1->updateUniforms();
shader1->setUniformLocationWith2f(shader1->getUniformLocationForName("pixelSize"), m_pixelSize.width, m_pixelSize.height);
shader1->setUniformLocationWith2f(shader1->getUniformLocationForName("direction"), 1.0f, 0.0f);
shader1->setUniformLocationWith1i(shader1->getUniformLocationForName("radius"), m_radius);
glUniform1fv(shader1->getUniformLocationForName("weights"), MAX_RADIUS, (GLfloat*)m_weights);
//スプライトをテクスチャに描画
m_texture1->beginWithClear(0, 0, 0, 1);
m_sprite1->visit();
m_texture1->end();
//ブラーのかかったテクスチャを元にスプライトを作成
m_sprite2->setTexture(m_texture1->getSprite()->getTexture());
m_sprite2->setFlippedY(true);
//紐付け済みのシェーダを取得して、ブラーの幅を更新
GLProgram *shader2 = m_sprite2->getShaderProgram();
shader2->updateUniforms();
shader2->setUniformLocationWith2f(shader2->getUniformLocationForName("pixelSize"), m_pixelSize.width, m_pixelSize.height);
shader2->setUniformLocationWith2f(shader2->getUniformLocationForName("direction"), 0.0f, 1.0f);
shader2->setUniformLocationWith1i(shader2->getUniformLocationForName("radius"), m_radius);
glUniform1fv(shader2->getUniformLocationForName("weights"), MAX_RADIUS, (GLfloat*)m_weights);
}
void HelloWorld::calculateGaussianWeights(const int points, float *weights){
float dx = 1.0f / float(points - 1);
float sigma = 1.0f / 3.0f;
float norm = 1.0f / (sqrtf(2.0f * M_PI) * sigma * points);
float divsigma2 = 0.5f / (sigma * sigma);
weights[0] = 1.0f;
for(int i = 1; i < MAX_RADIUS; i++){
if(i < points){
float x = float(i) * dx;
weights[i] = norm * expf(-x * x * divsigma2);
weights[0] -= 2.0f * weights[i];
}else{
weights[i] = 0.0;
}
}
}
void HelloWorld::menuCloseCallback(Ref* pSender){
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
{
public:
enum{ MAX_RADIUS = 32 };
HelloWorld():m_step(1), m_radius(0){}
~HelloWorld(){
}
int m_step, m_radius;
float m_weights[MAX_RADIUS];
cocos2d::Size m_visibleSize, m_textureSize, m_pixelSize;
cocos2d::Sprite *m_sprite1, *m_sprite2;
cocos2d::RenderTexture *m_texture1;
static cocos2d::Scene* createScene();
virtual bool init();
void update(float delta);
void calculateGaussianWeights(const int points, float *weights);
void menuCloseCallback(cocos2d::Ref* pSender);
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
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;
}
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform sampler2D u_texture;
uniform vec2 u_texSize;
uniform int u_mosaicLevel;
varying lowp vec4 v_fragmentColor;
uniform vec2 pixelSize;
uniform vec2 direction;
uniform int radius;
uniform float weights[32];
void main() {
vec4 sum = texture2D(u_texture, vec2(v_texCoord.x, v_texCoord.y)) * weights[0];
int MAX_RADIUS = 32;
for(int i = 1; i < MAX_RADIUS; i++){
if(i < radius){
vec2 offset = vec2(float(i) * pixelSize.x * direction.x, float(i) * pixelSize.y * direction.y);
sum += texture2D(u_texture, v_texCoord + offset) * weights[i];
sum += texture2D(u_texture, v_texCoord - offset) * weights[i];
}
}
gl_FragColor = sum * v_fragmentColor;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment