シェーディングの設定
フラットシェーディング(Flat shading):面の頂点の色を同一として描画する(Lambert shading)
スムースシェーディング:滑らかな曲面の描画を行う.
グ-ローシェーディング(Gouraud shading):
頂点の法線ベクトルから面の頂点の色を求め,それを補間して面の色を描画する.
フォンシェーディング(Phong shading):
頂点の法線ベクトルを基に,面全体の法線ベクトルを求め,それにより面の色を決定する.OpenGLによるシェーディングの設定
フラットシェーディングの設定
glShadeModel GL_FLAT
スムースシェーディング(Gouraud Shading) の設定
glShadeModel GL_SMOOTH
面の向きは法線の向きにより決定される.また法線の向きは面の色に大きく影響する.
(点毎の法線も設定できる)法線の設定
glNormal3f x, y, zポリゴンモードの設定
glPolygonMode GL_FRONT_AND_BACK, GL_FILL '両面を塗りつぶす
glPolygonMode GL_FRONT, GL_FILL '表を塗りつぶす
glPolygonMode GL_BACK, GL_LINE '裏を線で描画
glPolygonMode GL_BACK, GL_POINTS '裏を点で描画
以下のようにglMaterialfv関数に配列で受け渡す必要がある.
例)
Dim MaterialDiffuse(4) As Single
Dim MaterialSpecular(4) As Single
MaterialDiffuse(0)=.4 '赤(R)
MaterialDiffuse(1)=.3 '緑(G)
MaterialDiffuse(2)=.3 '青(B)
MaterialDiffuse(3)=1 'アルファ(A)
MaterialSpecular(0)=.2 '赤(R)
MaterialSpecular(1)=.2 '緑(G)
MaterialSpecular(2)=.2 '青(B)
MaterialSpecular(3)=1 'アルファ(A)'配列の0番目を受け渡す(環境光及び拡散光)
glMaterialfv faceFront, mprAmbientAndDiffuse, MaterialDiffuse(0)'配列の0番目を受け渡す(反射光)
glMaterialfv faceFront, mprSpecular, MaterialSpecular(0)
Private Sub Form_Initialize()
Timer1.Interval = 10
Timer1.Enabled = False
Initialize
End Sub
Private Sub Command1_MouseDown(Index As Integer,
Button As Integer, Shift As Integer, x As Single, y As Single)
Dim add As Integer
If Button = vbLeftButton
Then add = 1 Else add = -1
Select Case Index
Case 0
addr.z = add * 10: addr.y = 0
Case 1
addr.z = 0: addr.y = add * 10
End Select
Timer1.Enabled = True
End Sub
Private Sub Command1_MouseUp(Index As Integer,
Button As Integer, Shift As Integer, x As Single, y As Single)
Timer1.Enabled = False
End Sub
Private Sub Picture1_Paint()
ViewSet 50, Picture1.ScaleWidth
/ Picture1.ScaleHeight, 1, 100
SetLight
Draw
End Sub
Private Function Initialize() As Boolean
Dim pfd As PIXELFORMATDESCRIPTOR
Dim r&
Picture1.ScaleMode = vbPixels
pfd.nSize = Len(pfd)
pfd.nVersion = 1
' pfd.dwFlags = PFD_SUPPORT_OPENGL
Or PFD_DRAW_TO_WINDOW
pfd.dwFlags = PFD_SUPPORT_OPENGL
Or PFD_DRAW_TO_WINDOW Or PFD_DOUBLEBUFFER Or PFD_TYPE_RGBA
pfd.iPixelType = PFD_TYPE_RGBA
pfd.cColorBits = 24
pfd.cDepthBits = 16
pfd.iLayerType = PFD_MAIN_PLANE
r = ChoosePixelFormat(Picture1.hDC,
pfd)
If r = 0 Then
MsgBox "ChoosePixelFormat failed"
Exit Function
End If
r = SetPixelFormat(Picture1.hDC,
r, pfd)
m_hGLRC = wglCreateContext(Picture1.hDC)
wglMakeCurrent Picture1.hDC,
m_hGLRC
glDepthFunc GL_LEQUAL
glEnable GL_DEPTH_TEST
'シェーディング設定
' glShadeModel GL_SMOOTH
'スムースシェーディングの場合
glShadeModel GL_FLAT
'フラットシェーディングの場合
Initialize = True
End Function
Private Sub Form_Unload(Cancel As Integer)
If m_hGLRC <> 0 Then
wglMakeCurrent 0, 0
wglDeleteContext m_hGLRC
End If
End Sub
Private Sub ViewSet(fov As Single, aspect As
Single, near As Single, far As Single)
glMatrixMode GL_PROJECTION
glLoadIdentity
gluPerspective fov, aspect,
near, far
glViewport 0, 0, Picture1.ScaleWidth,
Picture1.ScaleHeight
glMatrixMode GL_MODELVIEW
End Sub
Public Sub Draw()
Dim n As Integer
'色・ライト設定用配列の定義
Dim MaterialDiffuse(3)
As Single
Dim MaterialSpecular(3)
As Single
Dim positionLight0(3)
As Single
'法線格納用変数
Dim normal As pnt3d
'背景色の設定(RGBA)
glClearColor 0.2, 0.2,
0.3, 0
glClear GL_COLOR_BUFFER_BIT
Or GL_DEPTH_BUFFER_BIT
glColor3f 1#, 1#, 1#
glLoadIdentity
'ここにライトのポジション設定を与えると
'物体の移動・回転とは関係ない.
FillArray4f positionLight0(),
0!, 1!, 1!, 1!
glLightfv GL_LIGHT0,
GL_POSITION, positionLight0(0)
glRotatef 10, 1, 0, 0
'視点回転
glTranslatef 0#, -1#,
-5# '視点設定
glPushMatrix
' glRotatef
90, 1, 0, 0 '球の回転 X軸周りに90度
glRotatef r.y, 0, 1, 0
glRotatef r.z, 0, 0, 1
'ここにライトのポジション設定を与えると物体の回転とともに
'ライトも回転する.
'
FillArray4f positionLight0(), 0!, 1!, 1!, 1!
'
glLightfv GL_LIGHT0, GL_POSITION, positionLight0(0)
'物体の色の設定1
FillArray4f MaterialDiffuse(), 0.45, 0.3, 0.15, 1!
FillArray4f MaterialSpecular(), 0.2, 0.1, 0.1, 1!
glMaterialfv faceFront, mprAmbientAndDiffuse, MaterialDiffuse(0)
glMaterialfv faceFront, mprSpecular, MaterialSpecular(0)
glutSolidSphere 0.3, 20, 20
'
glutWireSphere .3, 20, 20
glPushMatrix
glTranslatef 1, 0, 0
'物体の色の設定2
FillArray4f MaterialDiffuse(), 0.2, 0.2, 0.2, 1!
FillArray4f MaterialSpecular(), 0.3, 0.4, 0.4, 1!
glMaterialfv faceFront, mprAmbientAndDiffuse, MaterialDiffuse(0)
glMaterialfv faceFront, mprSpecular, MaterialSpecular(0)
glutSolidSphere 0.5, 20, 20
glPopMatrix
'任意の物体の描画
FillArray4f MaterialDiffuse(), 0.5, 0.1, 0.1, 1!
FillArray4f MaterialSpecular(), 0.2, 0.1, 0.1, 1!
glMaterialfv faceFront, mprAmbientAndDiffuse, MaterialDiffuse(0)
glMaterialfv faceFront, mprSpecular, MaterialSpecular(0)
glPolygonMode GL_FRONT, GL_FILL
glPolygonMode GL_BACK, GL_LINE
glBegin GL_POLYGON
glNormal3f 0, 0, 1 '法線の指定
glVertex3f -1, -1, 2
glVertex3f 1, -1, 2
glVertex3f 0, 1, 2
glEnd
'配列を用いた面の描画
pnt(0).x = -2: pnt(0).y = -1: pnt(0).z = -4
pnt(1).x = -1: pnt(1).y = -1: pnt(1).z = -4
pnt(2).x = 2: pnt(2).y = 0: pnt(2).z = -4
pnt(3).x = 1: pnt(3).y = 1: pnt(3).z = -4
pnt(4).x = -2: pnt(4).y = 0: pnt(4).z = -4
'法線の計算,3点のみ与えればよい.
FillArray4f MaterialDiffuse(), 0.1, 0.1, 0.4, 1!
FillArray4f MaterialSpecular(), 0.1, 0.1, 0.4, 1!
glMaterialfv faceFront, mprAmbientAndDiffuse, MaterialDiffuse(0)
glMaterialfv faceFront, mprSpecular, MaterialSpecular(0)
normal = calcNormal(pnt(0), pnt(1), pnt(2))
glPolygonMode GL_FRONT_AND_BACK, GL_FILL
glBegin GL_POLYGON
glNormal3f normal.x, normal.y, normal.z
For n = 0 To 4
glVertex3f pnt(n).x, pnt(n).y, pnt(n).z
Next
glEnd
glPopMatrix
SwapBuffers Picture1.hDC
End Sub
'ポリゴンの法線を計算するプロシージャ
Private Function calcNormal(P1 As pnt3d,
P2 As pnt3d, P3 As pnt3d) As pnt3d
Dim n As pnt3d
Dim length As Single
n.x = (P2.y - P1.y) *
(P3.z - P2.z) - (P2.z - P1.z) * (P3.y - P2.y)
n.y = (P2.z - P1.z)
* (P3.x - P2.x) - (P2.x - P1.x) * (P3.z - P2.z)
n.z = (P2.x - P1.x)
* (P3.y - P2.y) - (P2.y - P1.y) * (P3.x - P2.x)
'長さの計算
length = Sqr(n.x * n.x
+ n.y * n.y + n.z * n.z)
'単位ベクトルにする
If length <> 0 Then
calcNormal.x = n.x / length
calcNormal.y = n.y / length
calcNormal.z = n.z / length
End If
End Function
Private Sub Timer1_Timer()
r.z = r.z + addr.z
r.y = r.y + addr.y
Draw
End Sub
Private Sub FillArray4f(a() As Single, f1 As
Single, f2 As Single, f3 As Single, f4 As Single)
a(0) = f1: a(1) = f2: a(2)
= f3: a(3) = f4
End Sub
Private Sub SetLight()
Dim ambientLight0(3) As
Single
Dim positionLight0(3) As
Single
'fillarray4fはユーザー定義
FillArray4f ambientLight0(),
0.3!, 0.3!, 0.3!, 1!
glLightfv GL_LIGHT0, GL_AMBIENT,
ambientLight0(0)
glEnable GL_LIGHTING
glEnable GL_LIGHT0
End Sub