fortran66のブログ

fortran について書きます。

VBO 頂点バッファオブジェクト

ここを参考に Fortran で頂点バッファオブジェクトを使ってみます。本体はほぼ移植です。F03GLを利用。(F90GLにはインプリメントされていない命令がある?)


メモ帳

Libs::opengl_glext_c.lib glew64.lib glut64.lib opengl32.lib glu32.lib
LibPath::C:\Fortran\OpenGL\rb\x64\debug
cpp::static lib
f90::ProjectRightClick->OrojectDependency->cpp

MODULE m_mod
USE opengl_glu
USE opengl_glut
USE opengl_glext

INTEGER :: n(10)
REAL(GLfloat) :: points(3, 4)

CONTAINS
!-----------------------------------------------------------------
SUBROUTINE keyboard(key, x, y) BIND(C)
USE OpenGL_GL
INTEGER (kind=GLbyte), INTENT(in), VALUE :: key
INTEGER (kind=GLint ), INTENT(in), VALUE :: x, y
IF( key == 27 ) stop 'esc hit'
RETURN
END SUBROUTINE keyboard
!-----------------------------------------------------------------
SUBROUTINE reshape0(w, h) BIND(C, name = 'reshape')
INTEGER, VALUE, INTENT(IN) :: w, h
CALL glViewport(0, 0, w, h)
CALL glMatrixMode(GL_PROJECTION) 
CALL glLoadIdentity()
CALL gluPerspective(30.0, REAL(w, 8) / REAL(h, 8), 1.0, 100.0)
CALL glMatrixMode(GL_MODELVIEW)
CALL glLoadIdentity()
END SUBROUTINE reshape0
!-----------------------------------------------------------------
SUBROUTINE display() BIND(C, name = 'display')
CALL glClear( IOR(GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT) )
CALL glLoadIdentity()
CALL gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

CALL DRAW_XYZ() 
CALL glEnable(GL_DEPTH_TEST) 
CALL glColor3d(0, 1, 0) 

CALL glBindBuffer(GL_ARRAY_BUFFER, n(1))
CALL glVertexPointer(3, GL_FLOAT, 0, NULL())

CALL glEnableClientState(GL_VERTEX_ARRAY)
CALL glColor3d(1, 0, 1) 
CALL glDrawArrays(GL_POLYGON , 0 , 4)
CALL glDisableClientState(GL_VERTEX_ARRAY)

CALL glColor3d(1,1,1)
CALL glDisable(GL_DEPTH_TEST)
CALL glutSwapBuffers()
RETURN
END SUBROUTINE display
!-----------------------------------------------------------------
SUBROUTINE DRAW_XYZ()
CALL glBegin(GL_LINES)
CALL glColor3d(0, 1, 0)    ! x
CALL glVertex2d(-100, 0)
CALL glVertex2d( 100, 0)

CALL glColor3d(1, 0, 0)    ! y
CALL glVertex2d(0, -100)
CALL glVertex2d(0,  100)

CALL glColor3d(0, 0, 1)    ! z
CALL glVertex3d(0, 0, -100)
CALL glVertex3d(0, 0,  100)
CALL glEnd() 
RETURN
END SUBROUTINE DRAW_XYZ
!-----------------------------------------------------------------
END MODULE m_mod
!==================================================================
PROGRAM test
USE m_mod
USE IFwin
USE opengl_glut
USE opengl_glext
USE opengl_glee
IMPLICIT NONE
INTERFACE
 INTEGER FUNCTION glewinit() BIND(C, name='glewInit')
 END FUNCTION glewinit
 
 INTEGER FUNCTION glewIsSupported(text) BIND(C, name='glewIsSupported')
 CHARACTER(*) :: text
 END FUNCTION glewIsSupported
END INTERFACE
!
INTEGER :: i, iwin, bufferSize = 0
points = RESHAPE([-1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0], [3, 4])
CALL glutInit()
CALL glutInitDisplayMode(ior(GLUT_DOUBLE, ior(GLUT_RGB,GLUT_DEPTH)))
CALL glutInitWindowSize(400, 400)
iwin = glutCreateWindow('OpenGL VBO'//char(0))
!
i = glewInit() 
!PRINT *, i, glewIsSupported("GL_VERSION_1_4 GL_ARB_point_sprite"C)
CALL glutDisplayFunc(display)
CALL glutReshapeFunc(reshape0)
CALL glutKeyboardFunc(keyboard)
CALL glClearColor(1.0, 1.0, 1.0, 1.0)

CALL glGenBuffers(1, n)
!PRINT *, n, LOC(points), TRANSFER(C_LOC(points), 1), TRANSFER(C_LOC(points), INT(1, 8))
CALL glBindBuffer(GL_ARRAY_BUFFER, n(1)) 
CALL glBufferData(GL_ARRAY_BUFFER, 4*3*4, C_LOC(points), GL_STATIC_DRAW)
!CALL glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, bufferSize )
!PRINT *, 'buffefsize', buffersize
CALL glBindBuffer(GL_ARRAY_BUFFER, NULL) 

CALL glutMainLoop()
STOP
END PROGRAM test
MODULE opengl_glext
USE opengl_gl
USE, INTRINSIC :: iso_c_BINDing
   
INTEGER(glenum), PARAMETER :: GL_TEXTURE_COMPARE_FAIL_VALUE_ARB = z'80bf' 

INTEGER(glenum), PARAMETER :: GL_DEPTH_TEXTURE_MODE       = z'884b' 
INTEGER(glenum), PARAMETER :: GL_TEXTURE_COMPARE_MODE     = z'884c' 
INTEGER(glenum), PARAMETER :: GL_COMPARE_R_TO_TEXTURE     = z'884e' 

