jit.gl.shader / GLSL でプロシージャルテクスチャ(ビーチボール)生成

スクリーンショット 2014-08-04 23.30.07

夏だしビーチボールで夏感を演出

嘘です。プログラムだけでテクスチャ生成する手法をプロシージャルテクスチャと呼ぶそうですが、OpenGL Superbibleにビーチボールのサンプルがあったので実装してみました。法線ベクトルやVertexの位置を利用して色を決めてますね。まだアルゴリズムを飲み込めてないので、ポケモンのハイパーボールを練習で作ってみようか。

JXS / GLSLコード

[html]
<jittershader name="mrr-3colored-lights">
<description>
</description>

<language name="glsl" version="1.2">
<program name="vp" type="vertex">
<![CDATA[

#version 120

varying vec3 N,L,V;

void main(void)
{
vec3 lightPos = gl_LightSource[0].position.xyz;

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

//map object-space position onto unit sphere
V =gl_Vertex.xyz;

//eye-space normal
N = gl_NormalMatrix * gl_Normal;

//eye-space light vector
vec4 Veye = gl_ModelViewMatrix * gl_Vertex;
L =lightPos – Veye.xyz;
}

]]>
</program>
<program name="fp" type="fragment">
<![CDATA[

#version 120

varying vec3 V;
varying vec3 N;
varying vec3 L;

const vec3 myRed = vec3(1,0,0);
const vec3 myYellow = vec3(1,1,0);
const vec3 myGreen = vec3(0,1,0);
const vec3 myBlue = vec3(0,0,1);
const vec3 myWhite = vec3(1,1,1);
const vec3 myBlack = vec3(0,0,0);

const vec3 northHalfSpace = vec3(0,0,1);
const vec3 northeastHalfSpace = vec3(0.707,0,0.707);
const vec3 northwestHalfSpace = vec3(-0.707,0,0.707);
const float capSize = 0.03;
const float smoothEdgeTol = 0.0005;
const float ambientLighting = 0.1;
const float specularExp = 10.0;
const float specularIntensity = 0.5;

void main()
{
vec3 NN = normalize(N);
vec3 NL = normalize(L); //for ambient;
vec3 NH = normalize(NL +vec3(0,0,1)); //for specular
vec3 NV = normalize(V);

float mirror = (NV.x >= 0) ? 1. : -1.;
NV.xz *= mirror; //

vec4 distance;
distance.x = dot(NV, northHalfSpace);
distance.y = dot(NV, northeastHalfSpace);
distance.z = dot(NV, northwestHalfSpace);

distance.w = abs(NV.y) – 1.0 + capSize;
distance = smoothstep(vec4(0.), vec4(smoothEdgeTol), distance);

vec3 surfColor = mix(myBlack,myRed,distance.x);
surfColor += mix(myBlack,myGreen,distance.y * (1.0 – distance.z));
surfColor += mix(surfColor, myBlue, 1.0 – distance.y);

//top bottom
surfColor = mix(surfColor, myWhite, distance.w);

//ambient
surfColor *= (ambientLighting + vec3(max(0,dot(NN,NL))));
//specluar
surfColor += (specularIntensity *vec3(pow(max(0,dot(NN,NH)),specularExp)));

gl_FragColor = vec4(surfColor,1);
}
]]>
</program>
</language>
</jittershader>
[/html]

jit.gl.shader / GLSL で specular lighting を実装してみた #maxmsp #jitter #glsl

スクリーンショット 2014-08-04 22.09.47

Specular Lighting

OpenGL Superbibleのサンプルコードを練習がてら実装してみました。こちらの本は5th Editionも出ているのですが、Maxの対応がOpenGL2.0 / GLSL1.2 までなので、4th Editionを使っています。

JXS / GLSLサンプルコード

[html]
<jittershader name="mrr.specular">
<description>
specular-light
</description>

