2012.02.28 | 

最近やたら長いページが多くなってしかもパララックス効果とかあったりして
どうせなら滑らかにスクロールさせたいなーと思う今日この頃、
今夜は雪らしいですよ。こんにちはmuchoです。

というわけで、マウスホイールでのスクロールやスクロールバーをドラッグした時に
滑らかにスクロールするプラグインです。
smoothScrollerDemo

最初、ユーザーからのスクロール変更情報をキャプチャできないものかと画策したのですが、
mousewheelのイベントならともかく、onscrollイベントだと画面のスクロールそのものにかかってしまい、
ユーザーがスクロールバーを操作して発生したイベントかどうか判別できず断念。
そこで、
0.position:fixedをサポートしてるブラウザかチェック
1.コンテンツ全体を新規divでくるんでposition:fixedをかけて、
2.さらに空のdivタグでコンテンツ全体の高さを保持。
3.スクロールイベントでtop位置の変更をsetIntervalで回す。

BODYタグに背景画像を入れたり、
position:fixedのオブジェクトが他にあると
挙動がおかしくなるかもしれません。
使っていくうちにブラッシュアップできればと思います。



// コンテンツ全体を一つのオブジェクトに包んでプラグインを当てる
$(document).ready(function () {
	$("#page").smoothScroller({fps:60,speed:0.1});
});



というわけでまだアルファ版ですがよろしければどうぞ。
jquery.smoothScroller.zip

2012.02.27 | 

はじめまして。きょんたろです。
今回はhtml5のcanvasをすぐ使うようにTempleteを作ってみました。
まだいろんな技能はないですけどどんどんupdateする予定です。
そして追加したらいいな~ものがあれば教えてくださったら追加しておきます。

1.cssはdevjamのtempleteを使っています。
2.utils.jsにはいろいろutilのjsがicludeされています。
3.canvasUtils.jsにはcanvasの関するjsがicludeされています。
4.canvasBase.jsは基本になるjsです。
CanvasBasic_ver1.zip





    
        
        
        
        index
        
        
        
        
        
        
        
        
         
        
        
        
        
        
    
    
       
    




 
/**
 * @author shiftBrain DevJam
 * canvas groung ver1 
 * 2012.02.23
 */

//--------------------------------------------------------------------------------
// window loaded
//--------------------------------------------------------------------------------
function canvasStart(canvasID)
{
   if(canvasSupport){
       canvasApp(canvasID);
   }
}

//--------------------------------------------------------------------------------
// canvas support ture ? false
//--------------------------------------------------------------------------------
function canvasSupport(){
    return Modernizr.canvas
}

function canvasApp(canvasID)
{
    // ---------------------------------------------------------------------------
    // Common Variables ----------------------------------------------------------

    var sw;     // window Width
    var sh;     // window height 

    var cvs;    // canvas
    var ctx;    // canvas context
    var resize  = false; // canvas resize function true / false
    var frame   = new FrameRateApp(10); //bin/common/js/utils/frameRateApp.js
    var timer   = new Timer(); //bin/common/js/utils/timerApp.js

    //Debugger.log(frame.getInteval());
    //Debugger.log(frame.getFRAME());

    cvs     = document.getElementById(canvasID);
    ctx     = cvs.getContext("2d");
    resize  = false;
    canavsResize();

    // ---------------------------------------------------------------------------
    // canvas resize -------------------------------------------------------------
    // ## HOW TO USE ##
    // canavsResize()       --> window Size Setting
    // canavsResize(10,10)  --> width=10 height=10 customer size setting
    // ---------------------------------------------------------------------------

    window.addEventListener("resize",canavsResize, false);
    function canavsResize(w,h){
        sw = WindowSize.width();  //bin/common/js/utils/getSize.js
        sh = WindowSize.height();       
        Debugger.log("resizeEvent="+sw+"x"+sh);
        if(!w || !h){
            if(cvs && resize){
                cvs.width  = sw;
                cvs.height = sh;
            }
        }else{
            if(cvs){
                cvs.width  = w;
                cvs.height = h;
            }
        }
        Debugger.log("canvasSize="+cvs.width+"x"+cvs.height);
    }

// ***************************************************************************
// Code main ***********************************************************
    // ここから 変数と関数は 気に入るように変更してもいいです。

    function setup(){

    }

    function main(){
        update();
        draw();
    }

    function update()
    {

    }

    function draw()
    {

    }

// ---------------------------------------------------------------------------
// rendering Setting ---------------------------------------------------------
    setup();
    frame.setFRAME(30);    
    timer.start(main,frame.getInteval());
//setTimeout(timer.stop,3000)
}


