トゥーン風味
PhongとかBlinnをとばしてトゥーンをやってみた。
意外と簡単。
トゥーン用テクスチャを動的に生成したり
陰の合成をグレイスケールの乗算じゃなくて
PhotoShopの焼き込みみたいな合成ができるとよろしいかもしれない。
さらにはシャドウが欲しいところであります。
Vertex Shader
void main(){ gl_Position = ftransform(); gl_FrontColor=gl_Color; // トゥーン用に法線からテクスチャ座標を計算する // 法線 vec3 normal = normalize(gl_NormalMatrix * gl_Normal); // 頂点から光源への方向ベクトル vec3 light = normalize(gl_LightSource[0].position.xyz); // 視線(0, 0, 0)から頂点への方向ベクトル vec3 eye = normalize(vec3(gl_ModelViewMatrix * gl_Vertex)); // 内積 float lgtdot = dot(light, normal); float eyedot = dot(eye, normal); // テクスチャ座標に割り当てる gl_TexCoord[0].s = lgtdot*0.5+0.5; // スクリーン座標(-1〜+1)からテクスチャ座標(0〜1)に変換 gl_TexCoord[0].t = eyedot*0.5+0.5; // スクリーン座標(-1〜+1)からテクスチャ座標(0〜1)に変換 }
Fragment Shader
uniform sampler2D toontex; void main(){ vec4 color = texture2D(toontex, gl_TexCoord[0].st); gl_FragColor = color * gl_Color; }
toontexにテクスチャユニット0を結び付けている。
順番的にテクスチャ生成、シェーダプログラム生成、Uniform変数設定の順番でやらないとうまくいかなかった。
Shaderの外でシェーダと関連するところ
テクスチャ読み込み
improt Image # PIL glPixelStorei(GL_UNPACK_ALIGNMENT,1) texture=glGenTextures(1) # 0 glBindTexture(GL_TEXTURE_2D, texture) # settings glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) # 画像読み込み image=Image.open(file) if len(image.getbands())!=4: image=image.convert("RGBA") size=image.size # テクスチャ生成 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size[0], size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, image.tostring())
テクスチャユニット0(デフォルト)にテクスチャオブジェクトを作成
Uniform変数の定義
# シェーダ変数 texLoc = glGetUniformLocation(program, "toontex") if texLoc==-1: print "no active uniform variable" glUniform1i(texLoc, 0); # シェーダ変数にテクスチャユニット0を結びつける
テクスチャユニットとuniform変数"toontex"を結びつける