テクスチュアマッピング(2)

1.テクスチュア画像の繰り返し

 例えばブロック壁などを作成する場合,サイズの小さなテクスチュア画像を繰り返してマッピングすることが一般的である.
 ただし,マッピング画像を作成する場合には,横方向あるいは縦方向に接続できるよう作成する必要がある.

 設定方法
  テクスチャアの環境設定を以下のように変える必要がある.(補間方法を線形補間にしておく必要がある)
        glPixelStorei GL_UNPACK_ALIGNMENT, 1
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_LINEAR
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAP_FILTER, GL_LINEAR
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
        glTexEnvf GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL
        glEnable GL_TEXTURE_2D
        glTexImage2D GL_TEXTURE_2D, 0, 3, tex.w, tex.h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex(0, 0, 0)

  物体上のテクスチュア座標の設定
        glBegin GL_QUADS
            '法線の設定
            glNormal3f 0, 0, 1
            'テクスチャア座標の設定:及び物体の作成
            glTexCoord2f 0, 0: glVertex3f -1, -1, 0
            glTexCoord2f 2, 0: glVertex3f 1, -1, 0
            glTexCoord2f 2, 2: glVertex3f 1, 1, 0
            glTexCoord2f 0, 2: glVertex3f -1, 1, 0
        glEnd
 

2.複数のテクスチュア画像を用いる.

  複数のテクスチュアマッピングを実現するためのコード(Texture2.frm参照)
 

3.テクスチュアマッピングに対するトランスペアレンシィ

  マッピングを行なった物体に関しても, 物体の色設定におけるアルファ値を1より小さくすることにより,
  トランスペアレシィの設定が可能である.
 

4.サンプルコード(1)

'Texture2.frm(複数のテクスチュアを用いる)
'Form1上にCommand1,Picture1,Picture2が必要
Option Explicit
Dim m_hGLRC&
Private Type axis
    X As Single
    Y As Single
    Z As Single
End Type
Private Type texture
    dtex() As Byte
    w As Integer
    h As Integer
End Type

Dim tex(10) As texture 'テクスチュアマッピング用の配列

Dim rot As axis
Dim tr As axis
Dim addt As axis
Dim addr As axis

Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        addt.X = 0: addt.Y = 0: addt.Z = -1
        addr.X = 0: addr.Y = 0: addr.Z = 0
    Else
        addt.X = 0: addt.Y = 0: addt.Z = 1
        addr.X = 0: addr.Y = 0: addr.Z = 0
    End If
    Timer1.Enabled = Not Timer1.Enabled
End Sub

Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Timer1.Enabled = Not Timer1.Enabled
End Sub

Private Sub Command2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        addt.X = 0: addt.Y = 0: addt.Z = 0
        addr.X = 0: addr.Y = 1: addr.Z = 0
    Else
        addt.X = 0: addt.Y = 0: addt.Z = 0
        addr.X = 0: addr.Y = -1: addr.Z = 0
    End If
    Timer1.Enabled = Not Timer1.Enabled
End Sub

Private Sub Command2_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Timer1.Enabled = Not Timer1.Enabled
End Sub

Private Sub Form_Load()
    Timer1.Interval = 10
    Timer1.Enabled = False
    Command1.Caption = "移動"
    Command2.Caption = "回転"
    tr.Z = 6
End Sub

Private Sub Picture1_Paint()
    display
End Sub

Private Sub SetView()
    glMatrixMode GL_PROJECTION
    glLoadIdentity
    glFrustum -2, 2, -2, 2, 2, 100   '透視投影変換設定(gluPerspectiveの代替)
    glMatrixMode GL_MODELVIEW
    glViewport 0, 0, Picture1.Width, Picture1.Height
End Sub

Private Sub Form_Initialize()
    Initialize
End Sub

