demoのc言語のソースをpythonに移植。
c言語のソースをpythonに移植しました。だいたい似た感じでつくっているので、この2つを見ていけば、python<->c言語は出来るようになると思います。関数の引数とか手順に関して言えば、全く同じです。pythonの場合は、フラグの定数とか、構造体を別途、書かなければなりませんが、一回手に入れれば使いまわすだけです。
このデモはエスケープキーで終了します。
from OpenGL.GL import * from OpenGL.WGL import * from ctypes import * from ctypes.wintypes import * import sys import time vsh = """ void main(){ gl_Position = gl_Vertex; } """ fsh = """ uniform vec2 resolution; uniform float time; void main() { vec2 p = (2.0 * gl_FragCoord.xy - resolution.xy) / resolution.y; p += vec2(cos(time), sin(time)) * 0.5; float g = exp(-1.5 * dot(p,p)); gl_FragColor = vec4(g, g, g, 1.0); } """ msh = """ #version 330 out vec2 gain; uniform float sampleRate; vec2 mainSound(float time) { return vec2(sin(6.2831*440.0*fract(time))); } void main() { float time = float(gl_VertexID) / sampleRate; gain = mainSound(time) ; } """ winmm = windll.winmm kernel32 = windll.kernel32 user32 = windll.user32 WS_POPUP = 0x80000000 WS_OVERLAPPEDWINDOW = 0xcf0000 WS_VISIBLE = 0x10000000 PM_REMOVE = 1 WM_NCLBUTTONDOWN = 161 HTCLOSE = 20 VK_ESCAPE = 27 PFD_SUPPORT_OPENGL = 32 PFD_DOUBLEBUFFER = 1 WAVE_FORMAT_IEEE_FLOAT = 3 WAVE_MAPPER = -1 TIME_SAMPLES = 2 class WAVEFORMATEX(Structure): _fields_ = [ ("wFormatTag", WORD), ("nChannels", WORD), ("nSamplesPerSec", DWORD), ("nAvgBytesPerSec", DWORD), ("nBlockAlign", WORD), ("wBitsPerSample", WORD), ("cbSize", WORD) ] class WAVEHDR(Structure): pass LPWAVEHDR = POINTER(WAVEHDR) WAVEHDR._fields_ = [ ("lpData", LPSTR), ("dwBufferLength", DWORD), ("dwBytesRecorded", DWORD), ("dwUser", POINTER(DWORD)), ("dwFlags", DWORD), ("dwLoops", DWORD), ("lpNext", LPWAVEHDR), ("reserved", POINTER(DWORD)) ] class SMPTE(Structure): _fields_ = [ ("hour", BYTE), ("min", BYTE), ("sec", BYTE), ("frame", BYTE), ("fps", BYTE), ("dummy", BYTE), ("pad"[2], BYTE) ] class MIDI(Structure): _fields_ = [ ("songptrpos", DWORD) ] class U(Union): _fields_ = [ ("ms", DWORD), ("sample", DWORD), ("cb", DWORD), ("ticks", DWORD), ("smpte", SMPTE), ("midi", MIDI), ] class MMTIME(Structure): _fields_ = [ ("wType", UINT), ("u", U), ] XRES = 640 YRES = 480 SND_DURATION = 180 SAMPLE_RATE = 44100 SND_NUMCHANNELS = 2 SND_NUMSAMPLES = (SND_DURATION*SAMPLE_RATE) SND_NUMSAMPLESC = (SND_NUMSAMPLES*SND_NUMCHANNELS) samples = (c_float * SND_NUMSAMPLESC)() def main(): hdc = user32.GetDC(user32.CreateWindowExA(0,0xC018,0,WS_OVERLAPPEDWINDOW|WS_VISIBLE,0,0,XRES,YRES,0,0,0,0)) #hdc = user32.GetDC(user32.CreateWindowExA(0,0xC018,0,WS_POPUP|WS_VISIBLE,0,0,XRES,YRES,0,0,0,0)) pfd = PIXELFORMATDESCRIPTOR(0,1,PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,32,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0) SetPixelFormat(hdc,ChoosePixelFormat(hdc, pfd), pfd) wglMakeCurrent(hdc, wglCreateContext(hdc)) # mzk init programM = glCreateProgram() shader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(shader, msh) glCompileShader(shader) if glGetShaderiv(shader, GL_COMPILE_STATUS) != GL_TRUE: raise RuntimeError(glGetShaderInfoLog(shader).decode()) glAttachShader(programM, shader) outs = cast((c_char_p*1)(b"gain"), POINTER(POINTER(c_char))) glTransformFeedbackVaryings(programM, 1, outs, GL_INTERLEAVED_ATTRIBS) glLinkProgram(programM) glUseProgram(programM) vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, sizeof(samples), None, GL_STATIC_DRAW) glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo) glUniform1f(glGetUniformLocation(programM, "sampleRate"), SAMPLE_RATE) glEnable(GL_RASTERIZER_DISCARD) glBeginTransformFeedback(GL_POINTS) glDrawArrays(GL_POINTS, 0, SND_NUMSAMPLES) glEndTransformFeedback() glDisable(GL_RASTERIZER_DISCARD) glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(samples), byref(samples)) # gfx init global program program = glCreateProgram() shader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(shader, vsh) glCompileShader(shader) if glGetShaderiv(shader, GL_COMPILE_STATUS) != GL_TRUE: raise RuntimeError(glGetShaderInfoLog(shader).decode()) glAttachShader(program, shader) shader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(shader, fsh) glCompileShader(shader) if glGetShaderiv(shader, GL_COMPILE_STATUS) != GL_TRUE: raise RuntimeError(glGetShaderInfoLog(shader).decode()) glAttachShader(program, shader) glLinkProgram(program) glUseProgram(program) glUniform2f(glGetUniformLocation(program, "resolution"), XRES, YRES) wh = WAVEHDR(cast(samples, LPSTR), sizeof(samples)) wfx = WAVEFORMATEX( WAVE_FORMAT_IEEE_FLOAT, SND_NUMCHANNELS, SAMPLE_RATE, SAMPLE_RATE*sizeof(c_float)*SND_NUMCHANNELS, sizeof(c_float)*SND_NUMCHANNELS, sizeof(c_float)*8, 0 ) hwo = HANDLE(0) winmm.waveOutOpen(byref(hwo), WAVE_MAPPER, byref(wfx), 0, 0, 0) winmm.waveOutPrepareHeader(hwo, byref(wh), sizeof(WAVEHDR)) winmm.waveOutWrite(hwo, byref(wh), sizeof(WAVEHDR)) mmt = MMTIME(TIME_SAMPLES) msg = MSG() lpmsg = pointer(msg) fps, cnt, s0 = 0, 0, 0 while True: while user32.PeekMessageA(lpmsg, 0, 0, 0, PM_REMOVE): if (msg.message == WM_NCLBUTTONDOWN and msg.wParam == HTCLOSE): sys.exit() user32.DispatchMessageA(lpmsg) if(user32.GetAsyncKeyState(VK_ESCAPE)): sys.exit() winmm.waveOutGetPosition(hwo, byref(mmt), sizeof(mmt)) glUniform1f(glGetUniformLocation(program, "time"), mmt.u.sample / SAMPLE_RATE) glRects(1, 1, -1, -1) SwapBuffers(hdc) cnt += 1 if (mmt.u.sample - s0 > SAMPLE_RATE): fps = cnt cnt = 0 s0 = mmt.u.sample sys.stdout.write("\r FPS : %d TIME : %f" %(fps, mmt.u.sample / SAMPLE_RATE)) sys.stdout.flush() if (mmt.u.sample == SND_NUMSAMPLES): sys.exit() if __name__ == '__main__': main()
webGLに移植に関しては、ちょっと面倒です。同様の関数が無かったりすることがあるからです。手順に関しては、全く同じ良いです。