INTEGER(glenum), PARAMETER :: GL_QUERY_COUNTER_BITS       = z'8864' 
INTEGER(glenum), PARAMETER :: GL_CURRENT_QUERY            = z'8865' 
INTEGER(glenum), PARAMETER :: GL_QUERY_RESULT             = z'8866' 
INTEGER(glenum), PARAMETER :: GL_QUERY_RESULT_AVAILABLE   = z'8867' 

INTEGER(glenum), PARAMETER :: GL_ARRAY_BUFFER             = z'8892' 
INTEGER(glenum), PARAMETER :: GL_ELEMENT_ARRAY_BUFFER     = z'8893' 
   
INTEGER(glenum), PARAMETER :: GL_READ_WRITE               = z'88ba' 
  
INTEGER(glenum), PARAMETER :: GL_PIXEL_PACK_BUFFER        = z'88eb' 
INTEGER(glenum), PARAMETER :: GL_PIXEL_UNPACK_BUFFER      = z'88ec' 

INTEGER(glenum), PARAMETER :: GL_STREAM_DRAW              = z'88e0' 
INTEGER(glenum), PARAMETER :: GL_STREAM_READ              = z'88e1' 
INTEGER(glenum), PARAMETER :: GL_STREAM_COPY              = z'88e2'
    
INTEGER(glenum), PARAMETER :: GL_STATIC_DRAW              = z'88e4' 
INTEGER(glenum), PARAMETER :: GL_STATIC_READ              = z'88e5' 
INTEGER(glenum), PARAMETER :: GL_STATIC_COPY              = z'88e6'
    
INTEGER(glenum), PARAMETER :: GL_DYNAMIC_DRAW             = z'88e8' 
INTEGER(glenum), PARAMETER :: GL_DYNAMIC_READ             = z'88e9' 
INTEGER(glenum), PARAMETER :: GL_DYNAMIC_COPY             = z'88ea' 

INTEGER(glenum), PARAMETER :: GL_SAMPLES_PASSED           = z'8914' 

INTEGER(glenum), PARAMETER :: gl_buffer_size = Z'8764'

INTERFACE  
! glGenBuffers etc is available only if the GL version is 1.5 or greater.
! glGenBuffers - generate buffer object names
! void glGenBuffers( GLsizei n, GLuint* buffers)
SUBROUTINE glGenBuffers(n, buffers) BIND(C, name="cglewGenBuffers")
 USE opengl_gl
 INTEGER(kind=GLsizei), VALUE :: n
 INTEGER(GLuint), DIMENSION(n), intent(OUT) :: buffers       
END SUBROUTINE glGenBuffers
! glBINDBuffer - BIND a named buffer object
! void glBINDBuffer( GLenum TARGET, GLuint buffer)
SUBROUTINE glBINDBuffer(TARGET, buffer) BIND(C, name="cglewBindBuffer")
 USE opengl_gl
 INTEGER(GLenum), VALUE :: TARGET
 INTEGER(GLuint), VALUE :: buffer       
END SUBROUTINE glBINDBuffer
! glBufferData - creates and initializes a buffer object's data store
! void glBufferData( GLenum TARGET, GLsizeiptr size, const GLvoid* data, GLenum usage)
SUBROUTINE glBufferData(TARGET, size, data, usage) BIND(C, name="cglewBufferData")
  USE opengl_gl
  INTEGER(kind=GLenum), VALUE :: TARGET
  INTEGER(kind=GLsizei), VALUE :: size    ! size in bytes
  TYPE(C_PTR), VALUE :: data              ! pointer to data that will be copied into the data store
  INTEGER(kind=GLenum), VALUE :: usage    ! the expected usage pattern of the data store
END SUBROUTINE glBufferData
! glMapBuffer - map a buffer object's data store
! void * glMapBuffer( GLenum TARGET, GLenum access)
FUNCTION glMapBuffer(TARGET, access) BIND(C, name="cglewMapBuffer")
  USE opengl_gl
  TYPE(C_PTR) :: glMapBuffer       
  INTEGER(kind=GLenum), VALUE :: TARGET
  INTEGER(kind=GLenum), VALUE :: access
END FUNCTION glMapBuffer
!  
INTEGER(GLboolean) FUNCTION glUnmapBuffer(TARGET) BIND(C, name="cglewUnmapBuffer")
  USE opengl_gl
  INTEGER(kind=GLenum), VALUE :: TARGET
END FUNCTION glUnmapBuffer
!
SUBROUTINE glGetBufferPARAMETERiv(TARGET, VALUE, data) BIND(C, name = 'cglewGetBufferParameteriv')
  USE opengl_gl
  INTEGER(kind=GLenum), VALUE :: TARGET
  INTEGER(kind=GLenum), VALUE :: VALUE
  INTEGER :: data
END SUBROUTINE glGetBufferPARAMETERiv 
!
END INTERFACE
END MODULE opengl_glext
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdio.h>
extern "C" void cglewGenBuffers(GLsizei n, GLuint* buffer)
{
    glGenBuffers( n, buffer );
}

extern "C" void cglewBindBuffer(GLenum target, GLuint buffer) 
{
    glBindBuffer( target, buffer );
}

extern "C" void cglewBufferData(GLenum target, GLsizei size, const GLvoid * data, GLenum usage) 
{
	glBufferData(target, size, data, usage);
}

extern "C" GLvoid* cglewMapBuffer(GLenum target, GLenum access)
{
	return glMapBuffer(target, access);
}

extern "C" GLboolean cglewUnmapBuffer(GLenum target)
{
	return glUnmapBuffer(target);
}
extern "C" void cglewGetBufferParameteriv(GLenum target, GLenum value, GLint * data) 
{
	glGetBufferParameteriv(target, value, data); 
}

glUnmapBuffer, glmapbuffer は動作未確認。