はじめに
openFrameworksでは、openGLの機能であるGLSLというプログラム言語を使用することができます。
そこで今回、GLSLをopenFrameworksで使う方法を「マウスに追従するオーブのようなもの」を描画して簡単にご紹介いたします。
実行環境
・Xcode 8.3.3
・openFrameworks 0.9.8
・GLSL version 150
ポイントとして
・vertexShaderとfragmentShaderの2つのソースファイルを用意します。
・openFrameworksでGLSLを扱うのに、ofShaderオブジェクトを使用します。
Shaderソースの実装
・shader.vert
1 2 3 4 5 6 7 8 |
#version 150 uniform mat4 modelViewProjectionMatrix; in vec4 position; void main(){ gl_Position = modelViewProjectionMatrix * position; } |
・shader.frag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#version 150 out vec4 outputColor; uniform float time; uniform vec2 resolution; uniform vec2 mouse; void main( void ) { vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y); vec2 m = vec2(mouse.x, -mouse.y) / min(resolution.x, resolution.y) * 2.0; m.xy += vec2(-resolution.x, resolution.y) / min(resolution.x, resolution.y); float t = 0.1 / length(p - m); vec3 color = vec3(sin(time), cos(time), 0.5) * t; outputColor = vec4(color, 1.0); } |
fragmentShaderでは、openFrameworksから値を受け取る時にUniform変数で宣言します。
gl_FragCoordにはピクセルの位置が入っており、これをshader側で扱いやすくするために、resolutionを使い、shaderの画面座標を-1.0~1.0の値に正規化します。
mouseの値は、openFrameworksの画面座標が送られてくるため、こちらも先ほど正規化したshaderの座標と同様に-1.0~1.0の値に正規化します。
最終的に、outputColorで1ピクセル毎の色を指定しています。
openFrameworksの実装
今回のポイントでも挙げたように、openFrameworksでGLSLを扱うには、ofShaderを使用します。
shaderソースの置き場所は、プロジェクトフォルダ配下のbin/data/以下に置きます。
・main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "ofMain.h" #include "ofApp.h" int main(){ ofGLFWWindowSettings settings; settings.setGLVersion(3, 2); settings.width = 1024; settings.height = 768; ofCreateWindow(settings); ofRunApp(new ofApp()); } |
GLSL version 150を使用できるようにするため、main.cppにて設定を行なっています。
(defaultの設定の場合は、GLSL version 120を使用する必要があります。)
・ofApp.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#pragma once #include "ofMain.h" class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); //中略 ofShader shader; }; |
・ofApp.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include "ofApp.h" //-------------------------------------------------------------- void ofApp::setup(){ shader.load("shader.vert", "shader.frag"); } //-------------------------------------------------------------- void ofApp::update(){ } //-------------------------------------------------------------- void ofApp::draw(){ shader.begin(); shader.setUniform1f("time", ofGetElapsedTimef()); shader.setUniform2f("resolution", ofGetWidth(), ofGetHeight()); shader.setUniform2f("mouse", mouseX, mouseY); ofRect(0, 0, ofGetWidth(), ofGetHeight()); shader.end(); } //以下省略 |
ofApp.cppでは、draw()の中で、shader側に渡す処理と描画したい領域をbegin()とend()の中に記述します。
また、setUniformを使うことで、timeやresolution(画面サイズ)、mouseの値をshaderに渡しています。