2012.02.25 | 


記事とは関係ないけど、Fractal Noiseで遊んでみた動画
というのもHSV変換は絵がないので。
こんばんはこんばんは。muchoです。こんばんは。

以前 ActionScriptでもやったので、全然目新しくないですが、
GLSLでも変換する必要があったので作りました。




// vertical Shader

#version 120
vec3 HSVtoRGB(vec3 hsv)
{
	vec3 col;
	float hue = mod(hsv.r, 360.0);
	float s = max(0, min(1, hsv.g));
	float v = max(0, min(1, hsv.b));
	if(s > 0.0) {
		int h = int(floor(hue / 60.0));
		float f = hue / 60.0 - float(h);
		float p = v * (1.0 - s);
		float q = v * (1.0 - f * s);
		float r = v * (1.0 - (1.0 - f) * s);

		if(h == 0) col = vec3(v, r, p);
		else if(h == 1) col = vec3(q, v, p);
		else if(h == 2) col = vec3(p, v, r);
		else if(h == 3) col = vec3(p, q, v);
		else if(h == 4) col = vec3(r, p, v);
		else col = vec3(v, p, q);
	}else{
		col = vec3(v);
	}
	return col;
}

void main()
{
	gl_FragColor.rgb = HSVtoRGB(vec3(gl_TexCoord[0].x * 360.0, gl_TexCoord[0].y, 1.0));
	gl_FragColor.a = 1.0;
}


こんなかんじで、カラーピッカーもどきなグラデが描画されます。
こういうシンプルなのは今後はWEBGLでブログにアップしたいです。
今後ってのがいつになるやら・・・

2012.02.16 | 

こんにちは。muchoです。
前回のGLSL Gaussian Blur もどき part1に引き続き、GLSLでBlurをかけてみました。

前回、ガウス分布を求める公式がおかしいなーと思いしらべてみたところ
やっぱりおかしかったんですが、ガウス分布はやっぱり正弦波のようなので
結果的には一緒だろうということで、前回と変わらず。
変えたところは、ブラーのサイズによって、計算回数が増えていくんですが、
見た目と速度の具合で、調整しました。

ブラーサイズ50pxで60fps

ブラーサイズ100pxで60fps

ブラーサイズ300pxだと40fpsを切ってしまった。

前回とロジックは一緒で
一度横にブラーをかけ、その後、縦のブラーをかけています。
フレームバッファオブジェクトを使ったらかなり高速になりました。
以下抜粋ソースです。なにかの参考になれば。



//-----------------------------------------------------
//cpp
#include "cinder/app/AppBasic.h"
#include "cinder/Capture.h"
#include "cinder/gl/Fbo.h"
#include "cinder/gl/gl.h"
#include "cinder/gl/GlslProg.h"
#include "cinder/gl/Texture.h"
#include "Resources.h"

static const int X_RES  = 640;
static const int Y_RES  = 480;

using namespace ci;
using namespace ci::app;
using namespace std;

class GSLS_GaussianBlurApp : public AppBasic {
  public:
	void setup();
	void update();
	void draw();
	
	Color		backGround;
	ColorA		drawColor;
	float		mBlurSize;
	float		mBloom;
	float		fps;
	
	Capture		mCapture;
	
	// TEXTURE AND SHADER AND FBO
	gl::Texture	mTexture;
	gl::Fbo		mFbo;
	gl::GlslProg	mShaderH, mShaderV;
};

