« サブカテゴリー | メイン | RD-XS38(3) 番組ナビ お気に入り »

2006年02月12日

RenderMonkey(2) テクスチャパラメータ

新規にワークスペースを作ってみます。これはとても簡単で、RenderMonkey を立ち上げた後に [Effect Workspace で右クリック] → [Add Default Effect] → [DirectX/OpenGL] でそれぞれ選択が可能です。この雛型を選択するだけでそのまま動作するエフェクトが作成されます。

AddDefaultEffect.jpg
fig.1 Add Default Effect

例えば Textured Bump を選択します。デフォルト状態ではモデルは Sphere.3ds が選択されています[fig.2(a)]。モデルは前回示したように簡単に変更することができます[fig.2(b)]。

model_shpere.jpg
fig.2 (a) モデル変更前

model_teapot.jpg
fig.2 (b) モデル変更後

また Vertex Program / Fragment Program も自動的に生成されているので、あとは好きなように編集をすることが可能です。

uniform vec3 fvLightPosition;
uniform vec3 fvEyePosition;

varying vec2 Texcoord;
varying vec3 ViewDirection;
varying vec3 LightDirection;
   
attribute vec3 rm_Binormal;
attribute vec3 rm_Tangent;
   
void main( void )
{
   gl_Position = ftransform();
   Texcoord    = gl_MultiTexCoord0.xy;
    
   vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;
   
   vec3 fvViewDirection  = fvEyePosition - fvObjectPosition.xyz;
   vec3 fvLightDirection = fvLightPosition - fvObjectPosition.xyz;
     
   vec3 fvNormal         = gl_NormalMatrix * gl_Normal;
   vec3 fvBinormal       = gl_NormalMatrix * rm_Binormal;
   vec3 fvTangent        = gl_NormalMatrix * rm_Tangent;
      
   ViewDirection.x  = dot( fvTangent, fvViewDirection );
   ViewDirection.y  = dot( fvBinormal, fvViewDirection );
   ViewDirection.z  = dot( fvNormal, fvViewDirection );
   
   LightDirection.x  = dot( fvTangent, fvLightDirection.xyz );
   LightDirection.y  = dot( fvBinormal, fvLightDirection.xyz );
   LightDirection.z  = dot( fvNormal, fvLightDirection.xyz );
   
}
fig.3 Vertex Program
uniform vec4 fvAmbient;
uniform vec4 fvSpecular;
uniform vec4 fvDiffuse;
uniform float fSpecularPower;

uniform sampler2D baseMap;
uniform sampler2D bumpMap;

varying vec2 Texcoord;
varying vec3 ViewDirection;
varying vec3 LightDirection;

void main( void )
{
   vec3  fvLightDirection = normalize( LightDirection );
   vec3  fvNormal         = normalize( ( texture2D( bumpMap, Texcoord ).xyz * 2.0 ) - 1.0 );
   float fNDotL           = dot( fvNormal, fvLightDirection ); 
   
   vec3  fvReflection     = normalize( ( ( 2.0 * fvNormal ) * fNDotL ) - fvLightDirection ); 
   vec3  fvViewDirection  = normalize( ViewDirection );
   float fRDotV           = max( 0.0, dot( fvReflection, fvViewDirection ) );
   
   vec4  fvBaseColor      = texture2D( baseMap, Texcoord );
   
   vec4  fvTotalAmbient   = fvAmbient * fvBaseColor; 
   vec4  fvTotalDiffuse   = fvDiffuse * fNDotL * fvBaseColor; 
   vec4  fvTotalSpecular  = fvSpecular * ( pow( fRDotV, fSpecularPower ) );
  
   gl_FragColor = ( fvTotalAmbient + fvTotalDiffuse + fvTotalSpecular );
       
}
fig.4 Fragment Program

これだけでも shader プログラムの取り掛かりとしては非常に敷居が低くなっています。

RenderMonkey 以外にも shader プログラムのコードを自動生成してくるソフトとし ShaderGen があります[fig.5]。このソフトは OpenGL の固定機能を OpenGL Shading Language に置き換えてくれるもので、従来の OpenGL の固定機能を知っている人が shader プログラムを始める場合には有用なソフトだと思います。

ShaderGen-3.0.jpg
fig.5 ShaderGen 3.0