Private Function Initialize() As Boolean
    Dim pfd As PIXELFORMATDESCRIPTOR
    Dim R&
    Picture1.ScaleMode = vbPixels
 
    'set standard parameters
    pfd.nSize = Len(pfd)
    pfd.nVersion = 1
    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)
    'palette?
    m_hGLRC = wglCreateContext(Picture1.hDC)
    wglMakeCurrent Picture1.hDC, m_hGLRC
 
    glDepthFunc GL_LEQUAL
    glEnable GL_DEPTH_TEST
    glShadeModel GL_FLAT
 
    'Fog
    Dim fogclr(4) As Single
    fogclr(0) = 1: fogclr(1) = 1: fogclr(2) = 1: fogclr(3) = 1
    glFogfv GL_FOG_COLOR, fogclr(0)
    glFogfv GL_FOG_DENSITY, 0.1
    glDisable GL_FOG  'fogをONにする場合には glEnable GL_FOG
    glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
    glEnable GL_BLEND
 
    Picture2.Visible = True  'ここをFalseにするとPicture2は表示されない.
 
    SetView
    SetLight
    ReadTex "tex1.bmp", tex(1)
    ReadTex "brick1.bmp", tex(2)
    ReadTex "cloud1.bmp", tex(3)
    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 ReadTex(bmpname As String, t As texture)
    Dim i As Integer, j As Integer, w As Integer, h As Integer
    Picture2.AutoRedraw = True
    Picture2.AutoSize = True
    Picture2.ScaleMode = vbPixels
 
    '画像ファイルの読み込み
    '(画像ファイルは自分の作成したファイル名)
    Picture2.Picture = LoadPicture(bmpname)
    t.w = Picture2.ScaleWidth
    t.h = Picture2.ScaleHeight
 
    '画像サイズが分かったので配列を再定義
    ReDim t.dtex(0 To 2, 0 To t.w - 1, 0 To t.h - 1)
 
 
    '配列に画像情報を入力する(上下反転に注意)
    For j = 0 To t.h - 1
        For i = 0 To t.w - 1
            t.dtex(0, i, (t.h - 1) - j) = getR(Picture2.Point(i, j))
            t.dtex(1, i, (t.h - 1) - j) = getG(Picture2.Point(i, j))
            t.dtex(2, i, (t.h - 1) - j) = getB(Picture2.Point(i, j))
        Next
    Next
End Sub
Private Sub SetLight()
    '平行光源(固定)
    Dim valueLight0(3) As Single
    Dim positionLight0(3) As Single
 
    'fillarray4fはユーザー定義
    FillArray4f valueLight0(), 0.7!, 0.7!, 0.7!, 1!
    FillArray4f positionLight0(), 0!, 1!, 1!, 0!
 
    glLightfv GL_LIGHT0, GL_AMBIENT, valueLight0(0)
    glLightfv GL_LIGHT0, GL_DIFFUSE, valueLight0(0)
    glLightfv GL_LIGHT0, GL_SPECULAR, valueLight0(0)
    glLightfv GL_LIGHT0, GL_POSITION, positionLight0(0)
 
    glEnable GL_LIGHTING
    glEnable GL_LIGHT0
End Sub