void GSLS_GaussianBlurApp::setup()
{
	backGround = Color(0,0,0);
	drawColor = ColorA( 1.0f, 1.0f, 1.0f, 1.0f );

	try {
		mCapture = Capture( X_RES, Y_RES );
		mCapture.start();
	}
	catch( ... ) {
		console() << "Failed to initialize capture" << endl;
	}
	
	// SETUP PARAMS
	mParams = params::InterfaceGl( "params", Vec2i( 200, 85 ) );
	mParams.addParam( "FPS", &fps );
	mParams.addParam( "BlurSize", &mBlurSize, "min=0.0 max=500.0 step=1.0" );
	mParams.addParam( "Bloom", &mBloom, "min=0.0 max=2.0 step=0.01" );
	
	// SETUP SHADER
	mShaderH	= gl::GlslProg( loadResource( RES_VERT_ID ), loadResource( RES_HFRAG_ID ) );
	mShaderV	= gl::GlslProg( loadResource( RES_VERT_ID ), loadResource( RES_VFRAG_ID ) );
	
	// SETUP FBO
	gl::Fbo::Format format;
	mFbo = gl::Fbo( X_RES, Y_RES, format );
	
	// GL setup
	gl::enableAlphaBlending();
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	gl::clear( backGround, true );	
}

void GSLS_GaussianBlurApp::update()
{
	if( !mCapture || !mCapture.checkNewFrame()) return;
	mTexture = mCapture.getSurface();
	fps = getAverageFps();
}

void GSLS_GaussianBlurApp::draw()
{
	gl::clear( backGround, true );
	if(!mTexture) return;
	//
	// テクスチャーから横ブラーをFBOへドロー
	gl::pushMatrices();
	gl::setMatricesWindow(X_RES, Y_RES, false);
	mFbo.bindFramebuffer();
	gl::clear( backGround, true );
	mTexture.bind( 0 );
	mShaderH.bind();
	mShaderH.uniform( "texture0", 0 );
	mShaderH.uniform( "width", X_RES );
	mShaderH.uniform( "blurSize", mBlurSize );
	mShaderH.uniform( "bloom", mBloom );
	gl::drawSolidRect( getWindowBounds() );
	gl::popMatrices();
	mShaderH.unbind();
	mTexture.unbind();
	mFbo.unbindFramebuffer();
	gl::popModelView();
	//
	// FBOから縦ブラーをシーンにドロー
	gl::pushModelView();
	mFbo.bindTexture(0);
	mShaderV.bind();
	mShaderV.uniform( "texture0", 0 );
	mShaderV.uniform( "height", Y_RES );
	mShaderV.uniform( "blurSize", mBlurSize );
	mShaderV.uniform( "bloom", mBloom );
	gl::drawSolidRect( getWindowBounds() );
	mShaderV.unbind();
	mFbo.unbindTexture();
	gl::popModelView();
}





//-----------------------------------------------------
// Vertex Shader
void main()
{
	gl_TexCoord[0] = gl_MultiTexCoord0;
	gl_Position = ftransform();
}





//-----------------------------------------------------
// Fragment Shader horizontal

#version 120
uniform sampler2D texture0;
uniform int width;
uniform float blurSize;
uniform float bloom;

void main()
{
	float v;
	float pi = 3.141592653589793;
	float e_step = 1.0 / width;
	float radius = blurSize;
	if ( radius < 0 ) radius = 0;
	int steps = int(min(radius * 0.7, sqrt(radius) * pi));
	float r = radius / steps;
	float t = bloom / (steps * 2 + 1);
	float x = gl_TexCoord[0].x;
	float y = gl_TexCoord[0].y;
	vec4 sum = texture2D(texture0, vec2(x, y)) * t;
	int i;
	for(i = 1; i <= steps; i++){
		v = (cos(i / (steps + 1) / pi) + 1) * 0.5;
		sum += texture2D(texture0, vec2(x + i * e_step * r, y)) * v * t;
		sum += texture2D(texture0, vec2(x - i * e_step * r, y)) * v * t;
	}
 
  gl_FragColor = sum;
	
}





//-----------------------------------------------------
// vertical Shader horizontal

#version 120
uniform sampler2D texture0;
uniform int height;
uniform float blurSize;
uniform float bloom;

