def draw_callback_px(self, context): if self.moves % 3 == 0 and len(self.colors) < 32: self.mouse_path.append(self.mouse_pos) view = get_viewport() x, y = self.mouse_pos c = bgl.Buffer(bgl.GL_FLOAT, 4) bgl.glReadPixels(x + view[0], y + view[1], 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, c) self.colors.append(c.to_list()) # 50% alpha, 2 pixel width line bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1, 1, 1, 0.5) bgl.glLineWidth(4) bgl.glBegin(bgl.GL_LINE_STRIP) for x, y in self.mouse_path: bgl.glVertex2i(x, y) bgl.glEnd() # restore opengl defaults bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
def as_image(self, x, y, w, h, image_name): import bpy buffer = bgl.Buffer(bgl.GL_FLOAT, w * h) # * 4) bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) check_error("glReadBuffer(bgl.GL_COLOR_ATTACHMENT0)") bgl.glReadPixels(x, y, w, h, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, buffer) check_error("glReadPixels as_image") if image_name not in bpy.data.images: image = bpy.data.images.new(image_name, w, h) else: image = bpy.data.images[image_name] #if image.size[:] != (w, h): image.scale(w, h) pix = [] for v in buffer: # pix.extend([v / self._offset_cur, 0, 0, 1]) pix.extend([v, 0, 0, 1]) image.pixels = pix # image.pixels = [v / 255 for v in buffer] image.update()
def screenshot(x, y, w, h, mode=bgl.GL_FRONT, type=bgl.GL_BYTE): """スクリーンショットを撮ってRGBAのfloatバッファを返す :param x: Window.x :type x: int :param y: Window.y :type y: int :param w: Window.width :type w: int :param h: Window.height :type h: int :param mode: 読み込み先 :type mode: int :param type: バッファの型。bgl.GL_BYTE, bgl.GL_INT, ... :type type: int :return: スクリーンショット。float RGBA :rtype: bgl.Buffer """ buf = bgl.Buffer(type, w * h * 4) mode_bak = bgl.Buffer(bgl.GL_INT, 1) bgl.glGetIntegerv(bgl.GL_READ_BUFFER, mode_bak) bgl.glReadBuffer(mode) bgl.glReadPixels(x, y, w, h, bgl.GL_RGBA, type, buf) bgl.glFinish() bgl.glReadBuffer(mode_bak[0]) return buf
def render_viewport(context, save_image_as_file=False, show_image=False): region = context.region x = region.x y = region.y width = region.width height = region.height out = prepare_blimage(width, height, Pref.blimgname) buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glReadPixels(x, y, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) out.pixels = buffer[:] if save_image_as_file: save_image(out, context.scene) if show_image: def set_imageeditor_image(): win = context.window for area_imeditor in [ area for area in win.screen.areas if area.type == 'IMAGE_EDITOR' ]: for s in [ s for s in area_imeditor.spaces if s.type == 'IMAGE_EDITOR' ]: s.image = out return set_imageeditor_image()
def render_view_offscreen(self, context): sv3d = context.space_data # backup settings and set them to render overlays_were = sv3d.overlay.show_overlays sv3d.overlay.show_overlays = False shading_was = sv3d.shading.type sv3d.shading.type = 'RENDERED' width = context.region.width height = context.region.height offscreen = GPUOffScreen(width, height) scene = context.scene view_matrix = context.region_data.view_matrix projection_matrix = context.region_data.window_matrix with offscreen.bind(): offscreen.draw_view3d(scene, context.view_layer, context.space_data, context.region, view_matrix, projection_matrix) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) offscreen.free() sv3d.overlay.show_overlays = overlays_were sv3d.shading.type = shading_was return list(buffer)
def render_offscreen(self, context, width, height, imgname=''): assert context.area.type == 'NODE_EDITOR' and context.space_data.tree_type == 'CompositorNodeTree' gos = gpu.offscreen.new(width,height) gos.bind(True) try: bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() bgl.glScalef(1/width*2,1/height*2,1.0) bgl.glTranslatef(-width/2,-height/2,0) draw_callback(self, context, { 'center': Vector((width/2, height/2)) , 'zoom': 1.0 , 'back_image_alpha': 1.0 , 'image_size': (width, height) }) buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) x,y = 0,0 bgl.glReadPixels(x, y, width, height , bgl.GL_RGBA, bgl.GL_FLOAT, buffer) out = prepare_blimage(width, height, imgname or Pref.default_output_image_name) out.pixels = buffer[:] finally: gos.unbind(True)
def read_zbuffer(xy, wh=(1, 1), centered=False, src=None): if isinstance(wh, (int, float)): wh = (wh, wh) elif len(wh) < 2: wh = (wh[0], wh[0]) x, y, w, h = int(xy[0]), int(xy[1]), int(wh[0]), int(wh[1]) if centered: x -= w // 2 y -= h // 2 buf_size = w*h if src is None: # xy is in window coordinates! zbuf = bgl.Buffer(bgl.GL_FLOAT, [buf_size]) bgl.glReadPixels(x, y, w, h, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, zbuf) else: src, w0, h0 = src template = [0.0] * buf_size for dy in range(h): y0 = min(max(y + dy, 0), h0-1) for dx in range(w): x0 = min(max(x + dx, 0), w0-1) i0 = x0 + y0 * w0 i1 = dx + dy * w template[i1] = src[i0] zbuf = bgl.Buffer(bgl.GL_FLOAT, [buf_size], template) return zbuf
def capture(self, mouse_x=None, mouse_y=None): time_diff() self.__update_size() time_diff("__update_size") bgl.glReadBuffer(bgl.GL_FRONT) time_diff("glReadBuffer") bgl.glReadPixels( 0, 0, self.width, self.height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, self.buffer, ) time_diff("glReadPixels") # self.image.pixels = [v / 255 for v in self.buffer] remapped_buffer = remap(self.buffer, self.remapping_indexes) time_diff("remap") self.image.pixels = [v / 255 for v in remapped_buffer] if mouse_x is not None and mouse_y is not None: draw_cursor(self.image, mouse_x / self.width * IMAGE_WIDTH, mouse_y / self.height * IMAGE_HEIGHT) time_diff("image.pixels")
def draw_scene(self, context, projection_matrix): bgl.glEnable(bgl.GL_DEPTH_TEST) bgl.glDepthFunc(bgl.GL_LESS) # Get List of Mesh Objects objs = [] deps = bpy.context.view_layer.depsgraph for obj_int in deps.object_instances: obj = obj_int.object if obj.type == 'MESH' and obj.hide_render == False: mat = obj_int.matrix_world obj_eval = obj.evaluated_get(deps) mesh = obj_eval.to_mesh(preserve_all_data_layers=True, depsgraph=bpy.context.view_layer.depsgraph) mesh.calc_loop_triangles() tris = mesh.loop_triangles vertices = [] indices = [] for vert in mesh.vertices: # Multipy vertex Position by Object Transform Matrix vertices.append(mat @ vert.co) for tri in tris: indices.append(tri.vertices) #shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') shader = gpu.types.GPUShader(Base_Shader_3D.vertex_shader, DepthOnlyFrag.fragment_shader) batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices) batch.program_set(shader) batch.draw() gpu.shader.unbind() obj_eval.to_mesh_clear() #Write to Image for Debug debug = False if debug: scene = context.scene render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) image_name = "measureit_arch_depth" if image_name not in bpy.data.images: bpy.data.images.new(image_name, width, height) image = bpy.data.images[image_name] image.scale(width, height) image.pixels = [v / 255 for v in buffer] bgl.glDisable(bgl.GL_DEPTH_TEST)
def modal(self, context, event): context.area.tag_redraw() if event.type == 'MOUSEMOVE' or event.type == 'INBETWEEN_MOUSEMOVE': if self.record: # note that we record the the mouse position relative to the window (not to the region) self.mouse_path.append((event.mouse_x, event.mouse_y)) elif event.type == 'LEFTMOUSE': if event.value == 'PRESS' and not self.record: self.record = True self.mouse_path.append((event.mouse_x, event.mouse_y)) else: # release or second press while recording # bpy.types.SpaceImageEditor.draw_handler_remove(self._handle, 'WINDOW') if self.cursor_set: context.window.cursor_modal_restore() # we can only have 32 elements in a color band so we have to down sample the mouse points nmp = len(self.mouse_path) if nmp > 32: d = (nmp // 32) + 1 self.mouse_path = self.mouse_path[::d] buf = bgl.Buffer(bgl.GL_FLOAT, [1, 3]) if len(self.mouse_path) == 1: self.mouse_path.append(self.mouse_path[0]) elements = context.active_object.active_material.node_tree.nodes.active.color_ramp.elements # remove all elements (setpoints). Last one cannot be removed while len(elements) > 1: elements.remove(elements[0]) # set the color and the position of the first point # note that our recorded mouse positions are relative to the window but the framebuffer in our context # is also the whole window, in other words we do not have to add any offset. # unfortunately we can only read pixels from our own framebuffer that means we cannot sample pixels # outside our current window, not even another Blender window! wx = 0 #context.window.x wy = 0 #context.window.y x, y = self.mouse_path[0] bgl.glReadPixels(x + wx, y + wy, 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, buf) e = elements[0] rgb = buf[0] e.color = (rgb[0], rgb[1], rgb[2], 1) e.position = 0.0 # set the color of the other points, spacing them evenly delta = 1.0 / (len(self.mouse_path) - 1) i = 0 for x, y in self.mouse_path[1:]: i += 1 bgl.glReadPixels(x + wx, y + wy, 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, buf) rgb = buf[0] e = elements.new(i * delta) e.color = (rgb[0], rgb[1], rgb[2], 1) return {'FINISHED'} elif event.type in {'RIGHTMOUSE', 'ESC'}: if self.cursor_set: context.window.cursor_modal_restore() return {'CANCELLED'} return {'RUNNING_MODAL'}
def getlum(): g.readL = 0 if hasattr(g,"initialized"): for j in range(SAMPLES): bgl.glReadPixels(int(g.xpoint[j]),int(g.ypoint[j]), 1, 1, bgl.GL_LUMINANCE, bgl.GL_FLOAT, pixels) g.readL += pixels[0] g.readL /= SAMPLES
def modal(self, context, event): context.area.tag_redraw() if event.type == "MOUSEMOVE" or event.type == "INBETWEEN_MOUSEMOVE": if self.record: # note that we record the the mouse position relative to the window (not to the region) self.mouse_path.append((event.mouse_x, event.mouse_y)) elif event.type == "LEFTMOUSE": if event.value == "PRESS" and not self.record: self.record = True self.mouse_path.append((event.mouse_x, event.mouse_y)) else: # release or second press while recording # bpy.types.SpaceImageEditor.draw_handler_remove(self._handle, 'WINDOW') if self.cursor_set: context.window.cursor_modal_restore() # we can only have 32 elements in a color band so we have to down sample the mouse points nmp = len(self.mouse_path) if nmp > 32: d = (nmp // 32) + 1 self.mouse_path = self.mouse_path[::d] buf = bgl.Buffer(bgl.GL_FLOAT, [1, 3]) if len(self.mouse_path) == 1: self.mouse_path.append(self.mouse_path[0]) elements = context.active_object.active_material.node_tree.nodes.active.color_ramp.elements # remove all elements (setpoints). Last one cannot be removed while len(elements) > 1: elements.remove(elements[0]) # set the color and the position of the first point # note that our recorded mouse positions are relative to the window but the framebuffer in our context # is also the whole window, in other words we do not have to add any offset. # unfortunately we can only read pixels from our own framebuffer that means we cannot sample pixels # outside our current window, not even another Blender window! wx = 0 # context.window.x wy = 0 # context.window.y x, y = self.mouse_path[0] bgl.glReadPixels(x + wx, y + wy, 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, buf) e = elements[0] rgb = buf[0] e.color = (rgb[0], rgb[1], rgb[2], 1) e.position = 0.0 # set the color of the other points, spacing them evenly delta = 1.0 / (len(self.mouse_path) - 1) i = 0 for x, y in self.mouse_path[1:]: i += 1 bgl.glReadPixels(x + wx, y + wy, 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, buf) rgb = buf[0] e = elements.new(i * delta) e.color = (rgb[0], rgb[1], rgb[2], 1) return {"FINISHED"} elif event.type in {"RIGHTMOUSE", "ESC"}: if self.cursor_set: context.window.cursor_modal_restore() return {"CANCELLED"} return {"RUNNING_MODAL"}
def read_zbuffer(xy, wh=(1, 1)): # xy is in window coordinates! if isinstance(wh, (int, float)): wh = (wh, wh) elif len(wh) < 2: wh = (wh[0], wh[0]) x, y, w, h = int(xy[0]), int(xy[1]), int(wh[0]), int(wh[1]) zbuf = bgl.Buffer(bgl.GL_FLOAT, [w*h]) bgl.glReadPixels(x, y, w, h, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, zbuf) return zbuf
def read_zbuffer(xy, wh=(1, 1)): # xy is in window coordinates! if isinstance(wh, (int, float)): wh = (wh, wh) elif len(wh) < 2: wh = (wh[0], wh[0]) x, y, w, h = int(xy[0]), int(xy[1]), int(wh[0]), int(wh[1]) zbuf = bgl.Buffer(bgl.GL_FLOAT, [w * h]) bgl.glReadPixels(x, y, w, h, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, zbuf) return zbuf
def render_debug_cross(context, props: MasterProperties) -> (bgl.Buffer, int): """ Render debug cross :returns buffer with image and draw call count """ shaders = Shaders() offscreen = gpu.types.GPUOffScreen(props.resolution.resolution_x, props.resolution.resolution_y) draw_count = 0 quad_batch = batch_quad(shaders.debug) with offscreen.bind(): # black background bgl.glClearColor(0.0, 0.0, 0.0, 1.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) bgl.glEnable(bgl.GL_BLEND) bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE) shaders.debug.bind() for position in props.positions: pos = Vector((position.manual_x, position.manual_y)) # set position from object if position.variant == 'auto' and position.auto_object is not None: world_pos = position.auto_object.matrix_world.to_translation() pos = bpy_extras.object_utils.world_to_camera_view( context.scene, context.scene.camera, world_pos) uniforms = { "flare_position": pos.xy, "aspect_ratio": props.resolution.resolution_x / props.resolution.resolution_y, } set_float_uniforms(shaders.debug, uniforms) quad_batch.draw(shaders.debug) draw_count += 1 # copy rendered image to RAM buffer = bgl.Buffer( bgl.GL_FLOAT, props.resolution.resolution_x * props.resolution.resolution_y * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, props.resolution.resolution_x, props.resolution.resolution_y, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) return buffer, draw_count
def get_image(self): """ sends serialized image, uint8 image """ _buffer = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, _buffer) bgl.glReadBuffer(bgl.GL_FRONT) pix = bgl.Buffer(bgl.GL_INT, _buffer[2] * _buffer[3]) bgl.glReadPixels(_buffer[0], _buffer[1], _buffer[2], _buffer[3], bgl.GL_LUMINANCE, bgl.GL_INT, pix) array = numpy.zeros((self.screen_w * self.screen_h), dtype=numpy.uint8) array[0:self.screen_w * self.screen_h] = pix self.get_data((self.screen_w, self.screen_h)) for i in range(0, len(array), 400): self.get_data(array[i:i + 400])
def _read_buffer(self, mval): xmin = int(mval[0]) - self._dist_px ymin = int(mval[1]) - self._dist_px size_x = size_y = self.threshold if xmin < 0: #size_x += xmin xmin = 0 if ymin < 0: #size_y += ymin ymin = 0 bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadPixels(xmin, ymin, size_x, size_y, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, self._snap_buffer)
def modal(self, context, event): if ((event.type in {'RIGHTMOUSE', 'ESC'}) or (event.type == 'LEFTMOUSE' and event.value == 'RELEASE')): context.area.header_text_set() context.window.cursor_modal_restore() context.area.tag_redraw() return {'CANCELLED'} elif (event.type in {'LEFTMOUSE', 'MOUSEMOVE'} and event.value == 'PRESS'): bgl.glReadPixels(event.mouse_x, event.mouse_y, 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, self.buf) t = "{c[0]:.3f},{c[1]:.3f},{c[2]:.3f}".format(c=self.buf[0]) context.area.header_text_set(t) context.area.tag_redraw() return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def render(self, dg): scene = dg.scene scale = scene.render.resolution_percentage / 100.0 width = int(scene.render.resolution_x * scale) height = int(scene.render.resolution_y * scale) zu.blen_gl_enable() try: # Create drawing target self.genfb(width, height) # Prep Zu scene self.scene = zu.scene_new() view_mat = self.camera_model_matrix(scene.camera) view_mat.invert() win_mat = scene.camera.calc_matrix_camera(dg, x=width, y=height) cam = win_mat @ view_mat zu.scene_cam(self.scene, mat(cam)) self.load_dg(dg) # Render bgl.glViewport(0, 0, width, height) zu.scene_draw(self.scene, self.fb) # Retrieve texture data pixels = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, pixels) # Copy pixel data to output result = self.begin_result(0, 0, width, height) layer = result.layers[0].passes["Combined"] pixels = pixels.to_list() layer.rect = list( zip(*[pixels[i::4] for i in range(4)])) # FIXME: holy f**k this is slow self.end_result(result) finally: del self.objects self.objects = None del self.scene self.scene = None bgl.glBindFramebuffer(bgl.GL_FRAMEBUFFER, 0) self.delfb() zu.blen_gl_disable()
def render_opengl_image(image_name, cam, point_size): draw_manager = DrawManager.get_singleton() coords, colors = draw_manager.get_coords_and_colors() scene = bpy.context.scene render = bpy.context.scene.render width = render.resolution_x height = render.resolution_y # TODO Provide an option to render from the 3D view perspective # width = bpy.context.region.width # height = bpy.context.region.height offscreen = gpu.types.GPUOffScreen(width, height) with offscreen.bind(): bgl.glPointSize(point_size) bgl.glEnable(bgl.GL_DEPTH_TEST) # bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) view_matrix = cam.matrix_world.inverted() projection_matrix = cam.calc_matrix_camera( bpy.context.evaluated_depsgraph_get(), x=width, y=height ) perspective_matrix = projection_matrix @ view_matrix gpu.matrix.load_matrix(perspective_matrix) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) shader = gpu.shader.from_builtin("3D_FLAT_COLOR") shader.bind() batch = batch_for_shader( shader, "POINTS", {"pos": coords, "color": colors} ) batch.draw(shader) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadPixels( 0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer ) offscreen.free() image = create_image_lazy(image_name, width, height) copy_buffer_to_pixel(buffer, image)
def ReadOutDepthMap(): global HarambePointer global b global pix start_time = time.time() # select the front buffer (the game window) bgl.glReadPixels(b[0], b[1], b[2], b[3], bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, pix) jj = (ctypes.c_float * len(pix))() jj[:] = pix kfj = ctypes.pointer(jj) WriteDepthMapBufFile(ctypes.c_void_p(HarambePointer), kfj, len(jj)) print("--- %s seconds ---" % (time.time() - start_time))
def capture_under_cursor(buffer, mouse_x=0, mouse_y=0, type_flg="i") -> list: """ フラットなrgba(float)のlistを返す """ # GL_FLOATでバッファ作って読むと馬鹿みたいに重いのでGL_BYTE,GL_UNSIGNED_BYTEになってる bgl.glReadBuffer(bgl.GL_FRONT) bgl.glReadPixels( mouse_x, mouse_y, 1, 1, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer, ) if type_flg == "i": return [value for value in buffer] elif type_flg == "f": return [value / 255 for value in buffer]
def gen_screenshot_texture(x, y, w, h, mode=None): scissor_is_enabled = bgl.Buffer(bgl.GL_BYTE, 1) bgl.glGetIntegerv(bgl.GL_SCISSOR_TEST, scissor_is_enabled) scissor_box = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_SCISSOR_BOX, scissor_box) bgl.glEnable(bgl.GL_SCISSOR_TEST) bgl.glScissor(x, y, w, h) mode_bak = bgl.Buffer(bgl.GL_INT, 1) bgl.glGetIntegerv(bgl.GL_READ_BUFFER, mode_bak) if mode is not None: bgl.glReadBuffer(mode) pixels = bgl.Buffer(bgl.GL_BYTE, 4 * w * h) # RGBAにしないと斜めになる # GL_UNSIGNED_BYTEでないと色が僅かにずれる bgl.glReadPixels(x, y, w, h, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, pixels) bgl.glFinish() if mode is not None: bgl.glReadBuffer(mode_bak[0]) # 反転。確認用 # for i in range(4 * w * h): # if (i % 4) != 3: # pixels[i] = 255 - pixels[i] tex = gen_texture() bgl.glBindTexture(bgl.GL_TEXTURE_2D, tex) bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, w, h, 0, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, pixels) bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0) if not scissor_is_enabled[0]: bgl.glDisable(bgl.GL_SCISSOR_TEST) bgl.glScissor(*scissor_box) return tex
def perform_gpu_test(frag_source, cpu_func): grid = accel.HashedGrid(3) assert grid is not None hash_grid_glsl = gpu_utils.load_shader_file("gridhash", "def") shader = gpu.types.GPUShader(vert_source, frag_source, libcode=hash_grid_glsl) screen_size = 128 offscreen = gpu.types.GPUOffScreen(screen_size, screen_size) points = [[-1, -1], [-1, 1], [1, 1], [1, -1]] indices = ((0, 1, 2), (2, 3, 0)) batch = gpu_extras.batch.batch_for_shader(shader, "TRIS", {'pos': points}, indices=indices) for z in range(-5, 5): gpu_hashes = [] with offscreen.bind(): shader.uniform_int('z', z) shader.uniform_int('screen_size', screen_size) batch.draw(shader) # Starting from blender 3.0 we can: # fb = gpu.state.active_framebuffer_get() # buffer = fb.read_color(0,0, screen_size, screen_size, 4, 0, UBYTE) buffer = bgl.Buffer(bgl.GL_BYTE, screen_size * screen_size * 4) bgl.glReadPixels(0, 0, screen_size, screen_size, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) x = buffer[:] gpu_hashes = [ a + 256 * (b + 256 * (c + 256 * d)) for a, b, c, d in zip(x[::4], x[1::4], x[2::4], x[3::4]) ] i = 0 for y in range(-screen_size // 2, screen_size // 2): for x in range(-screen_size // 2, screen_size // 2): cpu_hash = cpu_func(grid, [x, y, z]) assert gpu_hashes[i] == cpu_hash i += 1
def drawCallback(self, context): # use ImageTexture.evaluate / get Image.pixels in case of View2D? # seems unnecessary to restore afterwards. bgl.glViewport(*self.viewport) bgl.glScissor(*self.viewport) b = bgl.Buffer(bgl.GL_FLOAT, 3) for p in itertools.chain(self.points, self.current_mouse_points): bgl.glReadPixels(p[0], p[1], 1, 1, bgl.GL_RGB, bgl.GL_FLOAT, b) p[-1] = self.convertColorspace(context, b.to_list()) points_drawn = 0 max_points_to_draw = PTS_LIMIT - self.remaining last_point_drawn = None for p in self.points: if points_drawn == max_points_to_draw: break self.drawPoint(*p[2:5]) last_point_drawn = p points_drawn += 1 # under cursor -> probably not wanted for p in self.current_mouse_points[:-1]: if points_drawn == max_points_to_draw: break self.drawPoint(*p[2:5]) last_point_drawn = p points_drawn += 1 segments_drawn = 0 if len(self.points) > 1: ps = iter(self.points) next(ps) for p1, p2 in zip(self.points, ps): if segments_drawn == max_points_to_draw - 1: break self.drawSegment(p1[2], p1[3], p2[2], p2[3], False) segments_drawn += 1 if self.current_mouse_points: p1 = self.points[-1] p2 = self.current_mouse_points[0] if segments_drawn < max_points_to_draw - 1: self.drawSegment(p1[2], p1[3], p2[2], p2[3], True) segments_drawn += 1 if len(self.current_mouse_points) > 1: ps = iter(self.current_mouse_points) next(ps) for p1, p2 in zip(self.current_mouse_points, ps): if segments_drawn == max_points_to_draw - 1: break self.drawSegment(p1[2], p1[3], p2[2], p2[3], True) segments_drawn += 1 if points_drawn == max_points_to_draw: # this means even the point under the cursor _is_ already # surnumerary, thus we have to draw the last segment in red if self.current_mouse_points: p1 = last_point_drawn p2 = self.current_mouse_points[-1] self.drawSegment(p1[2], p1[3], p2[2], p2[3], True, True) if context.window_manager.crd_show_values: for p, i in zip(itertools.chain(self.points, self.current_mouse_points), range(points_drawn)): blf.position(0, p[2] + 10, p[3] - 10, 0) bgl.glColor4f(0.8, 0.8, 0.8, 1.0) blf.size(0, 10, context.user_preferences.system.dpi) blf.draw(0, "(%.3f, %.3f, %.3f)" % tuple(p[-1])) if points_drawn <= max_points_to_draw: # we want to draw the current color anyways if self.current_mouse_points: p = self.current_mouse_points[-1] blf.position(0, p[2] + 10, p[3] - 10, 0) bgl.glColor4f(0.8, 0.8, 0.8, 1.0) blf.size(0, 10, context.user_preferences.system.dpi) blf.draw(0, "(%.3f, %.3f, %.3f)" % tuple(p[-1])) bgl.glColor4f(0.8, 0.8, 0.8, 1.0) blf.size(0, 20, context.user_preferences.system.dpi) if context.window_manager.crd_use_intermediate: blf.position(0, 10, 60, 0) blf.draw(0, "Oversamples:") blf.position(0, 160, 60, 0) blf.draw(0, str(context.window_manager.crd_intermediate_amount)) blf.position(0, 10, 30, 0) blf.draw(0, "Path Type:") blf.position(0, 160, 30, 0) blf.draw(0, {"POLYLINE": "Polyline", "CUBIC_SPLINE": "Cubic Spline"}[context.window_manager.crd_path_type])
def render_main(self, context, animation=False): # Save old info settings = bpy.context.scene.render.image_settings depth = settings.color_depth settings.color_depth = '8' # Get object list scene = context.scene objlist = context.scene.objects # -------------------- # Get resolution # -------------------- render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) # -------------------------------------- # Loop to draw all lines in Offsecreen # -------------------------------------- offscreen = gpu.types.GPUOffScreen(width, height) view_matrix = Matrix([[2 / width, 0, 0, -1], [0, 2 / height, 0, -1], [0, 0, 1, 0], [0, 0, 0, 1]]) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) # ----------------------------- # Loop to draw all objects # ----------------------------- for myobj in objlist: if myobj.visible_get() is True: if 'MeasureGenerator' in myobj: op = myobj.MeasureGenerator[0] draw_segments(context, myobj, op, None, None) # ----------------------------- # Loop to draw all debug # ----------------------------- if scene.measureit_debug is True: selobj = bpy.context.selected_objects for myobj in selobj: if scene.measureit_debug_objects is True: draw_object(context, myobj, None, None) elif scene.measureit_debug_object_loc is True: draw_object(context, myobj, None, None) if scene.measureit_debug_vertices is True: draw_vertices(context, myobj, None, None) elif scene.measureit_debug_vert_loc is True: draw_vertices(context, myobj, None, None) if scene.measureit_debug_edges is True: draw_edges(context, myobj, None, None) if scene.measureit_debug_faces is True or scene.measureit_debug_normals is True: draw_faces(context, myobj, None, None) # ----------------------------- # Draw a rectangle frame # ----------------------------- if scene.measureit_rf is True: rfcolor = scene.measureit_rf_color rfborder = scene.measureit_rf_border rfline = scene.measureit_rf_line bgl.glLineWidth(rfline) x1 = rfborder x2 = width - rfborder y1 = int(ceil(rfborder / (width / height))) y2 = height - y1 draw_rectangle((x1, y1), (x2, y2), rfcolor) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) offscreen.free() # ----------------------------- # Create image # ----------------------------- image_name = "measureit_output" if not image_name in bpy.data.images: bpy.data.images.new(image_name, width, height) image = bpy.data.images[image_name] image.scale(width, height) image.pixels = [v / 255 for v in buffer] # Saves image if image is not None and (scene.measureit_render is True or animation is True): ren_path = bpy.context.scene.render.filepath filename = "mit_frame" if len(ren_path) > 0: if ren_path.endswith(path.sep): initpath = path.realpath(ren_path) + path.sep else: (initpath, filename) = path.split(ren_path) ftxt = "%04d" % scene.frame_current outpath = path.realpath(path.join(initpath, filename + ftxt + ".png")) save_image(self, outpath, image) # restore default value settings.color_depth = depth
def render_opengl(self, context): from math import ceil layers = [] scene = context.scene for x in range(0, 20): if scene.layers[x] is True: layers.extend([x]) objlist = context.scene.objects render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) # I cant use file_format becuase the pdf writer needs jpg format # the file_format returns 'JPEG' not 'JPG' # file_format = context.scene.render.image_settings.file_format.lower() ren_path = bpy.path.abspath(bpy.context.scene.render.filepath) + ".jpg" # if len(ren_path) > 0: # if ren_path.endswith(os.path.sep): # initpath = os.path.realpath(ren_path) + os.path.sep # else: # (initpath, filename) = os.path.split(ren_path) # outpath = os.path.join(initpath, "ogl_tmp.png") # else: # self.report({'ERROR'}, "Invalid render path") # return False img = get_render_image(ren_path) if img is None: self.report({'ERROR'}, "Invalid render path:" + ren_path) return False tile_x = 240 tile_y = 216 row_num = ceil(height / tile_y) col_num = ceil(width / tile_x) cut4 = (col_num * tile_x * 4) - width * 4 totpixel4 = width * height * 4 viewport_info = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport_info) img.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST) # 2.77 API change if bpy.app.version >= (2, 77, 0): tex = img.bindcode[0] else: tex = img.bindcode if context.scene.name in bpy.data.images: old_img = bpy.data.images[context.scene.name] old_img.user_clear() bpy.data.images.remove(old_img) img_result = bpy.data.images.new(context.scene.name, width, height) tmp_pixels = [1] * totpixel4 #---------- Loop for all tiles for row in range(0, row_num): for col in range(0, col_num): buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glDisable( bgl.GL_SCISSOR_TEST ) # if remove this line, get blender screenshot not image bgl.glViewport(0, 0, tile_x, tile_y) bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() # defines ortographic view for single tile x1 = tile_x * col y1 = tile_y * row bgl.gluOrtho2D(x1, x1 + tile_x, y1, y1 + tile_y) # Clear bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) bgl.glEnable(bgl.GL_TEXTURE_2D) bgl.glBindTexture(bgl.GL_TEXTURE_2D, tex) # defines drawing area bgl.glBegin(bgl.GL_QUADS) bgl.glColor3f(1.0, 1.0, 1.0) bgl.glTexCoord2f(0.0, 0.0) bgl.glVertex2f(0.0, 0.0) bgl.glTexCoord2f(1.0, 0.0) bgl.glVertex2f(width, 0.0) bgl.glTexCoord2f(1.0, 1.0) bgl.glVertex2f(width, height) bgl.glTexCoord2f(0.0, 1.0) bgl.glVertex2f(0.0, height) bgl.glEnd() for obj in objlist: if obj.mv.type == 'VISDIM_A': for x in range(0, 20): if obj.layers[x] is True: if x in layers: opengl_dim = obj.mv.opengl_dim if not opengl_dim.hide: draw_dimensions(context, obj, opengl_dim, None, None) break #---------- copy pixels to temporary area bgl.glFinish() bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # read image data for y in range(0, tile_y): # final image pixels position p1 = (y * width * 4) + (row * tile_y * width * 4) + (col * tile_x * 4) p2 = p1 + (tile_x * 4) # buffer pixels position b1 = y * width * 4 b2 = b1 + (tile_x * 4) if p1 < totpixel4: # avoid pixel row out of area if col == col_num - 1: # avoid pixel columns out of area p2 -= cut4 b2 -= cut4 tmp_pixels[p1:p2] = buffer[b1:b2] img_result.pixels = tmp_pixels[:] img.gl_free() img.user_clear() bpy.data.images.remove(img) os.remove(ren_path) bgl.glEnable(bgl.GL_SCISSOR_TEST) #---------- restore opengl defaults bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 0.0, 1.0) if img_result is not None: return img_result
def snap_get(self, mval, main_snap_obj = None): ret = None, None, None self.mval[:] = mval snap_vert = self._snap_mode & VERT != 0 snap_edge = self._snap_mode & EDGE != 0 snap_face = self._snap_mode & FACE != 0 _Internal.gpu_Indices_enable_state() self._offscreen.bind() #bgl.glDisable(bgl.GL_DITHER) # dithering and AA break color coding, so disable # #multisample_enabled = bgl.glIsEnabled(bgl.GL_MULTISAMPLE) #bgl.glDisable(bgl.GL_MULTISAMPLE) bgl.glEnable(bgl.GL_DEPTH_TEST) proj_mat = self.rv3d.perspective_matrix.copy() if self.proj_mat != proj_mat: self.proj_mat = proj_mat _Internal.gpu_Indices_set_ProjectionMatrix(self.proj_mat) self.update_drawing() ray_dir, ray_orig = self.get_ray(mval) for i, snap_obj in enumerate(self.snap_objects[self.drawn_count:], self.drawn_count): obj = snap_obj.data[0] try: bbmin = Vector(obj.bound_box[0]) bbmax = Vector(obj.bound_box[6]) except ReferenceError: self.snap_objects.remove(snap_obj) continue if bbmin != bbmax: MVP = proj_mat @ snap_obj.mat mat_inv = snap_obj.mat.inverted() ray_orig_local = mat_inv @ ray_orig ray_dir_local = mat_inv.to_3x3() @ ray_dir in_threshold = _Internal.intersect_boundbox_threshold( self, MVP, ray_orig_local, ray_dir_local, bbmin, bbmax) else: proj_co = _Internal.project_co_v3(self, snap_obj.mat.translation) dist = self.mval - proj_co in_threshold = abs(dist.x) < self._dist_px and abs(dist.y) < self._dist_px #snap_obj.data[1] = primitive_point if in_threshold: if len(snap_obj.data) == 1: from .mesh_drawing import GPU_Indices_Mesh is_bound = obj.display_type == 'BOUNDS' draw_face = snap_face and not is_bound and obj.display_type != 'WIRE' draw_edge = snap_edge and not is_bound draw_vert = snap_vert and not is_bound snap_obj.data.append(GPU_Indices_Mesh(self.depsgraph, obj, draw_face, draw_edge, draw_vert)) snap_obj.data[1].set_draw_mode(snap_face, snap_edge, snap_vert) snap_obj.data[1].set_ModelViewMatrix(snap_obj.mat) if snap_obj == main_snap_obj: snap_obj.data[1].Draw(self._offset_cur, -0.0001) else: snap_obj.data[1].Draw(self._offset_cur) self._offset_cur += snap_obj.data[1].get_tot_elems() tmp = self.snap_objects[self.drawn_count] self.snap_objects[self.drawn_count] = self.snap_objects[i] self.snap_objects[i] = tmp self.drawn_count += 1 bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadPixels( int(self.mval[0]) - self._dist_px, int(self.mval[1]) - self._dist_px, self.threshold, self.threshold, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, self._snap_buffer) #bgl.glReadBuffer(bgl.GL_BACK) #import numpy as np #a = np.array(self._snap_buffer) #print(a) snap_obj, index = self._get_nearest_index() #print("index:", index) if snap_obj: ret = self._get_loc(snap_obj, index) bgl.glDisable(bgl.GL_DEPTH_TEST) self._offscreen.unbind() _Internal.gpu_Indices_restore_state() return (snap_obj, *ret)
def render_lens_flare(context, props: MasterProperties) -> (bgl.Buffer, int): """ Renders lens flare effect to buffer :returns buffer with effect """ max_x = props.resolution.resolution_x max_y = props.resolution.resolution_y # render kinda circles blades = props.camera.blades if blades == 0: blades = 256 shaders = Shaders() offscreen = gpu.types.GPUOffScreen(max_x, max_y) ghost_fb = gpu.types.GPUOffScreen(max_x, max_y) ghost_batch = batch_from_blades(blades, shaders.ghost) quad_batch = batch_quad(shaders.flare) draw_count = 0 noise_tex = NoiseTexture() # clear framebuffer with offscreen.bind(): # black background bgl.glClearColor(0.0, 0.0, 0.0, 1.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) bgl.glEnable(bgl.GL_BLEND) bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE) for position in props.positions: pos = Vector((position.manual_x, position.manual_y)) # set position from object if position.variant == 'auto' and position.auto_object is not None: world_pos = position.auto_object.matrix_world.to_translation() pos = bpy_extras.object_utils.world_to_camera_view( context.scene, context.scene.camera, world_pos) flare_vector = pos.xy - Vector((0.5, 0.5)) flare_vector.normalize() # first render ghosts one by one for ghost in props.ghosts: # calculate position ghost_x = ((pos.x - 0.5) * 2.0) * ghost.offset ghost_y = ((pos.y - 0.5) * 2.0) * ghost.offset # add perpendicular offset ghost_x += flare_vector.y * ghost.perpendicular_offset ghost_y += -flare_vector.x * ghost.perpendicular_offset with ghost_fb.bind(): render_ghost(props, ghost, shaders.ghost, ghost_batch, flare_vector, pos) draw_count += 1 with offscreen.bind(): # now copy to final buffer bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, ghost_fb.color_texture) # disable wrapping bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_BORDER) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_BORDER) border_color = bgl.Buffer(bgl.GL_FLOAT, 4, [0.0, 0.0, 0.0, 1.0]) bgl.glTexParameterfv(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_BORDER_COLOR, border_color) bgl.glActiveTexture(bgl.GL_TEXTURE2) bgl.glBindTexture(bgl.GL_TEXTURE_2D, props.spectrum_image.bindcode) bgl.glActiveTexture(bgl.GL_TEXTURE1) bgl.glBindTexture(bgl.GL_TEXTURE_2D, noise_tex.gl_code) copy_ghost(shaders.copy, quad_batch, ghost, props, Vector((ghost_x, ghost_y))) draw_count += 1 # finally render flare on top with offscreen.bind(): bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, noise_tex.gl_code) render_flare(props, pos.xy, shaders.flare, quad_batch) draw_count += 1 with offscreen.bind(): # copy rendered image to RAM buffer = bgl.Buffer(bgl.GL_FLOAT, max_x * max_y * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, max_x, max_y, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) offscreen.free() ghost_fb.free() noise_tex.free() return buffer, draw_count
def render_main(self, context, animation=False): # noinspection PyBroadException,PyBroadException try: # Get visible layers layers = [] scene = context.scene for x in range(0, 20): if scene.layers[x] is True: layers.extend([x]) # Get object list objlist = context.scene.objects # -------------------- # Get resolution # -------------------- scene = bpy.context.scene render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) # --------------------------------------- # Get output path # --------------------------------------- ren_path = bpy.context.scene.render.filepath if len(ren_path) > 0: if ren_path.endswith(os.path.sep): initpath = os.path.realpath(ren_path) + os.path.sep else: (initpath, filename) = os.path.split(ren_path) outpath = os.path.join(initpath, "measureit_tmp_render.png") else: self.report({'ERROR'}, "MeasureIt: Unable to save temporary render image. Define a valid render path") return False # Get Render Image img = get_render_image(outpath) if img is None: self.report({'ERROR'}, "MeasureIt: Unable to save temporary render image. Define a valid render path") return False # ----------------------------- # Calculate rows and columns # ----------------------------- tile_x = 240 tile_y = 216 row_num = ceil(height / tile_y) col_num = ceil(width / tile_x) print("MeasureIt: Image divided in " + str(row_num) + "x" + str(col_num) + " tiles") # pixels out of visible area cut4 = (col_num * tile_x * 4) - width * 4 # pixels aout of drawing area totpixel4 = width * height * 4 # total pixels RGBA viewport_info = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport_info) # Load image on memory img.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST) tex = img.bindcode # -------------------------------------------- # Create output image (to apply texture) # -------------------------------------------- if "measureit_output" in bpy.data.images: out_img = bpy.data.images["measureit_output"] if out_img is not None: out_img.user_clear() bpy.data.images.remove(out_img) out = bpy.data.images.new("measureit_output", width, height) tmp_pixels = [1] * totpixel4 # -------------------------------- # Loop for all tiles # -------------------------------- for row in range(0, row_num): for col in range(0, col_num): buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glDisable(bgl.GL_SCISSOR_TEST) # if remove this line, get blender screenshot not image bgl.glViewport(0, 0, tile_x, tile_y) bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() # defines ortographic view for single tile x1 = tile_x * col y1 = tile_y * row bgl.gluOrtho2D(x1, x1 + tile_x, y1, y1 + tile_y) # Clear bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) bgl.glEnable(bgl.GL_TEXTURE_2D) bgl.glBindTexture(bgl.GL_TEXTURE_2D, tex) # defines drawing area bgl.glBegin(bgl.GL_QUADS) bgl.glColor3f(1.0, 1.0, 1.0) bgl.glTexCoord2f(0.0, 0.0) bgl.glVertex2f(0.0, 0.0) bgl.glTexCoord2f(1.0, 0.0) bgl.glVertex2f(width, 0.0) bgl.glTexCoord2f(1.0, 1.0) bgl.glVertex2f(width, height) bgl.glTexCoord2f(0.0, 1.0) bgl.glVertex2f(0.0, height) bgl.glEnd() # ----------------------------- # Loop to draw all lines # ----------------------------- for myobj in objlist: if myobj.hide is False: if 'MeasureGenerator' in myobj: # verify visible layer for x in range(0, 20): if myobj.layers[x] is True: if x in layers: op = myobj.MeasureGenerator[0] draw_segments(context, myobj, op, None, None) break if scene.measureit_rf is True: bgl.glColor3f(1.0, 1.0, 1.0) rfcolor = scene.measureit_rf_color rfborder = scene.measureit_rf_border rfline = scene.measureit_rf_line bgl.glLineWidth(rfline) bgl.glColor4f(rfcolor[0], rfcolor[1], rfcolor[2], rfcolor[3]) x1 = rfborder x2 = width - rfborder y1 = int(math.ceil(rfborder / (width / height))) y2 = height - y1 draw_rectangle((x1, y1), (x2, y2)) # -------------------------------- # copy pixels to temporary area # -------------------------------- bgl.glFinish() bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # read image data for y in range(0, tile_y): # final image pixels position p1 = (y * width * 4) + (row * tile_y * width * 4) + (col * tile_x * 4) p2 = p1 + (tile_x * 4) # buffer pixels position b1 = y * width * 4 b2 = b1 + (tile_x * 4) if p1 < totpixel4: # avoid pixel row out of area if col == col_num - 1: # avoid pixel columns out of area p2 -= cut4 b2 -= cut4 tmp_pixels[p1:p2] = buffer[b1:b2] # ----------------------- # Copy temporary to final # ----------------------- out.pixels = tmp_pixels[:] # Assign image data img.gl_free() # free opengl image memory # delete image img.user_clear() bpy.data.images.remove(img) # remove temp file os.remove(outpath) # reset bgl.glEnable(bgl.GL_SCISSOR_TEST) # ----------------------- # restore opengl defaults # ----------------------- bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 0.0, 1.0) # Saves image if out is not None and (scene.measureit_render is True or animation is True): ren_path = bpy.context.scene.render.filepath filename = "mit_frame" if len(ren_path) > 0: if ren_path.endswith(os.path.sep): initpath = os.path.realpath(ren_path) + os.path.sep else: (initpath, filename) = os.path.split(ren_path) ftxt = "%04d" % scene.frame_current outpath = os.path.join(initpath, filename + ftxt + ".png") save_image(self, outpath, out) return True except: print("Unexpected error:" + str(sys.exc_info())) self.report({'ERROR'}, "MeasureIt: Unable to create render image") return False
def render_main_svg(self, context, animation=False): # Save old info scene = context.scene sceneProps= scene.MeasureItArchProps sceneProps.is_render_draw = True sceneProps.is_vector_draw = True clipdepth = context.scene.camera.data.clip_end path = scene.render.filepath objlist = context.view_layer.objects # -------------------- # Get resolution # -------------------- render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) offscreen = gpu.types.GPUOffScreen(width, height) view_matrix_3d = scene.camera.matrix_world.inverted() projection_matrix = scene.camera.calc_matrix_camera(context.view_layer.depsgraph, x=width, y=height) # Render Depth Buffer with offscreen.bind(): # Clear Depth Buffer, set Clear Depth to Cameras Clip Distance bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) bgl.glClearDepth(clipdepth) bgl.glEnable(bgl.GL_DEPTH_TEST) bgl.glDepthFunc(bgl.GL_LEQUAL) gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix_3d) gpu.matrix.load_projection_matrix(projection_matrix) texture_buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) draw_scene(self, context, projection_matrix) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, texture_buffer) if 'depthbuffer' in sceneProps: del sceneProps['depthbuffer'] sceneProps['depthbuffer'] = texture_buffer offscreen.free() if True: if not str('test') in bpy.data.images: bpy.data.images.new(str('test'), width, height) image = bpy.data.images[str('test')] image.scale(width, height) image.pixels = [v / 255 for v in texture_buffer] # Setup Output Path ren_path = bpy.context.scene.render.filepath filename = "mit_vector" ftxt = "%04d" % scene.frame_current outpath = (ren_path + filename + ftxt + '.svg') # Setup basic svg svg = svgwrite.Drawing( outpath, debug=False, size=('{}mm'.format(width), '{}mm'.format(height)), viewBox=('0 0 {} {}'.format(width,height)), id='root', ) # ----------------------------- # Loop to draw all objects # ----------------------------- for myobj in objlist: if myobj.visible_get() is True: mat = myobj.matrix_world if 'DimensionGenerator' in myobj: measureGen = myobj.DimensionGenerator[0] if 'alignedDimensions' in measureGen: for linDim in measureGen.alignedDimensions: draw_alignedDimension(context, myobj, measureGen,linDim,mat,svg=svg) if 'angleDimensions' in measureGen: for dim in measureGen.angleDimensions: draw_angleDimension(context, myobj, measureGen,dim,mat,svg=svg) if 'axisDimensions' in measureGen: for dim in measureGen.axisDimensions: draw_axisDimension(context, myobj, measureGen,dim,mat,svg=svg) if 'boundsDimensions' in measureGen: for dim in measureGen.boundsDimensions: draw_boundsDimension(context, myobj, measureGen,dim,mat,svg=svg) if 'arcDimensions' in measureGen: for dim in measureGen.arcDimensions: draw_arcDimension(context, myobj, measureGen,dim,mat,svg=svg) if 'areaDimensions' in measureGen: for dim in measureGen.areaDimensions: draw_areaDimension(context, myobj, measureGen,dim,mat,svg=svg) if 'LineGenerator' in myobj: # Draw Line Groups op = myobj.LineGenerator[0] draw_line_group(context, myobj, op, mat,svg=svg) #if 'AnnotationGenerator' in myobj: # op = myobj.AnnotationGenerator[0] # draw_annotation(context, myobj, op, mat) if False: # Draw Instance deps = bpy.context.view_layer.depsgraph for obj_int in deps.object_instances: if obj_int.is_instance: myobj = obj_int.object mat = obj_int.matrix_world if 'LineGenerator' in myobj: lineGen = myobj.LineGenerator[0] draw_line_group(context,myobj,lineGen,mat) if sceneProps.instance_dims: if 'AnnotationGenerator' in myobj: annotationGen = myobj.AnnotationGenerator[0] draw_annotation(context,myobj,annotationGen,mat) if 'DimensionGenerator' in myobj: DimGen = myobj.DimensionGenerator[0] for alignedDim in DimGen.alignedDimensions: draw_alignedDimension(context, myobj, DimGen, alignedDim,mat) for angleDim in DimGen.angleDimensions: draw_angleDimension(context, myobj, DimGen, angleDim,mat) for axisDim in DimGen.axisDimensions: draw_axisDimension(context,myobj,DimGen,axisDim,mat) svg.save(pretty=True) # restore default value sceneProps.is_render_draw = False sceneProps.is_vector_draw = False return True
def render_opengl(self, context): from math import ceil layers = [] scene = context.scene for x in range(0, 20): if scene.layers[x] is True: layers.extend([x]) objlist = context.scene.objects render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) # I cant use file_format becuase the pdf writer needs jpg format # the file_format returns 'JPEG' not 'JPG' # file_format = context.scene.render.image_settings.file_format.lower() ren_path = bpy.path.abspath(bpy.context.scene.render.filepath) + ".jpg" # if len(ren_path) > 0: # if ren_path.endswith(os.path.sep): # initpath = os.path.realpath(ren_path) + os.path.sep # else: # (initpath, filename) = os.path.split(ren_path) # outpath = os.path.join(initpath, "ogl_tmp.png") # else: # self.report({'ERROR'}, "Invalid render path") # return False img = get_render_image(ren_path) if img is None: self.report({'ERROR'}, "Invalid render path:" + ren_path) return False tile_x = 240 tile_y = 216 row_num = ceil(height / tile_y) col_num = ceil(width / tile_x) cut4 = (col_num * tile_x * 4) - width * 4 totpixel4 = width * height * 4 viewport_info = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport_info) img.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST) # 2.77 API change if bpy.app.version >= (2, 77, 0): tex = img.bindcode[0] else: tex = img.bindcode if context.scene.name in bpy.data.images: old_img = bpy.data.images[context.scene.name] old_img.user_clear() bpy.data.images.remove(old_img) img_result = bpy.data.images.new(context.scene.name, width, height) tmp_pixels = [1] * totpixel4 #---------- Loop for all tiles for row in range(0, row_num): for col in range(0, col_num): buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glDisable(bgl.GL_SCISSOR_TEST) # if remove this line, get blender screenshot not image bgl.glViewport(0, 0, tile_x, tile_y) bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() # defines ortographic view for single tile x1 = tile_x * col y1 = tile_y * row bgl.gluOrtho2D(x1, x1 + tile_x, y1, y1 + tile_y) # Clear bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) bgl.glEnable(bgl.GL_TEXTURE_2D) bgl.glBindTexture(bgl.GL_TEXTURE_2D, tex) # defines drawing area bgl.glBegin(bgl.GL_QUADS) bgl.glColor3f(1.0, 1.0, 1.0) bgl.glTexCoord2f(0.0, 0.0) bgl.glVertex2f(0.0, 0.0) bgl.glTexCoord2f(1.0, 0.0) bgl.glVertex2f(width, 0.0) bgl.glTexCoord2f(1.0, 1.0) bgl.glVertex2f(width, height) bgl.glTexCoord2f(0.0, 1.0) bgl.glVertex2f(0.0, height) bgl.glEnd() for obj in objlist: if obj.mv.type == 'VISDIM_A': for x in range(0, 20): if obj.layers[x] is True: if x in layers: opengl_dim = obj.mv.opengl_dim if not opengl_dim.hide: draw_dimensions(context, obj, opengl_dim, None, None) break #---------- copy pixels to temporary area bgl.glFinish() bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # read image data for y in range(0, tile_y): # final image pixels position p1 = (y * width * 4) + (row * tile_y * width * 4) + (col * tile_x * 4) p2 = p1 + (tile_x * 4) # buffer pixels position b1 = y * width * 4 b2 = b1 + (tile_x * 4) if p1 < totpixel4: # avoid pixel row out of area if col == col_num - 1: # avoid pixel columns out of area p2 -= cut4 b2 -= cut4 tmp_pixels[p1:p2] = buffer[b1:b2] img_result.pixels = tmp_pixels[:] img.gl_free() img.user_clear() bpy.data.images.remove(img) os.remove(ren_path) bgl.glEnable(bgl.GL_SCISSOR_TEST) #---------- restore opengl defaults bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 0.0, 1.0) if img_result is not None: return img_result
def render_main(self, context, animation=False): # Save old info settings = bpy.context.scene.render.image_settings depth = settings.color_depth settings.color_depth = '8' # Get object list scene = context.scene objlist = context.scene.objects # -------------------- # Get resolution # -------------------- render_scale = scene.render.resolution_percentage / 100 width = int(scene.render.resolution_x * render_scale) height = int(scene.render.resolution_y * render_scale) # -------------------------------------- # Loop to draw all lines in Offsecreen # -------------------------------------- offscreen = gpu.types.GPUOffScreen(width, height) view_matrix = Matrix([ [2 / width, 0, 0, -1], [0, 2 / height, 0, -1], [0, 0, 1, 0], [0, 0, 0, 1]]) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) # ----------------------------- # Loop to draw all objects # ----------------------------- for myobj in objlist: if myobj.visible_get() is True: if 'MeasureGenerator' in myobj: op = myobj.MeasureGenerator[0] draw_segments(context, myobj, op, None, None) # ----------------------------- # Loop to draw all debug # ----------------------------- if scene.measureit_debug is True: selobj = bpy.context.selected_objects for myobj in selobj: if scene.measureit_debug_objects is True: draw_object(context, myobj, None, None) elif scene.measureit_debug_object_loc is True: draw_object(context, myobj, None, None) if scene.measureit_debug_vertices is True: draw_vertices(context, myobj, None, None) elif scene.measureit_debug_vert_loc is True: draw_vertices(context, myobj, None, None) if scene.measureit_debug_edges is True: draw_edges(context, myobj, None, None) if scene.measureit_debug_faces is True or scene.measureit_debug_normals is True: draw_faces(context, myobj, None, None) # ----------------------------- # Draw a rectangle frame # ----------------------------- if scene.measureit_rf is True: rfcolor = scene.measureit_rf_color rfborder = scene.measureit_rf_border rfline = scene.measureit_rf_line bgl.glLineWidth(rfline) x1 = rfborder x2 = width - rfborder y1 = int(ceil(rfborder / (width / height))) y2 = height - y1 draw_rectangle((x1, y1), (x2, y2), rfcolor) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) offscreen.free() # ----------------------------- # Create image # ----------------------------- image_name = "measureit_output" if not image_name in bpy.data.images: bpy.data.images.new(image_name, width, height) image = bpy.data.images[image_name] image.scale(width, height) image.pixels = [v / 255 for v in buffer] # Saves image if image is not None and (scene.measureit_render is True or animation is True): ren_path = bpy.context.scene.render.filepath filename = "mit_frame" if len(ren_path) > 0: if ren_path.endswith(path.sep): initpath = path.realpath(ren_path) + path.sep else: (initpath, filename) = path.split(ren_path) ftxt = "%04d" % scene.frame_current outpath = path.realpath(path.join(initpath, filename + ftxt + ".png")) save_image(self, outpath, image) # restore default value settings.color_depth = depth
def drawBoltGPU(self, lines, pixels, coord, w, h): vertexSource = ''' in vec3 position; void main() { gl_Position = vec4(position, 1.0); } ''' geometrySource = ''' layout(lines) in; layout(triangle_strip, max_vertices = 4) out; void main() { float width = gl_in[1].gl_Position.z; vec2 line = gl_in[1].gl_Position.xy - gl_in[0].gl_Position.xy; vec2 normal = normalize(vec2(line.y, -line.x))*(width/2.0); for(int i=0; i<4; i++) { vec2 coords = gl_in[i/2].gl_Position.xy+(1-2*(i%2))*normal; gl_Position = vec4(coords, 0.0, 1.0); EmitVertex(); } EndPrimitive(); } ''' fragmentSource = ''' out vec4 fragColor; void main() { fragColor = vec4(1.0,1.0,1.0,1.0); } ''' positions = [] for segment in lines.segments: pts = lines.getCoords(segment)[0] ptA = np.divide(pts[0], np.array([w, h])) * 2 - 1.0 ptB = np.divide(pts[1], np.array([w, h])) * 2 - 1.0 width = bl_math.clamp( self.thickness * (1.0 - (segment.level / (self.falloff * lines.getMaxLevel()))), 0, self.thickness) / w positions.append((ptA[0], ptA[1], width)) positions.append((ptB[0], ptB[1], width)) offscreen = gpu.types.GPUOffScreen(w, h) shaders = gpu.types.GPUShader(vertexSource, fragmentSource, geocode=geometrySource) batch = batch_for_shader(shaders, 'LINES', {"position": tuple(positions)}) with offscreen.bind(): bgl.glClearColor(0.0, 0.0, 0.0, 1.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) with gpu.matrix.push_pop(): gpu.matrix.load_matrix(mathutils.Matrix.Identity(4)) gpu.matrix.load_projection_matrix(mathutils.Matrix.Identity(4)) shaders.bind() batch.draw(shaders) buffer = bgl.Buffer(bgl.GL_FLOAT, w * h * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, w, h, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) pixels.foreach_set(buffer) offscreen.free()
def get_pixel_data_from_current_back_buffer(width, height): buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) return buffer
def render_main(self, context, objlist, animation=False): # noinspection PyBroadException,PyBroadException # Save old info scene = context.scene render = scene.render settings = render.image_settings depth = settings.color_depth settings.color_depth = '8' # noinspection PyBroadException try: # Get visible layers layers = [] for x in range(0, 20): if scene.layers[x] is True: layers.extend([x]) # -------------------- # Get resolution # -------------------- render_scale = render.resolution_percentage / 100 width = int(render.resolution_x * render_scale) height = int(render.resolution_y * render_scale) # --------------------------------------- # Get output path # --------------------------------------- temp_path = path.realpath(bpy.app.tempdir) if len(temp_path) > 0: outpath = path.join(temp_path, "archipack_tmp_render.png") else: self.report({ 'ERROR' }, "Archipack: Unable to save temporary render image. Define a valid temp path" ) settings.color_depth = depth return False # Get Render Image img = self.get_render_image(outpath) if img is None: self.report({ 'ERROR' }, "Archipack: Unable to save temporary render image. Define a valid temp path" ) settings.color_depth = depth return False # ----------------------------- # Calculate rows and columns # ----------------------------- tile_x = 240 tile_y = 216 row_num = ceil(height / tile_y) col_num = ceil(width / tile_x) print("Archipack: Image divided in " + str(row_num) + "x" + str(col_num) + " tiles") # pixels out of visible area cut4 = (col_num * tile_x * 4) - width * 4 # pixels aout of drawing area totpixel4 = width * height * 4 # total pixels RGBA viewport_info = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport_info) # Load image on memory img.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST) # 2.77 API change if bpy.app.version >= (2, 77, 0): tex = img.bindcode[0] else: tex = img.bindcode # -------------------------------------------- # Create output image (to apply texture) # -------------------------------------------- if "archipack_output" in bpy.data.images: out_img = bpy.data.images["archipack_output"] if out_img is not None: out_img.user_clear() bpy.data.images.remove(out_img) out = bpy.data.images.new("archipack_output", width, height) tmp_pixels = [1] * totpixel4 # -------------------------------- # Loop for all tiles # -------------------------------- for row in range(0, row_num): for col in range(0, col_num): buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glDisable( bgl.GL_SCISSOR_TEST ) # if remove this line, get blender screenshot not image bgl.glViewport(0, 0, tile_x, tile_y) bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() # defines ortographic view for single tile x1 = tile_x * col y1 = tile_y * row bgl.gluOrtho2D(x1, x1 + tile_x, y1, y1 + tile_y) # Clear bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) bgl.glEnable(bgl.GL_TEXTURE_2D) bgl.glBindTexture(bgl.GL_TEXTURE_2D, tex) # defines drawing area bgl.glBegin(bgl.GL_QUADS) bgl.glColor3f(1.0, 1.0, 1.0) bgl.glTexCoord2f(0.0, 0.0) bgl.glVertex2f(0.0, 0.0) bgl.glTexCoord2f(1.0, 0.0) bgl.glVertex2f(width, 0.0) bgl.glTexCoord2f(1.0, 1.0) bgl.glVertex2f(width, height) bgl.glTexCoord2f(0.0, 1.0) bgl.glVertex2f(0.0, height) bgl.glEnd() # ----------------------------- # Loop to draw all lines # ----------------------------- for o, d in objlist: if o.hide is False: # verify visible layer for x in range(0, 20): if o.layers[x] is True: if x in layers: context.scene.objects.active = o # print("%s: %s" % (o.name, d.manip_stack)) manipulators = d.manip_stack if manipulators is not None: for m in manipulators: if m is not None: m.draw_callback( m, context, render=True) break # ----------------------------- # Loop to draw all debug # ----------------------------- """ if scene.archipack_debug is True: selobj = bpy.context.selected_objects for myobj in selobj: if scene.archipack_debug_vertices is True: draw_vertices(context, myobj, None, None) if scene.archipack_debug_faces is True or scene.archipack_debug_normals is True: draw_faces(context, myobj, None, None) """ """ if scene.archipack_rf is True: bgl.glColor3f(1.0, 1.0, 1.0) rfcolor = scene.archipack_rf_color rfborder = scene.archipack_rf_border rfline = scene.archipack_rf_line bgl.glLineWidth(rfline) bgl.glColor4f(rfcolor[0], rfcolor[1], rfcolor[2], rfcolor[3]) x1 = rfborder x2 = width - rfborder y1 = int(ceil(rfborder / (width / height))) y2 = height - y1 draw_rectangle((x1, y1), (x2, y2)) """ # -------------------------------- # copy pixels to temporary area # -------------------------------- bgl.glFinish() bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # read image data for y in range(0, tile_y): # final image pixels position p1 = (y * width * 4) + (row * tile_y * width * 4) + (col * tile_x * 4) p2 = p1 + (tile_x * 4) # buffer pixels position b1 = y * width * 4 b2 = b1 + (tile_x * 4) if p1 < totpixel4: # avoid pixel row out of area if col == col_num - 1: # avoid pixel columns out of area p2 -= cut4 b2 -= cut4 tmp_pixels[p1:p2] = buffer[b1:b2] # ----------------------- # Copy temporary to final # ----------------------- out.pixels = tmp_pixels[:] # Assign image data img.gl_free() # free opengl image memory # delete image img.user_clear() bpy.data.images.remove(img) # remove temp file remove(outpath) # reset bgl.glEnable(bgl.GL_SCISSOR_TEST) # ----------------------- # restore opengl defaults # ----------------------- bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 0.0, 1.0) # Saves image if out is not None: # and (scene.archipack_render is True or animation is True): ren_path = bpy.context.scene.render.filepath filename = "ap_frame" if len(ren_path) > 0: if ren_path.endswith(path.sep): initpath = path.realpath(ren_path) + path.sep else: (initpath, filename) = path.split(ren_path) ftxt = "%04d" % scene.frame_current outpath = path.realpath( path.join(initpath, filename + ftxt + ".png")) self.save_image(outpath, out) settings.color_depth = depth return True except: settings.color_depth = depth print("Unexpected error:" + str(exc_info())) self.report({ 'ERROR' }, "Archipack: Unable to create render image. Be sure the output render path is correct" ) return False
def generate_icon(name, verts=None, faces=None): pcoll = preview_collections["shape_types"] if name in pcoll: thumb = pcoll.get(name) else: thumb = pcoll.new(name) thumb.image_size = (200, 200) if verts is not None: import bgl polygon_color = bpy.context.user_preferences.themes[0].view_3d.edge_facesel edge_color = bpy.context.user_preferences.themes[0].view_3d.edge_select vertex_color = bpy.context.user_preferences.themes[0].view_3d.vertex_select clear_color = bpy.context.user_preferences.themes[0].user_interface.wcol_menu.inner viewport_info = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport_info) buffer = bgl.Buffer(bgl.GL_FLOAT, 200 * 200 * 4) bgl.glDisable(bgl.GL_SCISSOR_TEST) bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) bgl.glEnable(bgl.GL_LINE_SMOOTH) bgl.glEnable(bgl.GL_POINT_SMOOTH) bgl.glViewport(0, 0, 200, 200) bgl.glMatrixMode(bgl.GL_MODELVIEW) bgl.glPushMatrix() bgl.glLoadIdentity() bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glPushMatrix() bgl.glLoadIdentity() bgl.gluOrtho2D(0, 0, 0, 0) bgl.glLineWidth(4.0) bgl.glPointSize(10.0) bgl.glClearColor(*clear_color) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) if faces is None: bgl.glBegin(bgl.GL_POLYGON) bgl.glColor3f(*polygon_color) for vert in verts: bgl.glVertex2f(*vert) bgl.glEnd() else: bgl.glBegin(bgl.GL_TRIANGLES) bgl.glColor3f(*polygon_color) for face in faces: bgl.glVertex2f(*verts[face[0]]) bgl.glVertex2f(*verts[face[1]]) bgl.glVertex2f(*verts[face[2]]) bgl.glEnd() bgl.glBegin(bgl.GL_LINE_LOOP) bgl.glColor3f(*edge_color) for vert in verts: bgl.glVertex2f(*vert) bgl.glEnd() bgl.glBegin(bgl.GL_POINTS) bgl.glColor3f(*vertex_color) for vert in verts: bgl.glVertex2f(*vert) bgl.glEnd() bgl.glReadPixels(0, 0, 200, 200, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) bgl.glEnable(bgl.GL_SCISSOR_TEST) bgl.glLineWidth(1.0) bgl.glPointSize(1.0) buffer = buffer[:] for idx in range(0, 200 * 200 * 4, 4): if ( buffer[idx] == clear_color[0] and buffer[idx + 1] == clear_color[1] and buffer[idx + 2] == clear_color[2] ): buffer[idx + 3] = 0.0 thumb.image_pixels_float = buffer
def render_map(self, context): import tempfile image_name = "Gem Map" width = self.width height = self.height ratio_w = width / self.region.width ratio_h = height / self.region.height padding = 30 x = padding y = height - padding temp_filepath = os.path.join(tempfile.gettempdir(), "gem_map_temp.png") asset.render_preview(width, height, temp_filepath, compression=15, gamma=2.2) render_image = load_image(temp_filepath) render_image.gl_load() mat_offscreen = Matrix() mat_offscreen[0][0] = 2 / width mat_offscreen[0][3] = -1 mat_offscreen[1][1] = 2 / height mat_offscreen[1][3] = -1 shader = gpu.shader.from_builtin("2D_UNIFORM_COLOR") shader_img = gpu.shader.from_builtin("2D_IMAGE") offscreen = gpu.types.GPUOffScreen(width, height) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) with gpu.matrix.push_pop(): gpu.matrix.load_matrix(mat_offscreen) gpu.matrix.load_projection_matrix(Matrix()) # Background # -------------------------------- shader.bind() shader.uniform_float("color", (1.0, 1.0, 1.0, 1.0)) batch = batch_for_shader( shader, "TRI_FAN", {"pos": self.rect_coords(0, 0, width, height)}) batch.draw(shader) # Render result # -------------------------------- bgl.glEnable(bgl.GL_BLEND) bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, render_image.bindcode) shader_img.bind() shader_img.uniform_int("image", 0) args = { "pos": self.rect_coords(0, 0, width, height), "texCoord": self.rect_coords(0, 0, 1, 1), } batch = batch_for_shader(shader_img, "TRI_FAN", args) batch.draw(shader_img) # Gem map # -------------------------------- self.draw_gems(context, ratio_w=ratio_w, ratio_h=ratio_h) self.onscreen_gem_table(x, y, color=(0.0, 0.0, 0.0, 1.0)) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) offscreen.free() if image_name not in bpy.data.images: bpy.data.images.new(image_name, width, height) image = bpy.data.images[image_name] image.scale(width, height) image.pixels = [v / 255 for v in buffer] if self.use_save and bpy.data.is_saved: filepath = bpy.data.filepath filename = os.path.splitext(os.path.basename(filepath))[0] save_path = os.path.join(os.path.dirname(filepath), filename + " Gem Map.png") image.filepath_raw = save_path image.file_format = "PNG" image.save() render_image.gl_free() bpy.data.images.remove(render_image) if os.path.exists(temp_filepath): os.remove(temp_filepath) # Restore OpenGL defaults # ---------------------------- bgl.glDisable(bgl.GL_BLEND) # Show in a new window # ---------------------------- asset.show_window(width, height, space_data={"image": image})
def snap_get(self, mval): ret = None, None self.mval[:] = mval snap_vert = self._snap_mode & VERT != 0 snap_edge = self._snap_mode & EDGE != 0 snap_face = self._snap_mode & FACE != 0 _Internal.gpu_Indices_enable_state() self._offscreen.bind() #bgl.glDisable(bgl.GL_DITHER) # dithering and AA break color coding, so disable # #multisample_enabled = bgl.glIsEnabled(bgl.GL_MULTISAMPLE) #bgl.glDisable(bgl.GL_MULTISAMPLE) bgl.glEnable(bgl.GL_DEPTH_TEST) proj_mat = self.rv3d.perspective_matrix.copy() if self.proj_mat != proj_mat: self.proj_mat = proj_mat _Internal.gpu_Indices_set_ProjectionMatrix(self.proj_mat) self.update_all() ray_dir, ray_orig = self.get_ray(mval) for i, snap_obj in enumerate(self.snap_objects[self.drawn_count:], self.drawn_count): obj = snap_obj.data[0] bbmin = Vector(obj.bound_box[0]) bbmax = Vector(obj.bound_box[6]) if bbmin != bbmax: MVP = proj_mat * snap_obj.mat mat_inv = snap_obj.mat.inverted() ray_orig_local = mat_inv * ray_orig ray_dir_local = mat_inv.to_3x3() * ray_dir in_threshold = _Internal.intersect_boundbox_threshold(self, MVP, ray_orig_local, ray_dir_local, bbmin, bbmax) else: proj_co = _Internal.project_co_v3(self, snap_obj.mat.translation) dist = self.mval - proj_co in_threshold = abs(dist.x) < self._dist_px and abs(dist.y) < self._dist_px #snap_obj.data[1] = primitive_point if in_threshold: if len(snap_obj.data) == 1: from .mesh_drawing import GPU_Indices_Mesh snap_obj.data.append(GPU_Indices_Mesh(obj, snap_face, snap_edge, snap_vert)) snap_obj.data[1].set_draw_mode(snap_face, snap_edge, snap_vert) snap_obj.data[1].set_ModelViewMatrix(snap_obj.mat) snap_obj.data[1].Draw(self._offset_cur) self._offset_cur += snap_obj.data[1].get_tot_elems() self.snap_objects[self.drawn_count], self.snap_objects[i] = self.snap_objects[i], self.snap_objects[self.drawn_count] self.drawn_count += 1 bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadPixels( int(self.mval[0]) - self._dist_px, int(self.mval[1]) - self._dist_px, self.threshold, self.threshold, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, self._snap_buffer) bgl.glReadBuffer(bgl.GL_BACK) snap_obj, index = self._get_nearest_index() #print(index) if snap_obj: ret = self._get_loc(snap_obj, index) self._offscreen.unbind() _Internal.gpu_Indices_restore_state() return snap_obj, ret[0], ret[1]