|
楼主 |
发表于 2006-9-21 19:16:11
|
显示全部楼层
主要变量:
Private backBuffer(640& * 480&) As Long '定义了存放图片数据的数组
Private Type Ray
Origin As Vector
Direction As Vector
End Type
Private primaryRay As Ray '定义了观察者的位置及观察方向
Private directionTable() As Vector '定义了射线方向(数组)
Public LightLoc As Vector '定义了灯光的位置
主要函数:
Sub Main '主函数
Rotate '球体位置旋转的函数
GenerateRayDirectionTable() '创建了开始的射线(数组)
TraceScene '场景跟踪,球体的遮挡关系也在此进行
IntersectSphere '射线与球体相交的长度计算
ShadeSphere '通过灯光与法线的夹角计算颜色,渲染
VectorDot '向量点积(计算向量间的夹角或长度)
VectorNormalize '单位化向量
待续
Public Sub TraceScene(ByRef Spheres() As Sphere, ByRef numSpheres As Integer, ByRef LightLoc As Vector)
'// 开始计算射线
Dim X As Long, Y As Long, Z As Long
Dim closestIntersectionDistance As Single
Dim closestIntersectedSphereNum As Integer
Dim currResult As TraceResult
Dim lngBuffer As Long
'//改变loop大小让FPS 显示更快
'//尤其是外部的 loop 影响最大!!!
'//缩方, 这会改变窗口
For Y = 150 To 350
For X = 250 To 400
'//单一的数值会快很多...
primaryRay.Direction = directionTable(X + (Y * 640))
closestIntersectionDistance = 1000000
closestIntersectedSphereNum = -1
'//循环所有的球体找出最靠近眼睛的球体号
For Z = 0 To numSpheres
currResult = IntersectSphere(primaryRay, Spheres(Z))
If currResult.Hit Then
If currResult.Distance < closestIntersectionDistance Then
closestIntersectionDistance = currResult.Distance
closestIntersectedSphereNum = Z
Exit For
End If
End If
Next Z
'//仅计算相交最靠近眼睛的球体
If (closestIntersectedSphereNum > -1) Then
'//bits数组赋值
Bits(X, Y) = ShadeSphere(Spheres(closestIntersectedSphereNum), primaryRay, closestIntersectionDistance, LightLoc)
Else
With Bits(X, Y)
.rgbRed = 0
.rgbBlue = 0
.rgbGreen = 0
End With
End If
Next X
Next Y
With frmMain.picRay
'//复制 bits 数据到图片
SetDIBits lngHDC, lngImageHandle, 0, BInfo.bmiHeader.biHeight, Bits(0, 0), BInfo, DIB_RGB_COLORS
'图片刷新
.Refresh
End With
End Sub
Public Function IntersectSphere(ByRef myRay As Ray, ByRef mySphere As Sphere) As TraceResult
Dim rayToSphereCenter As Vector '眼睛到球体中心的向量
Dim lengthRTSC2 As Single
Dim closestApproach As Single
Dim halfCord2 As Single
With IntersectSphere
.Hit = False
'// 眼睛到球体中心的向量并归到单一的原点
Call VectorSub(mySphere.Center, myRay.Origin, rayToSphereCenter)
'// lengthRTSC2 ='眼睛到球体中心距离的平方
lengthRTSC2 = VectorDot(rayToSphereCenter, rayToSphereCenter)
closestApproach = VectorDot(rayToSphereCenter, myRay.Direction)
'//如果是在背面,就返回失败(背面照不到光线)
If closestApproach < 0 Then Exit Function
'//halfCord2 = 球体中心到射线的垂直点与射线与球体交点的距离平方。
halfCord2 = (mySphere.Radius * mySphere.Radius) - lengthRTSC2 + (closestApproach * closestApproach) ' // sphere.radius 的平方可以在循环前先计算出来
|
-
|