トックのCG部屋-トップ別室へ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  1. --/--/--(--) --:--:--|
  2. スポンサー広告

そろそろシェーディングの部分を

作ろうかと思うけどその前にプログラムの構造を少し考えようと
んでまぁ肌、髪の毛、その他でいろいろとシェーディングの仕方を変えようとしたときに
シェーディング用のインターフェイスを作ってそれを実装したクラスを作れば管理が楽じゃないかと
まぁ友達が同じようなことやってたけど考え方の元は
先生にCでのメモリ管理について聞きにいったときにちらっと話してた
Javaでも関数ポインタと同じようなことができるんだよ的な話
これ知らなかった時期は毎回if文やswitch文で分けてたよ…
もっとも今回のプログラムはそう頻繁に呼ぶわけじゃないから真価は発揮しないと思うけどね
今回は少し実際のコード的なところも触れていこうかと
理由はないよ!本当だよ!
かなり長いから追記で

それと注意
・クラス名や変数名はかなり適当(基本略しまくり,スペルミス上等)だけど突っ込まない
・実際に使う状態で動かしてないからちゃんと思った通りになってるかはわからない(コンパイラには通るレベル
・Javaの解説の間違いは許せないレベルじゃない限りスルーしてくれるとうれしい

んでまぁ具体的に何を書けばいいのかというと
・シェーディング用のインターフェイス
・それを実装したクラス(複数)
・それらを名前で管理できるようにするためのEnum型クラス
・選択等をコントロールするためのクラス
あとどうでもいいけどサブパッケージでまとめたりするといいかもしれない

シェーダの選択部分
public class ShaderControl {
public static ShaderPri getShader(String name){
ShaderName sn=ShaderName.COMMON;
try{
sn=ShaderName.valueOf(name);
}catch(IllegalArgumentException e){}

switch(sn){
case COMMON:
return new ComSh();
case HAIR:
return new HairSh();
case SKIN:
return new HairSh();
default:
return new ComSh();
}
}
}

public enum ShaderName {COMMON,SKIN,HAIR}
こんな感じでString型で名前をもらって対応するシェーダを返す
わざわざ新しくクラスを作る行数じゃないかもしれないけど
もしかしたら後でまた追加するかもしれないしね
ShaderPriがインターフェイスで返してるのがそれぞれ実装したクラス(Priってのはprimitivの略のつもり)
Enum型のを一緒に書いたけどファイル的には別
例外catchとか正直やらない方がいいんだろうけどチェック用のメソッド書くの面倒だからいいや
はじめからShaderNameでもらえばいいような気もするけど
結局ファイルからインポートするとどこかでString→ShaderNameにしなきゃいけないから
まぁそれをここでやっても別に問題はないかなと
番号じゃなくてわざわざEnum型で管理するのは後で拡張とか考えたときにいろいろと便利かなと思ったから

んで、肝心のShaderPriがどうなってるかというと
public interface ShaderPri {
public void shading(BufferedImage img,PixBuffSet bs,int[][] area,Object option);
}
たったこれだけ
だからシェーディング用のクラスは何か値を管理してるとかそんなんじゃなくて
本当にただそれぞれが持ってるメソッドへのポインタ代わりというわけ
それぞれの引数の意味は
左から描画先の画像、バッファ、描画する領域、オプション
まぁこの辺はレンダラの構造の問題だから
一番右のoptionってのはそれぞれのシェーダに個別に何か値を与えたいときに使う
シェーダ毎に必要な値の型も数も違うからこういう形になった
抽象クラスにしてコンストラクタで値を入れるにしても呼び出し元が上のあれだから
結局こういう形で入れることになるんじゃないかな
Object型は参照型の最上位のスーパークラスだからどんなオブジェクトも入れられる
voidポインタみたいなものと考えても大丈夫だと思う、きっと
リストや配列もオブジェクト型だからこんなこともできる
public class Test {
public static void main(String[] args){
//オブジェクト型の配列を作る
Object[] array=new Object[4];

//数値(多分オートボクシング)
array[0]=50;

//リスト
ArrayList<Color> al=new ArrayList<Color>();
al.add(Color.RED);
al.add(Color.BLACK);
array[1]=al;

//文字列
array[2]="てきすと";

//配列
array[3]=new double[]{65.4,36.4,5.1};

//Object型にキャストして引数にぶち込む
show((Object)array);
}

public static void show(Object o){
//もらったObjectを配列にキャスト
Object[] comp=(Object[])o;

//最初のはInteger。試しに5をかけて表示
int x=(Integer)comp[0]*5;
System.out.println(x);

//2番目は色のリスト。forで回して表示してみる
for(Color c:(ArrayList<Color>)comp[1]){
System.out.println(c);
}

//3番目は文字列、試しに最初の文字を切って表示
System.out.println(((String)comp[2]).substring(1));

//最後は配列。合計を出して表示させてみる
double sum=0.0;
for(double d:(double[])comp[3]){
sum+=d;
}
System.out.println(sum);
}
}
上の結果は
250
java.awt.Color[r=255,g=0,b=0]
java.awt.Color[r=0,g=0,b=0]
きすと
106.9
とまぁObject型のインスタンス一つでいくらでも値が渡せる
ただ当たり前だけど構造をちゃんと把握してキャストを正確にやらないと例外で止まる
別なシェーダ用のインスタンスを間違って入れるようなことがあるとアウトだね
インナークラスとか使った方がいいのかもしれないけど正直よくわからないからやめておく

とまぁぶっちゃけどうでもいいところに行数裂いたけどこんな感じ
多分上の構造を実際にどう使うのかは自分しかわかってないと思うけど
まぁいいんだよ
全部自己満足の世界だし

あと実際にShaderPriを実装したクラスだけど
例として三つクラスだけ作ったというだけで中身は全然書いてないよ
最初に書いたけど"作ろうかと思うけどその前に"の段階だから

さーて今回は珍しくコードまで載せて解説チックなことしたけど
やっぱりなれないことはするもんじゃないね
コード書きながらだったってこともあるけどここまでで大体2時間半
気が向いたらまた書くかもしれないけどデフォにはしたくないね
  1. 2009/12/09(水) 22:14:44|
  2. 自作レンダラ
  3. | トラックバック:0
  4. | コメント:0
<<球状レンダリング | ホーム | ライフゲーム>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://took.blog72.fc2.com/tb.php/642-c16363b5
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

トック

Author:トック

プロフィール(仮)

twitter:elgraiv_took
└ブログ更新情報

twitter:elgraiv_take
└無駄な日常つぶやき用

FC2カウンター

コンテンツ一覧

本棚

最近の記事

カテゴリー

月別アーカイブ

ブログ内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。