Private Sub display()
    Dim MaterialAmbient(3) As Single
    Dim MaterialDiffuse(3) As Single
    Dim MaterialSpecular(3) As Single
 
    glMatrixMode GL_MODELVIEW
 
    glClearColor 0.3, 0.3, 0.4, 1
    glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
    glLoadIdentity
    glRotatef rot.Y, 0, 1, 0
    glTranslatef -tr.X, 0, -tr.Z
 
    glPushMatrix
        glTranslatef 0, 0, 2
        FillArray4f MaterialAmbient(), 0.17, 0.2, 0.17, 1
        FillArray4f MaterialDiffuse(), 0.17, 0.2, 0.17, 1!
        FillArray4f MaterialSpecular(), 0.3, 0.4, 0.3, 1!
        glMaterialfv GL_FRONT, GL_AMBIENT, MaterialAmbient(0)
        glMaterialfv GL_FRONT, GL_DIFFUSE, MaterialDiffuse(0)
        glMaterialfv GL_FRONT, GL_SPECULAR, MaterialSpecular(0)
        glutSolidSphere 0.5, 20, 20
    glPopMatrix
 
    glPushMatrix
        glTranslatef -2, 0, 0
 
        FillArray4f MaterialAmbient(), 0.17, 0.17, 0.17, 1
        FillArray4f MaterialDiffuse(), 0.17, 0.17, 0.17, 1!
        FillArray4f MaterialSpecular(), 0.3, 0.3, 0.3, 1!
        glMaterialfv GL_FRONT, GL_AMBIENT, MaterialAmbient(0)
        glMaterialfv GL_FRONT, GL_DIFFUSE, MaterialDiffuse(0)
        glMaterialfv GL_FRONT, GL_SPECULAR, MaterialSpecular(0)
 
        'テクチュアの環境設定
        glPixelStorei GL_UNPACK_ALIGNMENT, 1
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_LINEAR
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
        glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
        glTexEnvf GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL
 
        'テクスチュアを実行可能にする
        glEnable GL_TEXTURE_2D
 
        'テクスチュアイメージの設定
        glTexImage2D GL_TEXTURE_2D, 0, 3, tex(1).w, tex(1).h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex(1).dtex(0, 0, 0)
        glBegin GL_QUADS
            '法線の設定
            glNormal3f 0, 0, 1
            'テクスチャア座標の設定:及び物体の作成
            glTexCoord2f 0, 0: glVertex3f -1, -1, 0
            glTexCoord2f 1, 0: glVertex3f 1, -1, 0
            glTexCoord2f 1, 1: glVertex3f 1, 1, 0
            glTexCoord2f 0, 1: glVertex3f -1, 1, 0
        glEnd
    glPopMatrix
 
    glPushMatrix
        glTranslatef 2, 0, 0
        FillArray4f MaterialAmbient(), 0.17, 0.17, 0.17, 1
        FillArray4f MaterialDiffuse(), 0.17, 0.17, 0.17, 1!
        FillArray4f MaterialSpecular(), 0.3, 0.3, 0.3, 1!
        glMaterialfv GL_FRONT, GL_AMBIENT, MaterialAmbient(0)
        glMaterialfv GL_FRONT, GL_DIFFUSE, MaterialDiffuse(0)
        glMaterialfv GL_FRONT, GL_SPECULAR, MaterialSpecular(0)
        glTexImage2D GL_TEXTURE_2D, 0, 3, tex(2).w, tex(2).h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex(2).dtex(0, 0, 0)
        glBegin GL_QUADS
            '法線の設定
            glNormal3f 0, 0, 1
            'テクスチャア座標の設定:及び物体の作成
            glTexCoord2f 0, 0: glVertex3f -1, -1, 0
            glTexCoord2f 2, 0: glVertex3f 1, -1, 0
            glTexCoord2f 2, 2: glVertex3f 1, 1, 0
            glTexCoord2f 0, 2: glVertex3f -1, 1, 0
        glEnd
    glPopMatrix
 
    '混合する物体は最後に描画
    glPushMatrix
        FillArray4f MaterialAmbient(), 0.3, 0.3, 0.3, 0.5
        FillArray4f MaterialDiffuse(), 0.2, 0.2, 0.2, 0.5
        FillArray4f MaterialSpecular(), 0.2, 0.2, 0.2, 0.5
        glMaterialfv GL_FRONT, GL_AMBIENT, MaterialAmbient(0)
        glMaterialfv GL_FRONT, GL_DIFFUSE, MaterialDiffuse(0)
        glMaterialfv GL_FRONT, GL_SPECULAR, MaterialSpecular(0)
        glTexImage2D GL_TEXTURE_2D, 0, 3, tex(3).w, tex(3).h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex(3).dtex(0, 0, 0)
        glBegin GL_QUADS
            '法線の設定
            glNormal3f 0, 0, 1
            'テクスチャア座標の設定:及び物体の作成
            glTexCoord2f 0, 0: glVertex3f -3, -3, 2
            glTexCoord2f 1, 0: glVertex3f 3, -3, 2
            glTexCoord2f 1, 1: glVertex3f 3, 3, 2
            glTexCoord2f 0, 1: glVertex3f -3, 3, 2
        glEnd
    glPopMatrix
 
    'テクスチュアOFF
    glDisable GL_TEXTURE_2D
 
    SwapBuffers Picture1.hDC
End Sub

Public Function getR(color As Long) 'Longの整数からR成分を抜き出す関数を設定
    getR = color And &HFF&
End Function

Public Function getG(color As Long)  'Longの整数からG成分を抜き出す関数を設定
    getG = (color And &HFF00&) / &H100&
End Function

Public Function getB(color As Long) 'Longの整数からB成分を抜き出す関数
    getB = (color And &HFF0000) / &H10000
End Function

Private Sub Timer1_Timer()
    rot.Y = rot.Y + 1 * addr.Y
    tr.X = tr.X + 0.2 * Sin((rot.Y) / 180 * 3.1415) * addt.Z
    tr.Z = tr.Z + 0.2 * Cos((rot.Y) / 180 * 3.1415) * addt.Z
    display
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
 

5.サンプルコード(2)

 Walk throughプログラム
 http://www.myu.ac.jp/~makanae/  OpenGLサンプルプログラム(Texture3)を参照