render.py 18 KB

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