render.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. # A visualizer for the Python client (or any other client) rendering to a mapped file
  2. import optparse
  3. import mmap
  4. import os
  5. import time
  6. import struct
  7. import colorsys
  8. import math
  9. parser = optparse.OptionParser()
  10. parser.add_option('-E', '--engine', dest='engine', default='pygame', help='Rendering engine to use')
  11. parser.add_option('--map-file', dest='map_file', default='client_map', help='File mapped by -G mapped')
  12. parser.add_option('--map-samples', dest='map_samples', type='int', default=4096, help='Number of samples in the map file (MUST agree with client)')
  13. parser.add_option('--pg-samp-width', dest='samp_width', type='int', help='Set the width of the sample pane (by default display width / 2)')
  14. parser.add_option('--pg-fullscreen', dest='fullscreen', action='store_true', help='Use a full-screen video mode')
  15. parser.add_option('--pg-no-colback', dest='no_colback', action='store_true', help='Don\'t render a colored background')
  16. parser.add_option('--pg-low-freq', dest='low_freq', type='int', default=40, help='Low frequency for colored background')
  17. parser.add_option('--pg-high-freq', dest='high_freq', type='int', default=1500, help='High frequency for colored background')
  18. parser.add_option('--pg-log-base', dest='log_base', type='int', default=2, help='Logarithmic base for coloring (0 to make linear)')
  19. options, args = parser.parse_args()
  20. while not os.path.exists(options.map_file):
  21. print 'Waiting for file to exist...'
  22. time.sleep(1)
  23. f = open(options.map_file)
  24. mapping = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
  25. f.close()
  26. fixfmt = '>f'
  27. fixfmtsz = struct.calcsize(fixfmt)
  28. sigfmt = '>' + 'f' * options.map_samples
  29. sigfmtsz = struct.calcsize(sigfmt)
  30. strfmtsz = len(mapping) - fixfmtsz - sigfmtsz
  31. print 'Map size:', len(mapping), 'Appendix size:', strfmtsz
  32. print 'Size triple:', fixfmtsz, sigfmtsz, strfmtsz
  33. STREAMS = strfmtsz / struct.calcsize('>Lf')
  34. strfmt = '>' + 'Lf' * STREAMS
  35. print 'Detected', STREAMS, 'streams'
  36. if options.engine == 'pygame':
  37. import pygame
  38. import pygame.gfxdraw
  39. pygame.init()
  40. WIDTH, HEIGHT = 640, 480
  41. dispinfo = pygame.display.Info()
  42. if dispinfo.current_h > 0 and dispinfo.current_w > 0:
  43. WIDTH, HEIGHT = dispinfo.current_w, dispinfo.current_h
  44. flags = 0
  45. if options.fullscreen:
  46. flags |= pygame.FULLSCREEN
  47. disp = pygame.display.set_mode((WIDTH, HEIGHT), flags)
  48. WIDTH, HEIGHT = disp.get_size()
  49. SAMP_WIDTH = WIDTH / 2
  50. if options.samp_width:
  51. SAMP_WIDTH = options.samp_width
  52. BGR_WIDTH = WIDTH - SAMP_WIDTH
  53. HALFH = HEIGHT / 2
  54. PFAC = HEIGHT / 128.0
  55. sampwin = pygame.Surface((SAMP_WIDTH, HEIGHT))
  56. sampwin.set_colorkey((0, 0, 0))
  57. lastsy = HALFH
  58. bgrwin = pygame.Surface((BGR_WIDTH, HEIGHT))
  59. bgrwin.set_colorkey((0, 0, 0))
  60. clock = pygame.time.Clock()
  61. font = pygame.font.SysFont(pygame.font.get_default_font(), 24)
  62. def rgb_for_freq_amp(f, a):
  63. a = max((min((a, 1.0)), 0.0))
  64. pitchval = float(f - options.low_freq) / (options.high_freq - options.low_freq)
  65. if options.log_base == 0:
  66. try:
  67. pitchval = math.log(pitchval) / math.log(options.log_base)
  68. except ValueError:
  69. pass
  70. bgcol = colorsys.hls_to_rgb(min((1.0, max((0.0, pitchval)))), 0.5 * (a ** 2), 1.0)
  71. return [int(i*255) for i in bgcol]
  72. while True:
  73. DISP_FACTOR = struct.unpack(fixfmt, mapping[:fixfmtsz])[0]
  74. LAST_SAMPLES = struct.unpack(sigfmt, mapping[fixfmtsz:fixfmtsz+sigfmtsz])
  75. VALUES = struct.unpack(strfmt, mapping[fixfmtsz+sigfmtsz:])
  76. FREQS, AMPS = VALUES[::2], VALUES[1::2]
  77. if options.no_colback:
  78. disp.fill((0, 0, 0), (0, 0, WIDTH, HEIGHT))
  79. else:
  80. gap = WIDTH / STREAMS
  81. for i in xrange(STREAMS):
  82. FREQ = FREQS[i]
  83. AMP = AMPS[i]
  84. if FREQ > 0:
  85. bgcol = rgb_for_freq_amp(FREQ, AMP)
  86. else:
  87. bgcol = (0, 0, 0)
  88. disp.fill(bgcol, (i*gap, 0, gap, HEIGHT))
  89. bgrwin.scroll(-1, 0)
  90. bgrwin.fill((0, 0, 0), (BGR_WIDTH - 1, 0, 1, HEIGHT))
  91. for i in xrange(STREAMS):
  92. FREQ = FREQS[i]
  93. AMP = AMPS[i]
  94. if FREQ > 0:
  95. try:
  96. pitch = 12 * math.log(FREQ / 440.0, 2) + 69
  97. except ValueError:
  98. pitch = 0
  99. else:
  100. pitch = 0
  101. col = [min(max(int(AMP * 255), 0), 255)] * 3
  102. bgrwin.fill(col, (BGR_WIDTH - 1, HEIGHT - pitch * PFAC - PFAC, 1, PFAC))
  103. sampwin.fill((0, 0, 0), (0, 0, SAMP_WIDTH, HEIGHT))
  104. x = 0
  105. for i in LAST_SAMPLES:
  106. sy = int(i * HALFH + HALFH)
  107. pygame.gfxdraw.line(sampwin, x - 1, lastsy, x, sy, (0, 255, 0))
  108. x += 1
  109. lastsy = sy
  110. disp.blit(bgrwin, (0, 0))
  111. disp.blit(sampwin, (BGR_WIDTH, 0))
  112. if DISP_FACTOR != 0:
  113. tsurf = font.render('%+011.6g'%(DISP_FACTOR,), True, (255, 255, 255), (0, 0, 0))
  114. disp.fill((0, 0, 0), tsurf.get_rect())
  115. disp.blit(tsurf, (0, 0))
  116. pygame.display.flip()
  117. for ev in pygame.event.get():
  118. if ev.type == pygame.KEYDOWN:
  119. if ev.key == pygame.K_ESCAPE:
  120. pygame.quit()
  121. exit()
  122. elif ev.type == pygame.QUIT:
  123. pygame.quit()
  124. exit()
  125. if not os.path.exists(options.map_file):
  126. pygame.quit()
  127. exit()
  128. clock.tick(60)
  129. elif options.engine == 'glfw':
  130. import array, ctypes
  131. import glfw
  132. from OpenGL import GL
  133. from OpenGL.GL import *
  134. if not glfw.init():
  135. print 'GLFW: Init failed'
  136. exit()
  137. monitor = glfw.get_primary_monitor()
  138. mode = glfw.get_video_mode(monitor)
  139. glfw.window_hint(glfw.RED_BITS, mode.bits.red)
  140. glfw.window_hint(glfw.GREEN_BITS, mode.bits.green)
  141. glfw.window_hint(glfw.BLUE_BITS, mode.bits.blue)
  142. glfw.window_hint(glfw.REFRESH_RATE, mode.refresh_rate)
  143. glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
  144. glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
  145. glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
  146. win = glfw.create_window(mode.size.width, mode.size.height, 'render', monitor, None)
  147. if not win:
  148. print 'GLFW: Window creation failed'
  149. glfw.terminate()
  150. exit()
  151. glfw.make_context_current(win)
  152. print 'Version:', glGetString(GL_VERSION)
  153. print 'Renderer:', glGetString(GL_RENDERER)
  154. rect_data = array.array('f', [
  155. -1.0, -1.0,
  156. 1.0, -1.0,
  157. 1.0, 1.0,
  158. -1.0, -1.0,
  159. 1.0, 1.0,
  160. -1.0, 1.0,
  161. ])
  162. rect = glGenBuffers(1)
  163. glBindBuffer(GL_ARRAY_BUFFER, rect)
  164. glBufferData(GL_ARRAY_BUFFER, rect_data.tostring(), GL_STATIC_DRAW)
  165. rect_zo_data = array.array('f', [
  166. 0.0, 0.0,
  167. 1.0, 0.0,
  168. 1.0, 1.0,
  169. 0.0, 0.0,
  170. 1.0, 1.0,
  171. 0.0, 1.0,
  172. ])
  173. rect_zo = glGenBuffers(1)
  174. glBindBuffer(GL_ARRAY_BUFFER, rect_zo)
  175. glBufferData(GL_ARRAY_BUFFER, rect_zo_data.tostring(), GL_STATIC_DRAW)
  176. samp_buf = glGenBuffers(1)
  177. glBindBuffer(GL_ARRAY_BUFFER, samp_buf)
  178. glBufferData(GL_ARRAY_BUFFER, mapping[fixfmtsz:fixfmtsz+sigfmtsz], GL_STREAM_DRAW)
  179. glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, samp_buf)
  180. freq_buf = glGenBuffers(1)
  181. glBindBuffer(GL_ARRAY_BUFFER, freq_buf)
  182. glBufferData(GL_ARRAY_BUFFER, STREAMS * 4, None, GL_STREAM_DRAW)
  183. glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, freq_buf)
  184. amp_buf = glGenBuffers(1)
  185. glBindBuffer(GL_ARRAY_BUFFER, amp_buf)
  186. glBufferData(GL_ARRAY_BUFFER, STREAMS * 4, None, GL_STREAM_DRAW)
  187. glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, amp_buf)
  188. lin_buf = glGenBuffers(1)
  189. glBindBuffer(GL_ARRAY_BUFFER, lin_buf)
  190. lin_arr = array.array('f', [(float(i) / options.map_samples) * 2.0 - 1.0 for i in range(options.map_samples)])
  191. #print lin_arr
  192. glBufferData(GL_ARRAY_BUFFER, lin_arr.tostring(), GL_STATIC_DRAW)
  193. bg_tex = glGenTextures(1)
  194. glBindTexture(GL_TEXTURE_2D, bg_tex)
  195. bg_data = array.array('B', [0 for i in range(mode.size.width * mode.size.height)])
  196. glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, mode.size.width, mode.size.height, 0, GL_RED, GL_UNSIGNED_BYTE, bg_data.tostring())
  197. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
  198. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
  199. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
  200. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
  201. bg_swp = glGenTextures(1)
  202. glBindTexture(GL_TEXTURE_2D, bg_swp)
  203. glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, mode.size.width, mode.size.height, 0, GL_RED, GL_UNSIGNED_BYTE, bg_data.tostring())
  204. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
  205. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
  206. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
  207. glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
  208. # Some *4s below because the texture is packed as RGBA8 despite only indexing R
  209. bar_pfac = mode.size.height / 128.0
  210. bg_bar_h = int(bar_pfac)
  211. bg_bar_sz = (bg_bar_h*4)
  212. block_d = '\x7f' * (64*64*4)
  213. clear_d = '\x00' * (mode.size.height*4)
  214. fbs = glGenFramebuffers(1)
  215. fbd = glGenFramebuffers(1)
  216. def make_prog(vss, fss):
  217. vs = glCreateShader(GL_VERTEX_SHADER)
  218. glShaderSource(vs, vss)
  219. glCompileShader(vs)
  220. if not glGetShaderiv(vs, GL_COMPILE_STATUS):
  221. print 'Vertex error:', glGetShaderInfoLog(vs)
  222. exit()
  223. fs = glCreateShader(GL_FRAGMENT_SHADER)
  224. glShaderSource(fs, fss)
  225. glCompileShader(fs)
  226. if not glGetShaderiv(fs, GL_COMPILE_STATUS):
  227. print 'Fragment error:', glGetShaderInfoLog(fs)
  228. exit()
  229. prog = glCreateProgram()
  230. glAttachShader(prog, vs)
  231. glAttachShader(prog, fs)
  232. glLinkProgram(prog)
  233. if not glGetProgramiv(prog, GL_LINK_STATUS):
  234. print 'Program error:', glGetProgramInfoLog(prog)
  235. exit()
  236. return prog
  237. prog_bg = make_prog('''
  238. #version 430
  239. in vec2 vPosition;
  240. in vec2 vTex;
  241. out vec2 vUV;
  242. void main(void) {
  243. gl_Position = vec4(vPosition,0.0,1.0);
  244. vUV = vTex;
  245. }''', '''
  246. #version 430
  247. in vec2 vUV;
  248. layout (location = 0) out vec4 FragColor;
  249. layout (std430, binding = 2) buffer bfreq {
  250. uint freq[];
  251. };
  252. layout (std430, binding = 3) buffer bamp {
  253. float amp[];
  254. };
  255. vec3 map_col(uint fr, float intensity) {
  256. if(fr == 0) return vec3(0.0,0.0,0.0);
  257. return vec3(
  258. 0.66 * clamp((float(fr) - 40.0) / (1500.0 - 40.0), 0.0, 1.0),
  259. 1.0,
  260. clamp(intensity, 0.0, 1.0)
  261. );
  262. }
  263. vec3 hsv2rgb(vec3 c)
  264. {
  265. vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
  266. vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
  267. return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
  268. }
  269. void main(void) {
  270. float zox = (vUV.x + 1.0) / 2.0;
  271. uint v = uint(zox * freq.length());
  272. FragColor = vec4(
  273. hsv2rgb(map_col(freq[v], amp[v])),
  274. 1.0
  275. );
  276. }''')
  277. glUseProgram(prog_bg)
  278. vao_bg = glGenVertexArrays(1)
  279. glBindVertexArray(vao_bg)
  280. glBindBuffer(GL_ARRAY_BUFFER, rect)
  281. a_vPosition = glGetProgramResourceLocation(prog_bg, GL_PROGRAM_INPUT, 'vPosition')
  282. print 'prog_bg a_vPosition', a_vPosition
  283. glVertexAttribPointer(a_vPosition, 2, GL_FLOAT, False, 0, None)
  284. glEnableVertexAttribArray(a_vPosition)
  285. a_vTex = glGetProgramResourceLocation(prog_bg, GL_PROGRAM_INPUT, 'vTex')
  286. print 'prog_bg a_vTex', a_vTex
  287. glVertexAttribPointer(a_vTex, 2, GL_FLOAT, False, 0, None)
  288. glEnableVertexAttribArray(a_vTex)
  289. prog_scope = make_prog('''
  290. #version 430
  291. in float vX;
  292. in float vY;
  293. void main(void) {
  294. gl_Position = vec4(vX, vY, 0.0, 1.0);
  295. }
  296. ''', '''
  297. #version 430
  298. layout (location = 0) out vec4 FragColor;
  299. void main(void) {
  300. FragColor = vec4(0.0, 1.0, 0.0, 1.0);
  301. }
  302. ''')
  303. glUseProgram(prog_scope)
  304. vao_scope = glGenVertexArrays(1)
  305. glBindVertexArray(vao_scope)
  306. glBindBuffer(GL_ARRAY_BUFFER, lin_buf)
  307. a_vX = glGetProgramResourceLocation(prog_scope, GL_PROGRAM_INPUT, 'vX')
  308. print 'prog_scope a_vX', a_vX
  309. glVertexAttribPointer(a_vX, 1, GL_FLOAT, False, 0, None)
  310. glEnableVertexAttribArray(a_vX)
  311. glBindBuffer(GL_ARRAY_BUFFER, samp_buf)
  312. a_vY = glGetProgramResourceLocation(prog_scope, GL_PROGRAM_INPUT, 'vY')
  313. print 'prog_scope a_vY', a_vY
  314. glVertexAttribPointer(a_vY, 1, GL_FLOAT, False, 0, None)
  315. glEnableVertexAttribArray(a_vY)
  316. prog_bar = make_prog('''
  317. #version 430
  318. in vec2 vPosition;
  319. in vec2 vTex;
  320. out vec2 vUV;
  321. void main(void) {
  322. gl_Position = vec4(vPosition, 0.0, 1.0);
  323. vUV = vTex;
  324. }''', '''
  325. #version 430
  326. in vec2 vUV;
  327. layout (location = 0) out vec4 FragColor;
  328. uniform sampler2D uTex;
  329. void main(void) {
  330. vec4 col = texture(uTex, vUV);
  331. FragColor = vec4(1.0, 1.0, 1.0, col.r);
  332. }''')
  333. glUseProgram(prog_bar)
  334. vao_bar = glGenVertexArrays(1)
  335. glBindVertexArray(vao_bar)
  336. glBindBuffer(GL_ARRAY_BUFFER, rect)
  337. a_vPosition = glGetProgramResourceLocation(prog_bar, GL_PROGRAM_INPUT, 'vPosition')
  338. print 'prog_bar a_vPosition', a_vPosition
  339. glVertexAttribPointer(a_vPosition, 2, GL_FLOAT, False, 0, None)
  340. glEnableVertexAttribArray(a_vPosition)
  341. a_vTex = glGetProgramResourceLocation(prog_bar, GL_PROGRAM_INPUT, 'vTex')
  342. print 'prog_bar a_vTex', a_vTex
  343. glBindBuffer(GL_ARRAY_BUFFER, rect_zo)
  344. glVertexAttribPointer(a_vTex, 2, GL_FLOAT, False, 0, None)
  345. glEnableVertexAttribArray(a_vTex)
  346. u_uTex = glGetProgramResourceLocation(prog_bar, GL_UNIFORM, 'uTex')
  347. print 'prog_bar u_uTex', u_uTex
  348. glUniform1i(u_uTex, 0)
  349. glActiveTexture(GL_TEXTURE0)
  350. glBindTexture(GL_TEXTURE_2D, bg_tex)
  351. glClearColor(0.2, 0.0, 0.0, 1.0)
  352. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  353. while not glfw.window_should_close(win):
  354. glfw.make_context_current(win)
  355. glClear(GL_COLOR_BUFFER_BIT)
  356. arr = array.array('f')
  357. arr.fromstring(mapping[fixfmtsz:fixfmtsz+sigfmtsz])
  358. arr.byteswap()
  359. glBindBuffer(GL_ARRAY_BUFFER, samp_buf)
  360. glBufferSubData(GL_ARRAY_BUFFER, 0, arr.tostring())
  361. arr = array.array('I')
  362. arr.fromstring(mapping[fixfmtsz+sigfmtsz:])
  363. #print len(arr)
  364. arr.byteswap()
  365. glBindBuffer(GL_ARRAY_BUFFER, freq_buf)
  366. glBufferSubData(GL_ARRAY_BUFFER, 0, arr[::2].tostring())
  367. arr_fq = arr[::2]
  368. arr = array.array('f')
  369. arr.fromstring(mapping[fixfmtsz+sigfmtsz:])
  370. #print len(arr)
  371. arr.byteswap()
  372. glBindBuffer(GL_ARRAY_BUFFER, amp_buf)
  373. glBufferSubData(GL_ARRAY_BUFFER, 0, arr[1::2].tostring())
  374. arr_am = arr[1::2]
  375. #print len(arr_fq), len(arr_am)
  376. #print zip(arr_fq, arr_am)
  377. glBindFramebuffer(GL_READ_FRAMEBUFFER, fbs)
  378. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbd)
  379. glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bg_tex, 0)
  380. glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bg_swp, 0)
  381. stat = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)
  382. if stat != GL_FRAMEBUFFER_COMPLETE:
  383. print 'Incomplete read buffer:', stat
  384. stat = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
  385. if stat != GL_FRAMEBUFFER_COMPLETE:
  386. print 'Incomplete draw buffer:', stat
  387. glBlitFramebuffer(
  388. 1, 0, mode.size.width, mode.size.height,
  389. 0, 0, mode.size.width - 1, mode.size.height,
  390. GL_COLOR_BUFFER_BIT, GL_NEAREST
  391. )
  392. glBindFramebuffer(GL_FRAMEBUFFER, 0)
  393. bg_swp, bg_tex = bg_tex, bg_swp
  394. glBindTexture(GL_TEXTURE_2D, bg_tex)
  395. glTexSubImage2D(GL_TEXTURE_2D, 0, mode.size.width - 1, 0, 1, mode.size.height, GL_RED, GL_UNSIGNED_BYTE, clear_d)
  396. for f, a in zip(arr_fq, arr_am):
  397. if f == 0:
  398. continue
  399. try:
  400. pitch = 12 * math.log(f / 440.0, 2) + 69
  401. except ValueError:
  402. pitch = 0
  403. bg_bar_d = chr(int(255 * max((0.0, min((1.0, a)))))) * bg_bar_sz
  404. glTexSubImage2D(GL_TEXTURE_2D, 0, mode.size.width - 1, int(pitch * bar_pfac), 1, bg_bar_h, GL_RED, GL_UNSIGNED_BYTE, bg_bar_d)
  405. #print 'plot', mode.size.width - 1, int(pitch * bg_bar_h), 1, bg_bar_h, repr(bg_bar_d)
  406. #glTexSubImage2D(GL_TEXTURE_2D, 0, mode.size.width - 64, int(pitch * bg_bar_h), 64, 64, GL_RED, GL_UNSIGNED_BYTE, block_d)
  407. #glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 64, 64, GL_RED, GL_UNSIGNED_BYTE, block_d)
  408. #glTexSubImage2D(GL_TEXTURE_2D, 0, mode.size.width - 64, mode.size.height - 64, 64, 64, GL_RED, GL_UNSIGNED_BYTE, block_d)
  409. glActiveTexture(GL_TEXTURE0)
  410. glBindTexture(GL_TEXTURE_2D, 0)
  411. glUseProgram(prog_bg)
  412. glBindVertexArray(vao_bg)
  413. glDrawArrays(GL_TRIANGLES, 0, 6)
  414. glUseProgram(prog_bar)
  415. glBindVertexArray(vao_bar)
  416. glBindTexture(GL_TEXTURE_2D, bg_tex)
  417. #print bg_tex, bg_swp
  418. #print glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH), glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT)
  419. glEnable(GL_BLEND)
  420. glDrawArrays(GL_TRIANGLES, 0, 6)
  421. glDisable(GL_BLEND)
  422. glBindTexture(GL_TEXTURE_2D, 0)
  423. glUseProgram(prog_scope)
  424. glBindVertexArray(vao_scope)
  425. glDrawArrays(GL_LINE_STRIP, 0, options.map_samples)
  426. glfw.swap_buffers(win)
  427. glfw.poll_events()
  428. glfw.terminate()