<language name="glsl" version="1.2">
<program name="vp" type="vertex">
<![CDATA[

#version 120

void main(void)
{
//normal MVP transform
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

//Lighting
vec3 lightPos = gl_LightSource[0].position.xyz;

vec3 N = normalize(gl_NormalMatrix * gl_Normal);
vec4 V = gl_ModelViewMatrix * gl_Vertex;
vec3 L = normalize(lightPos – V.xyz);
vec3 H = normalize(L + vec3(0,0,1));

const float specularExp = 128.;

//calculate diffuse lighting
float NdotL = max(0,dot(N,L));
gl_FrontColor = gl_Color *vec4(NdotL);

//calculate specular lighting
float NdotH = 0;//max(0.0, dot(N,H));

if(NdotL > 0.0){
NdotH = max(0.0,dot(N,H) * 8.0 – 7.0);
}

gl_TexCoord[0] = vec4(NdotH,0,0,1);
}
]]>
</program>
<program name="fp" type="fragment">
<![CDATA[

#version 120

void main()
{
//add diffuse & specular
gl_FragColor = gl_Color + gl_TexCoord[0];
}
]]>
</program>
</language>
</jittershader>
[/html]

おまけ

スクリーンショット 2014-08-04 21.38.19
法線ベクトルで色を塗ってみました。

Cycling74 Max で GLSL1.2 を使ったシェーディングをはじめよう #maxmsp #jitter #glsl

スクリーンショット 2014-08-04 16.08.30

シェーダがあるでは無いか!

Maxを使ったインタラクティブアプリケーションの開発は、音や音楽とのインタラクションや、Ableton Liveとの連携、コンパイルしないで変更を加え続けられるリアルタイム性など、他には無い独自なメリットが色々とあると思います。

しかし3Dの描画に関しては、OpenGLの対応バージョンが2.0止まりな事もあり、openFrameworksやUnity等の開発環境と比べると少し見劣りします。とはいえ、プログラマブルシェーダを利用する事ができるので、可能性としては例えばSIGGRAPHの論文を実装して最新のレンダリングもできるのではないかな・・・!?

そこで今回はMaxの3D描画を強化するべく、jitterに関するGLSL周辺の調査とサンプルプログラム試してみました。

Maxにおけるシェーダについて

  • JXSファイル:XML形式でMaxとやりとりを行うパラメーター等を記述するファイル。またGLSL等のシェーダをこのファイルに読込むか直接書く事でシェーダを利用する。.jxsファイルで保存したらjit.gl.shaderとjit.gl.slabでreadして使う。
  • シェーダの種類:Vertex Shader / Geometry Shader / Fragment Shader が利用可能
  • シェーダ言語:GLSL1.2 / CG / ARB
  • 豊富なサンプル:Mac版のフォルダパス→ /Applications/Max 6.1/Cycling ’74/jitter-shaders Geometry ShaderやGPGPU、Audio処理用のシェーダも。ジオメトリシェーダを使う際は、プリミティブの種類がシェーダと合ってないと利用できないので注意。
  • Cycling74 Forumでは、GLSL1.5(OpenGL3)そうとうのシェーダーが使えるという記述がありましたが、私の環境(Macbook Pro Retina / Mavericks)では利用できませんでした。
  • jit.gl.pix:フラグメントシェーダのみに特化したオブジェクト。jit.gl.slabと互換。

jit.gl.pixでは使えないバーテックスとジオメトリが鍵になりそうな気がしますね。今後の記事でサンプルファイルなどを紹介できればと思います。

JXS / GLSLサンプルコード

[html]
<jittershader name="mrr-test-simple">
<description>
test
</description>

<language name="glsl" version="1.2">
<program name="vp" type="vertex">
<![CDATA[

#version 120

void main(void)
{
vec4 clipCoord = gl_ModelViewProjectionMatrix *gl_Vertex;
gl_Position = clipCoord;
gl_FrontColor = gl_Color;

vec3 ndc =clipCoord.xyz / clipCoord.w;

gl_FrontSecondaryColor = vec4((ndc *0.5) +0.5,1);

//gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
]]>
</program>
<program name="fp" type="fragment">
<![CDATA[

#version 120

void main()
{
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
gl_FragColor =mix(gl_Color,vec4(vec3(gl_SecondaryColor),1.),1);
}
]]>
</program>
</language>
</jittershader>
[/html]

上記画像は、jit.gl.shaderに上記JXSファイルを読み込ませて、jit.gl.gridshapeとjit.gl.multiple で作ったモデルに対してアタッチして生成した画像です。glsl部分は、外部ファイルを読込む事も可能です。

参考サイト