メディア処理演習 CG:
課題 3:Excel によるコンピュータグラフィクス 3
(1)座標値
6. 幾何データの表示
複数の頂点座標を指定する場合,x, y, z 値を頂点数だけ
幾何データを構成する頂点ごとに座標変換を行う頂
並べて定義します.このとき,並べられた順に頂点の識
点処理および,変換された頂点をもとにして画面上の画
別番号をつけます.
措置を計算し結果を表示するピクセル処理について前
(2)接続情報
回説明しました.今回はこれらの処理技術を統合して
ポリゴンデータを構成する三角形パッチごとに,その 3
Excel を使って幾何データを表示するシステムを構築し
頂点の識別番号を順に指定します.隣接する三角形パッ
ましょう.
チと識別番号の順序を一致させます.
(3)色
6.1 幾何データの表現
頂点または三角形パッチごとに色 r, g, b を指定します.
3次元 CG において,描画の対象となるデータは点・
頂点に色を指定した場合,三角形内部はその頂点から補
線分・面で表されることが多く,一般に「幾何データ」
間されて色が割り当てられます.
と呼ばれます.面データは,ポリゴンデータとも呼ばれ,
6.1.2 四面体データの記述
複数の線分からなる閉領域として表現されます.特に,
4 つの三角形からなる四面体データの記述例を示し
三角形ポリゴン(三角形パッチ)は立体を構成する基本
ます.
要素として利用され,複雑な異形上の物体を三角形パッ
(1)データ用ワークシートを作成する
チを使って近似形状を描画することが多い.本演習では,
①「3.3.xls」を開く.
複数の三角形パッチで表現されるポリゴンデータを対
②ワークシートを追加する.
象として描画を行います.
③ワークシート名を「Data」とする.
6.1.1 ポリゴンデータ
(2)頂点の座標値を指定する
ポリゴンデータは,面を構成する頂点の座標値および
①セル B2 に「Vertex」と入力する
その接続情報,色からなります.
②セル B3 に「ID」と入力し,セル B4, B5, B6, B7 にそ
座標値:
接続情報:
れぞれ,頂点の識別番号「1」,「2」,「3」,「4」を
1 (x1, y1, z1)
①(1, 2, 3)
入力する.
2 (x2, y2, z2)
②(3, 2, 4)
③セル C2 に「Object coordinate」と入力し,セル C3, D3,
3 (x3, y3, z3)
E3, F3 にそれぞれ,「x」,「y」,「z」,「w」を入
4 (x4, y4, z4)
力する.
1:頂点の識別番号
色(頂点ごと) 色(面ごと)
④セル範囲 C4:F7 に下表を参考に4つの頂点座標を入
①:三角形パッチの
1 (r1, g1, b1)
①(r1, g1, b1)
2 (r2, g2, b2)
②(r2, g2, b2)
識別番号
力した後,名前「Vertices」をつける.
3 (r3, g3, b3)
4 (r4, g4, b4)
図 6.1 ポリゴンデータ 1
C
D
E
F
③セル範囲 C16:E19 に対して下表を参考にして 4 つの三
4
0
0
2.5
1
角形パッチの色を入力したあと,名前「Color」をつけ
5
0
2.5
-2.5
1
る.
6
-2.5
-2.5
-2.5
1
7
2.5
-2.5
-2.5
1
C
D
E
16
255
0
0
⑤下図を参考にして,外枠太罫線およびセルの色づけを
17
0
255
0
行う.
18
0
0
255
19
255
0
255
④下図を参考にして,外枠太罫線およびセルの色づけを
行う.
(3)接続情報を指定する
①セル B8 に「Connection」と入力する
②セル B9 に「ID」と入力し,セル B10, B11, B12, B13
6.2 フレームバッファ処理
にそれぞれ三角形パッチの識別番号「1」,「2」,「3」,
「4」を入力する
幾何データを効率よく表示するためのダブルバッフ
③セル範囲 C10:E13 に対して下表を参考にして 4 つの三
ァリングおよび陰線消去や陰面消去を効率よく実行す
角形パッチの接続情報を入力した後,名前「Connections」
るための Z バッファアルゴリズムについて説明し,VBA
をつける.
を利用してそれらの機能を実装します.
6.2.1 モジュール変換
C
D
E
10
1
2
3
ダブルバッファリングおよび Z バッファアルゴリズ
11
1
3
4
ムを実装するために,カラーバッファ用ワークシートを
12
1
4
2
2 つ,デプスバッファ用ワークシートを1つ利用します.
13
2
4
3
これらのシートを効率よく利用するために,デプスバッ
④下図を参考にして頂点の接続情報に対して外枠太罫
ファ用ワークシート名(DepthBuffer),カラーバッファ
線およびセルの色づけを行う.
用ワークシート名(ColorBuffer)および 2 つのカラーバ
ッファを識別するための番号(BackBufferID)をモジュ
ールレベルの変数(モジュール変数)として宣言します.
'' デプスバッファ用ワークシート名
Public Const DepthBufferSheetname = "DepthBuffer"
'' カラーバッファ用ワークシート名
Public Const ColorBufferSheetname = "ColorBuffer"
'' カラーバッファ識別用番号(1 or 2)
Public BackBufferID
(4)頂点または三角形パッチの色を指定する
①セル B14 に「Color」と入力する.
ここで, public とは,プロジェクト内で自由に参照
②セル B15 に「ID」と入力し,セル B16, B17, B18, B19
することができる変数であることを表します.
に,それぞれ,頂点または三角形パッチの識別番号「1」,
「2」,「3」,「4」を入力する.
2
' (x,y)で指定されたセルを指定された色(r,g,b)で塗
りつぶす。
Worksheets(color_buffer).Cells(y, x).Interior.color =
RGB(r, G, b)
End Sub
6.2.2 ダブルバッファリング
カラーバッファを 2 つ使い,それらを切り替えて描画
するダブルバッファリングを行うことで効率よく連続
的な映像を描画することができます.本演習ではダブル
バッファリングを実現するために表面バッファと裏面
6.2.3 Z バッファアルゴリズム
バッファの入れ替えを行う SwapBuffers 関数を以下の様
Z バッファアルゴリズムでは,描画の対象となるポリ
に作成します.ただし,CStr 関数は,引数で指定され
ゴンデータの奥行き値(デプス値)を格納するためのデ
る数値を文字に変換する関数であり,例えば,
プスバッファを用意し,描画の際に格納されたデプス値
BackBufferID が 2 の場合,「color_buffer = ColorBuffer
と描画対象とするデータのデプス値を比較することに
Sheetname + CStr(BackBufferID) 」とすることで,
よって描画するかどうかの判断を行います.
color_buffer に「ColorBuffer2」という文字列が代入され
Z バッファアルゴリズムに対応した線分および三角
ます.
形の描画を行うためには,線分上および三角形内部での
'' フレームバッファの入れ替え(ダブルバッファリン
グ)
Sub SwapBuffers()
' BackBufferID で指定されたカラーバッファを選択す
る。
color_buffer = ColorBufferSheetname +
CStr(BackBufferID)
Worksheets(color_buffer).Select
デプスの値が必要となりますが,色の補間と同様に頂点
デプスの値から補完することによって,それらを計算す
ることが可能です.点の描画関数 DrawPixelWithDepth
は以下の様になります.
'' 点の描画(デプス値付き)
Sub DrawPixelWithDepth(x, y, depth, r, G, b)
' 現在選択されているカラーバッファ名
(color_buffer)と
' デプスバッファ名(depth_buffer)を取得する。
color_buffer = ColorBufferSheetname +
CStr(BackBufferID)
depth_buffer = DepthBufferSheetname
' もう一方のカラーバッファを初期化する。
BackBufferID = 3 - BackBufferID
color_buffer = ColorBufferSheetname +
CStr(BackBufferID)
ClearFrameBuffer color_buffer
' デプスバッファを初期化する。
depth_buffer = DepthBufferSheetname
ClearDepthBuffer depth_buffer
End Sub
' デプスバッファから対応するデプス値
(depth_current)を取得する。
depth_current = Worksheets(depth_buffer).Cells(y,
x).Value
関数を以下の様にダブルバッファリングに対応した関
' 奥行き比較を行う。
If depth < depth_current Then
Worksheets(color_buffer).Cells(y, x).Interior.color
= RGB(r, G, b)
Worksheets(depth_buffer).Cells(y, x).Value =
depth
End If
End Sub
数に書き換えます.
また,線分の描画関数 DrawLineWithDepth, および,三
ダブルバッファ機能を有効にした場合,BackBufferID
で識別されるカラーバッファに対して選択的に画素値
を書き込む必要があります.そのため,前回の演習では
書き込むフレームバッファを固定としていた DrawPixel
角形の描画関数 DrawTriangleWithDepth,デプス値を考
'' 点の描画
Sub DrawPixel(x, y, r, G, b)
' 現在選択されているカラーバッファ名
(color_buffer)を取得する。
color_buffer = ColorBufferSheetname +
CStr(BackBufferID)
慮したスキャン変換処理を行う関数 ScanlineWithDepth
はエクセルファイル「6.1.xls」に記載しています.
3
6.3 シェーディング処理
します.拡散反射による反射強度 Idiffuse は法線ベクトル
3 次元空間中に定義される幾何データに対して,光源
N と光源ベクトル L が与えられ,それらがともに単位
を設定し,データの形状に応じて適切に陰影を与えるシ
ベクトルであれば N と L の内積を計算することによ
ェーディングを行うことによって,立体感のある描画を
って以下の様に計算することができます.
行うことができます(図 6.1).ここでは,VBA を利用
Idiffuse = kd Cd (N・L)
したシェーディング処理の実装について説明します.
ただし,Cd は拡散光の強度を表します.kd は 0∼1 まで
(6.2)
の値で表される拡散反射の強度調整を行うパラメタで
す.以下に拡散反射による反射強度 Idiffuse を計算する
DiffuseTerm を示します.
'' 拡散反射による反射強度の計算
Function DiffuseTerm(kd, Cd, N, L)
' N と L の内積 NL を計算する。
NL = N(1) * L(1) + N(2) * L(2) + N(3) * L(3)
(a)シェーディングあり (b)シェーディングなし ' NL が負の値となるとき、つまりθがπ/2(90 度)
以上になるときは裏面を
' 照らすことになるため、反射強度を 0 とするよう
に調整する。
NL = WorksheetFunction.Max(NL, 0)
図 6.1 シェーディング処理 6.3.1 光の反射
シェーディング処理を行うためには,物体表面でおこ
' 反射強度を計算する。
DiffuseTerm = kd * Cd * NL
End Function
る光の反射を計算する必要があります.CG では通常,
光の反射は環境光による反射,拡散反射,鏡面反射の3
つの成分から構成されます.
環境光による反射
鏡面反射
環境光は,間接光とも呼ばれ,
な面である場合に,一方向から入射した光が別の一方向
空間全体を照らす効果を持ち,物体や光源の位置・向き
に反射します.しかし,実際には一方向のみに反射する
に関係なく,物体表面を均等に照明します.この環境光
ような完全な鏡面反射であることは少なく,多くの物体
による物体表明での反射光の強度 Iambient は以下の様に
では反射は不完全です.そのため,物体表面に光が強く
して計算することができます.
Iambient = kaCa
鏡面反射は物体表面が鏡のように滑らか
反射する部分が発生し,光沢感のある反射になります.
(6.1)
ただし,Ca は 0∼1 までの値で表される環境光の強度
(色)を表します.ka は 0∼1 までの値で表される反射
強度の調整を行うパラメタであり,この値が 1 に近いほ
ど物体表面が明るく描画されます.以下は環境光による
反射強度 Iambient を計算する関数 AmbientTerm を示します.
'' 環境光による反射強度の計算
Function AmbientTerm(ka, Ca)
' 反射強度を計算する。
AmbientTerm = ka * Ca
End Function
拡散反射
図 6.2 鏡面反射 拡散反射は乱反射とも呼ばれ,物体表面の
微少な凹凸や表面下散乱の影響によって全方向に散乱
4
鏡面反射による反射強度 Ispecular は正反射ベクトル R と
算するための代表的なモデルである「ランバート反射モ
視線ベクトル V を用いて以下のように計算することが
デル」と「フォン反射モデル」について説明します(図
できます.
6.3).
Ispecular = ks Cs (R・V)s
(6.3)
ただし,Cs は鏡面光の強度を表します.s は光沢度を表
すパラメタであり,値が大きくなるにつれて鋭く集中し
たハイライト効果になります.また,ks は 0∼1 までの
値で表される拡散反射の強度調整を行うパラメタです.
また,正反射ベクトル R は,物体表面上の法線ベクト
(a)ランバート反射モデル (b)フォン反射モデル ル N と光源ベクトル L を用いて
R = 2(R・V)N - L
図 6.3 ランバート反射モデルとフォン反射モデル (6.4)
と表すことができます.以下に,鏡面反射による反射強
度 Ispecular を計算する関数 SpecularTerm を示します.
ランバート反射モデル
ランバート反射モデルは鏡
'' 鏡面反射による反射強度の計算
Function SpecularTerm(ks, Cs, s, N, L, V)
' N と L の内積 NL を計算する。
NL = N(1) * L(1) + N(2) * L(2) + N(3) * L(3)
面反射成分を考慮せず環境光による反射と拡散反射の
みから反射強度を計算することで,光沢感をなくした反
射モデルです.このモデルに基づく反射強度 Ilambert は
' NL が負の値となるとき、
' つまりθがπ/2(90 度)以上になるときは裏面を
' 照らすことになるため、
' 反射強度を 0 とするように調整する。
NL = WorksheetFunction.Max(NL, 0)
' 正反射ベクトル R を計算する。
Dim r(3)
r(1) = 2 * NL * N(1) - L(1)
r(2) = 2 * NL * N(2) - L(2)
r(3) = 2 * NL * N(3) - L(3)
Ilambert = Iambient + Idiffuse
(6.5)
で求めることができます.また,物体の色を Cm とした
場合,反射光 Clambert は以下の様にして計算することが
できます.ただし,物体色を RGB 成分で表現する場合
は R, G, B それぞれに対して以下の計算式を行う必要が
あります.
Clambert = Cm Ilambert
' R と V の内積 RV を計算する。
RV = r(1) * V(1) + r(2) * V(2) + r(3) * V(3)
(6.6)
以下に,ランバート反射モデルに基づいて反射光を計算
する関数 LambertReflection を示します.
' RV が負値にならないように調整する。
RV = WorksheetFunction.Max(RV, 0)
'' ランバート反射モデルによる反射光の計算
Function LambertReflection(Cm, ka, Ca, kd, Cd, N, L)
' 環境光による反射強度を計算する。
Iambient = AmbientTerm(ka, Ca)
' RV の n 乗を計算する。
RVn = WorksheetFunction.Power(RV, s)
' 反射強度を計算する。
SpecularTerm = ks * Cs * RVn
End Function
' 拡散反射による反射強度を計算する。
Idiffuse = DiffuseTerm(kd, Cd, N, L)
' ランバート反射モデルによる反射強度を計算する。
Ilambert = Iambient + Idiffuse
6.3.2 反射モデル
' 反射光を計算する。
LambertReflection = Cm * Ilambert
End Function
物体表面で起こる光の反射は,環境光による反射,拡
散反射,鏡面反射の成分を合成するこにより表現され,
その強度(輝度)を計算することによって物体の色や明
るさを決定することができます.ここでは,輝度値を計
5
フォン反射モデル
Sub Main_DrawTetrahedron()
フォン反射モデルは,環境光によ
る反射光および拡散反射光に加え,鏡面反射も考慮して
End Sub
反射強度を計算する反射モデルであり,光沢感のある表
②メイン関数内で,カラーバッファおよびデプスバッフ
現が可能です.物体色を Cm, 白色成分を Cw とした場合,
ァの作成・初期化を行う.
' カラーバッファの識別番号を 2 にする。
BackBufferID = 2
反射光 Cphong は以下の様にして計算することができます.
Cphong = Cm Ilambert + Cw Ispecular
(6.7)
' カラーバッファおよびデプスバッファを生成・初
期化する。
color_buffer1 = ColorBufferSheetname + CStr(1)
color_buffer2 = ColorBufferSheetname + CStr(2)
depth_buffer = DepthBufferSheetname
以下にフォン反射モデルに基づき反射光を計算する関
数 PhongReflection を示します.
'' フォン反射モデルによる反射光の計算
Function PhongReflection(Cm, Cw, ka, Ca, kd, Cd, ks, Cs, s,
N, L, V)
' ランバート反射モデルによる反射光を計算する。
Lambert = LambertReflection(Cm, ka, Ca, kd, Cd, N, L)
CreateFrameBuffer color_buffer1, 1, 11
CreateFrameBuffer color_buffer2, 1, 11
CreateFrameBuffer depth_buffer, 1, 11
' 鏡面反射による反射強度を計算する。
Ispecular = SpecularTerm(ks, Cs, s, N, L)
ClearFrameBuffer color_buffer1
ClearFrameBuffer color_buffer2
ClearDepthBuffer depth_buffer
' 反射光を計算する。
PhongReflection = Lambert + Cw * Ispecular
End Function
(3)入力パラメタの設定
①幾何変換ワークシート内の回転角をメイン関数から
6.5 Excel による幾何データの表示
設定する.ここでは,0 ∼360 まで 10 ごとに変換させ
本日の演習では,まず,オブジェクトの回転などを行
て,四面体データの回転アニメーションを行う.
うための入力パラメタを VBA プログラムから指定して,
ワークシート上での座標変換の計算に利用します.次に,
ワークシート上で,計算された座標変換行列を使って,
ポリゴンデータを構成する頂点をオブジェクト座標か
らウィンドウ座標へ変換します.最後に VBA プログラ
ムを利用して,ウィンドウ座標系に変換された頂点から
' 回転アニメーション表示を行う。
For deg = 0 To 360 Step 10
Worksheets("Transformation").Range("C5").Value =
deg
Worksheets("Transformation").Range("D5").Value =
deg
Worksheets("Transformation").Range("E5").Value =
deg
構成される三角形パッチを描画し,その結果をフレーム
※
バッファに表示します.
// --- ここの内容は(5)ピクセル処理
で記載します
Next
6.5.1 実装
(1) ワークシートの準備
(4)頂点処理
①ワークシート名「ColorBuffer」を「ColorBuffer1」と
①データ記述用ワークシート「Data」で頂点変換を行う.
変更する.
②ワークシートを2つ追加し,それぞれワークシート名
まず,セル G2 に「Camera coordinate」と入力し,G3, H3,
を「ColorBuffer2」,「DepthBuffer」とする.
I3, J3 にそれぞれ「x」,「y」,「z」,「w」と入力す
る.
(2)メイン関数の追加
②モデルビュー変換行列「M_modelview」を使ってオブ
①標準モジュールに,四面体データの描画を行うメイン
ジェクト座標で表される「Vertices」をカメラ座標に経
関数「Main_DrawTetrahedron」を追加する.
何する.セル範囲 G4:J7 を選択肢,数式バーに
6
' 1 番目の頂点の座標値とデプス値を取得する。
index1 = Triangle.Cells(1, 1)
x1 = Round(Range("ProjectedVertices").Cells(index1, 1))
y1 = Round(Range("ProjectedVertices").Cells(index1, 2))
d1 = Range("ProjectedVertices").Cells(index1, 3)
' 2 番目の頂点の座標値とデプス値を取得する。
index2 = Triangle.Cells(1, 2)
x2 = Round(Range("ProjectedVertices").Cells(index2, 1))
y2 = Round(Range("ProjectedVertices").Cells(index2, 2))
d2 = Range("ProjectedVertices").Cells(index2, 3)
' 3 番目の頂点の座標値とデプス値を取得する。
index3 = Triangle.Cells(1, 3)
x3 = Round(Range("ProjectedVertices").Cells(index3, 1))
y3 = Round(Range("ProjectedVertices").Cells(index3, 2))
d3 = Range("ProjectedVertices").Cells(index3, 3)
「 =MMULT(Vertices,TRANSPOSE(M_modelview)) 」と
入力した後,Ctl キーと Shift キーを押しながら Enter キ
ーを押す.そして,同範囲内に名前「P_cam」をつける.
③セル K2 に「Clip coordinate」 と入力し,セル K3, L3,
M3, N3 にそれぞれ「x」,「y」,「z」,「w」と入力
する.
④投影変換行列「M_proj」を使ってカメラ座標で表され
る「P_cam」をクリップ座標に変換する.セル範囲 G4:J7
を選択し,数式バーに
「=MMULT(P_cam,TRANSPOSE(M_proj))」と入力した
' 三角形パッチの色を取得する。
r = Range("Colors").Cells(index0, 1)
G = Range("Colors").Cells(index0, 2)
b = Range("Colors").Cells(index0, 3)
後,Ctl キーと Shift キーを押しながら Enter キーを押す.
そして,同範囲に名前「P_clip」をつける.
⑤セル O2 に「Window coodinate」と入力し,セル O3, P3,
' 三角形パッチを描画する。
DrawTriangleWithDepth x1, y1, d1, x2, y2, d2, x3, y3, d3,
r, G, b
Q3, R3 にそれぞれ「x」,「y」,「z」,「w」と入力
する.
' 稜線を描画する。
d = 0.0001
DrawLineWithDepth x1, y1, d1 - d, x2, y2, d2 - d, 0, 0, 0
DrawLineWithDepth x2, y2, d2 - d, x3, y3, d3 - d, 0, 0, 0
DrawLineWithDepth x3, y3, d3 - d, x1, y1, d1 - d, 0, 0, 0
⑥ビューポート変換行列「M_viewport」を使ってクリッ
プ座標で表される「P_clip」をウィンドウ座標に変換す
る.セル範囲 O3:R7 を選択肢,数式バーに
「=MMULT(P_clip,TRANSPOSE(M_viewport))」と入力
index0 = index0 + 1
Next
した後,Ctl キーと Shift キーを押しながら Enter キーを
押す.そして,同範囲に名前「ProjectedVertices」をつ
' 描画用カラーバッファを入れ替える。
SwapBuffers
ける.
⑦以下を参考に,外枠太罫線およびセルの色つけを行う.
(5)ピクセル処理
( (3) の図中※には,上図が入ります)
参考資料
①接続情報「Connections」をもとにしてフレームバッフ
Excel で学ぶコンピュータグラフィックス技術入門
ァ上に三角形パッチを描画します,
坂本尚久, 小山田耕二, コロナ社 (2011 年)
②メイン関数内で下図に示すように三角形パッチごと
にデプス値を考慮して描画する.このとき,「Colors」
で指定される色を三角形パッチごとに割り当てる.また,
四面体の稜線を三角形パッチより少し手前に描画する.
③ダブルバッファリングを有効にして描画する
' 三角形パッチごとに描画する。
index0 = 1 ' 色データ取得用インデックス
For Each Triangle In Range("Connections").Rows
7
© Copyright 2026 Paperzz