void main()
{
	float v;
	float pi = 3.141592653589793;
	float e_step = 1.0 / height; 
	float radius = blurSize;
	if ( radius < 0 ) radius = 0;
	int steps = int(min(radius * 0.7, sqrt(radius) * pi));
	float r = radius / steps;
	float t = bloom / (steps * 2 + 1);
	float x = gl_TexCoord[0].x;
	float y = gl_TexCoord[0].y;
	vec4 sum = texture2D(texture0, vec2(x, y)) * t;
	int i;
	for(i = 1; i <= steps; i++){
		v = (cos(i / (steps + 1) / pi) + 1) * 0.5;
		sum += texture2D(texture0, vec2(x, y + i * e_step * r)) * v * t;
		sum += texture2D(texture0, vec2(x, y - i * e_step * r)) * v * t;
	}
 
  gl_FragColor = sum;
	
}



個人的には100ピクセルぼかして60fps出せたので大満足!

2012.02.13 | 

あと15分で月曜日。今回苦戦のため画像が準備できませんでした。
こんばんはmuchoです。

今回はGLSLでGaussian Blurの自作に挑戦しました。
作りたいというか欲しかったのが、とにかく高速で、大きくボケるフィルター。

ズバリ目指したのはこれ↓
http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
最初はquasimondoさんのソースをさっくり移植しようと思ったんですが、
商用で使ってる方もいるみたいで、二次利用を断念。

こちらのサイトを参考にしました。
http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
英語なのでいまいちよく分かりませんが、
まず横にぼかしをかけて、
その結果画像をさらに縦にぼかすと
計算が少なくてすむということらしい。
9ピクセルぼかすとすると本来なら
9x9=81
それを横と縦で分けることで
9+9=18
この差は大きい!
実際9x9的な本来のブラーを作ってみましたが、OpenCVのGaussian Blurと比べて
高速化が感じられず、上記の横かけて、縦かけての2段階描画方式にしてみました。
まずはそのままコピペしてみたところ、大きくぼかすとおかしなことに。
というわけで、参考サイトでは9+9固定なのですが、ボカすサイズによって、
描画回数が変わるように書き直してみました。
以下がそのソース。

煮詰まりまくりで作ったので、微妙にソースに意味不明なところがあります。
さらにどうも正弦波の値の求め方がおかしいような?
おまけに、本来のブラーよりは高速化したとはいえ、大きくぼかすと
まだまだ実用には厳しい遅さ。。。
次回はquasimondoさんのソースをさらに読み解きつつ、
これをチューニングできたらと思います。できるのかなー。怪しいなー。



//horizontal Fragment Shader
#version 120
uniform sampler2D texture0;
uniform int width;
uniform int height;
uniform float blurSize;

void main()
{
	float v;
	float w_step = 1.0 / width;
	float h_step = 1.0 / height; 
	float radius = blurSize;
	if ( radius < 0 ) radius = 0;
	int steps = int(radius);
	float x = gl_TexCoord[0].x;
	float y = gl_TexCoord[0].y;
	float pi = 3.141592653589793;
	float t = 1/(steps*2+1);
	vec4 sum = texture2D(texture0, vec2(x, y))*t;
	int i;
	for(i = 1; i<=steps;i++){
		v = (cos(i/(steps+1)*pi)+1)*0.5;
		sum += texture2D(texture0, vec2(x + i*w_step, y))*v*t;
		sum += texture2D(texture0, vec2(x - i*w_step, y))*v*t;
	}
 
  gl_FragColor = sum;
	
}

//---------------------------------------------------------------
//vertical Fragment Shader

#version 120
uniform sampler2D texture0;
uniform int width;
uniform int height;
uniform float blurSize;

void main()
{
	float v;
	float w_step = 1.0 / width;
	float h_step = 1.0 / height; 
	float radius = blurSize;
	if ( radius < 0 ) radius = 0;
	int steps = int(radius);
	float x = gl_TexCoord[0].x;
	float y = gl_TexCoord[0].y;
	float pi = 3.141592653589793;
	float t = 1/(steps*2+1);
	vec4 sum = texture2D(texture0, vec2(x, y))*t;
	int i;
	for(i = 1; i<=steps;i++){
		v = (cos(i/(steps+1)/pi)+1)*0.5;
		sum += texture2D(texture0, vec2(x, y + i*h_step))*v*t;
		sum += texture2D(texture0, vec2(x, y - i*h_step))*v*t;
	}
 
  gl_FragColor = sum;
	
}