N88-BASICでレイトレーシング (4回目)
2021/6/4(金)
N88-BASICでレイトレーシング (4回目)
(by ULproject for N88-BASIC, NL-BASIC)
(NL-BASICはAlt+6で高速化します)
今回は陰影(濃淡)を付けます
濃淡は表面の色を表すdiffuse(拡散反射係数)
を使用します
RGB各0~1で指定し、0~1の実数で濃淡を表現
します
N88-BASICの8色モードで濃淡を表すために
RGBの各明るさに対応して乱数で点を描く量の
増減で表現しています
前回のx0,y0,ix,iy,izの値を使用して
色c、濃淡b、大きさiz×izの点を
(ix × iz + x0 , iy × iz + y0)
のPC画面座標に描くサブルーチン
*DRAWSを作ります。
IF CL(3) < 0 THEN RETURN
Y1 = Y0 + IY * IZ: Y2 = Y1 + IZ - 1
X1 = X0 + IX * IZ: X2 = X1 + IZ - 1
FOR PY=Y1 TO Y2
FOR PX=X1 TO X2
C = 0
IF RND(1) < CL(0) THEN C = C + 2
IF RND(1) < CL(1) THEN C = C + 4
IF RND(1) < CL(2) THEN C = C + 1
PSET(PX, PY), C
NEXT
NEXT
RETURN
CL(0)=1の時100%、CL(0)=0の時0%にしたいので
0~1未満の乱数 RND(1) < CL(0) のとき
赤(R:2)を有効にします
RND(1) <= CL(0)とするとCL(0)=0の時も点が
描かれてしまいます
CL(0~2)でRGB(色番号2,4,1)を表します
光が球面に垂直に当たった場所は明る
く、水平方向から当たった場所は暗く
見え、その光は乱反射(四方八方に拡散)
しますので、球をどの方向から見ても
光の量は変わりません
つまり、視線Eの方向は無関係ということです
この光を拡散光(diffuse)と言い次式で表わします
b = L・N
見ている球の中心が原点になるように
変換した座標系で考えると、
P:視線が見ている球表面上の点
N:点Pでの球の法線ベクトル(N = P/|P|)
球の表面の接面に垂直な単位ベクトル
L:点Pから光源を見る方向
図2
bは図2のLの矢印の先からNに
下した垂線との交点と点Pの距離で、
θが0°で最大の1、90°で0となり、
この値は、球表面に当たる単位面積
当たりの光の量に比例します
光が当たっていない場所の明るさを
環境光で指定します
DATA文に追加してAMに読込ませます
0番の球を減衰しない点光源にし、視線と球の
交点の色cと明るさbを求めるサブルーチン
*SHADE
を作ります
siが交点のある球の番号ですので、
GOSUB *DISTANCE
IF T < 0 THEN CL(3) = -1: RETURN
CL(0) = SD(SI,0): CL(1) = SD(SI,1): CL(2) = SD(SI,2): CL(3) = 1
IF SI = 0 THEN RETURN ' light
si=0の球は光源にしたので濃淡なしにします
V0(0) = V(0) - SP(SI,0)
V0(1) = V(1) - SP(SI,1)
V0(2) = V(2) - SP(SI,2)
P(0) = V0(0) + E(0) * T
P(1) = V0(1) + E(1) * T
P(2) = V0(2) + E(2) * T
V0を球を原点にした時のVとして、
P = V0 + Etで、原点にある球上の
点の座標Pを求めます
B = SQR(P(0)*P(0) + P(1)*P(1) + P(2)*P(2)) ' P = V0+Et
IF B <> 0 THEN B = 1/B ELSE B = 0
N(0) = P(0) * B
N(1) = P(1) * B
N(2) = P(2) * B ' N = P/|P|
N = P/|P| を|P|=0のときエラーに
ならないように工夫して求めます
P(0) = SP(0,0) - (P(0) + SP(SI,0))
P(1) = SP(0,1) - (P(1) + SP(SI,1))
P(2) = SP(0,2) - (P(2) + SP(SI,2))
B = SQR(P(0)*P(0) + P(1)*P(1) + P(2)*P(2))
IF B <> 0 THEN B = 1/B ELSE B = 0
P(0) = P(0) * B
P(1) = P(1) * B
P(2) = P(2) * B ' P = L(光源方向)
点Pから光源方向の単位ベクトルL
を求めます。Pはもう使わないので
Lの値はPに入れています
B = P(0)*N(0) + P(1)*N(1) + P(2)*N(2) ' b = L・N
IF B < AM THEN B = AM ' ambient
b = L・Nを求めます
bが環境光am未満ならbを環境光
にします
CL(0) = CL(0) * B: CL(1) = CL(1) * B: CL(2) = CL(2) * B
で明るさを反映させます
CL(0~2)に表示色(RGB)が入ります
CL(3) < 0の時は交点なしです
NL-BASICとblg~.zip(ray004.bas)は
以下のリンクからダウンロードできます
Readme.txtを読んで遊んで下さい
次回