さてここまでは前フリで、今回は基本となるテクスチャの扱いを簡単にまとめます。ワークスペースは新規に Screen-Aligned Quad を選択します[fig.6]。

Screen-AlignedQuad.jpg
fig.6 Screen-Aligned Quad

ここでテクスチャを base.tga から ati.tga に変更します。これはテクスチャの向きを確認するためです。base.tga から ati.tga に変更するとテクスチャの向きが上下が逆になっていることがわかります。これを直す方法はいろいろとありますが、ここでは Vertex Program を変更します。

varying vec2  texCoord;

void main(void)
{
   gl_Position = vec4( gl_Vertex.xy, 0.0, 1.0 );
   gl_Position = sign( gl_Position );
    
   // Texture coordinate for screen aligned (in correct range):
//   texCoord = (vec2( gl_Position.x, - gl_Position.y ) + vec2( 1.0 ) ) / vec2( 2.0 );
   texCoord = (vec2( gl_Position.x, gl_Position.y ) + vec2( 1.0 ) ) / vec2( 2.0 );
}
fig.7 Vertex Program の変更

また、これだけでは何なので Fragment Program も変更してみます。

uniform sampler2D Texture0;

varying vec2 texCoord;

void main(void)
{
//    gl_FragColor = texture2D( Texture0, texCoord );
    gl_FragColor = texture2D( Texture0, texCoord*2.0 );
}
fig.8 Fragment Program の変更

ここまでの変更で fig.9 の状態になっているはずです。

Screen-AlignedQuad_01.jpg
fig.9 texture, Vertex Program, Fragment Program 変更

さてここからが本題で、今回注目するのは Texture Parameter です。これは Texture0 をダブルクリックかマウス右クリックで Edit を選択します[fig.10]。

Screen-AlignedQuad_02.jpg
fig.10 Texture State Editor の選択

ここでは glTexParam{i|f|v}, glTexEnv{i|f|v} に関連するパラメータの設定を行うことができます。デフォルトでは GL_TextureMinify = GL_LINEAR_MIPMAP_LINEAR, GL_TextureMagnify = GL_LINEAR が設定されています[fig.11]。

Screen-AlignedQuad_03.jpg
fig.11 Texture State Editor デフォルト値

さてここで Fragment Program に戻り、以下の様に編集してみます[fig.12]。

uniform sampler2D Texture0;

varying vec2 texCoord;

void main(void)
{
//    gl_FragColor = texture2D( Texture0, texCoord );
    gl_FragColor = texture2D( Texture0, fract(texCoord*2.0) );
}
fig.12 Fragment Program の変更 2

この変更を行うと表示されているテクスチャの中央にスジが入るのが確認できると思います[fig.13]。

Screen-AlignedQuad_04.jpg
fig.13 スジが現れた状態

最初に RenderMonkey を使ったとき、何故テクスチャ座標の算出に fract, floor などを使うとこのスジが現れるのかがわかりませんでした。そのときにはまだ Texture State Editor の出し方がわからなかったため RenderMonkey のバグかとも思いましたが、実際にはこれは GL_TextureMinify が影響しています。というわけで Texture State Editor に戻り GL_TextureMinify を GL_LINEAR に変更します[fig.14]。

Screen-AlignedQuad_05.jpg
fig.14 GL_TextureMinify の変更

この変更により GL_LINEAR_MIPMAP_LINEAR の効果は得られなくなりますがテスクチャのスジは消せます。MIPMAP 画像が見れないので RenderMonkey がどんな MIPMAP を生成しているか謎ですが、うまく MIPMAP のレベル調整ができれば実際のプログラム上では問題はないでしょう。

私はこの問題にはまり「RenderMonkey の fract, floor ってバグってる?」と思いいろいろと検索をしてしました。結果的に web 上では情報が見つからなかったのですが、この問題のおかげでちょっとは RenderMonkey に慣れることができたな、と思います。

また、これ以外のパラメータも変更してみて下さい。特に fract を外して GL_TextureWrap{S|T|R} を変更すると普通に REPEAT/CLAMP 系の動作を確認することができます。


投稿者 napier : 2006年02月12日 19:08


トラックバック

このエントリーのトラックバックURL:
http://will.squares.net/mt/mt-modified-tb.cgi/283