def draw_custom_3d_elements(mode): """Get's updated custom 3D elements and draws them :param mode: drawing mode for custom elements (can be: 'Normal' or 'X-ray') :type mode: str """ if mode == "Normal": glEnable(GL_DEPTH_TEST) glClear(GL_DEPTH_BUFFER_BIT) else: # X-ray mode disable_depth_test() scs_globals = _get_scs_globals() # TERRAIN POINTS glPointSize(5.0) for tp_position, tp_color in _terrain_points_storage.get_positions_and_colors(): _primitive.draw_point(tp_position, tp_color) glPointSize(1.0) (prefab_locators, collision_locators, model_locators) = _get_custom_visual_elements() # reset point size to 1.0 and set line width to 2.0 before drawing curves and lines glPointSize(1.0) glLineWidth(2.0) # CURVES AND LINES if scs_globals.display_connections: _connections_group_wrapper.draw(prefab_locators) # reset line width to 1.0 after drawing curves and lines glLineWidth(1.0) # LOCATORS if scs_globals.display_locators: # PREFAB LOCATORS if prefab_locators: for obj in prefab_locators.values(): _locators.prefab.draw_prefab_locator(obj, scs_globals) # COLLISION LOCATORS if collision_locators: for obj in collision_locators.values(): _locators.collider.draw_collision_locator(obj, scs_globals) # MODEL LOCATORS if model_locators: for obj in model_locators.values(): _locators.model.draw_model_locator(obj, scs_globals)
def export(filepath, face_data, colors, width, height, opacity): offscreen = gpu.types.GPUOffScreen(width, height) offscreen.bind() try: bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) draw_image(face_data, opacity) pixel_data = get_pixel_data_from_current_back_buffer(width, height) save_pixels(filepath, pixel_data, width, height) finally: offscreen.unbind() offscreen.free()
def clear(self): is_bound = self is _SnapOffscreen.bound if not is_bound: self.bind() bgl.glColorMask(bgl.GL_TRUE, bgl.GL_TRUE, bgl.GL_TRUE, bgl.GL_TRUE) bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glDepthMask(bgl.GL_TRUE) bgl.glClearDepth(1.0); bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) if not is_bound: self.unbind()
def h_clip_begin(bounds, padding=[0, 0, 0, 0]): vp = bgl.Buffer(bgl.GL_INT, 4) bgl.glGetIntegerv(bgl.GL_VIEWPORT, vp) B = [bounds[0]+padding[0], bounds[1]+padding[1], bounds[2]-padding[2]*2, bounds[3]-padding[3]*2] # Do some math to invert the coords scp = [0, 0, int(B[2]), int(B[3])] scp[0] = int(B[0] + vp[0]) scp[1] = int(vp[1] + (vp[3] - B[1] - B[3])) bgl.glEnable(bgl.GL_SCISSOR_TEST) bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_SCISSOR_BIT) bgl.glScissor(*scp)
def h_mask_begin(bounds, radius=0): bgl.glEnable(bgl.GL_STENCIL_TEST) bgl.glColorMask(False, False, False, False) bgl.glDepthMask(False) bgl.glStencilFunc(bgl.GL_NEVER, 1, 0xFF) bgl.glStencilOp(bgl.GL_REPLACE, bgl.GL_KEEP, bgl.GL_KEEP) bgl.glStencilMask(0xFF) bgl.glClear(bgl.GL_STENCIL_BUFFER_BIT) h_round_rect(bounds, radius) bgl.glColorMask(True, True, True, True) bgl.glDepthMask(True) bgl.glStencilMask(0x00); bgl.glStencilFunc(bgl.GL_EQUAL, 0, 0xFF) bgl.glStencilFunc(bgl.GL_EQUAL, 1, 0xFF)
def draw_custom_3d_elements(mode): """Get's updated custom 3D elements and draws them :param mode: drawing mode for custom elements (can be: 'Normal' or 'X-ray') :type mode: str """ if mode == "Normal": glEnable(GL_DEPTH_TEST) glClear(GL_DEPTH_BUFFER_BIT) else: # X-ray mode disable_depth_test() context = bpy.context (prefab_locators, collision_locators, model_locators) = _get_custom_visual_elements() # PREFAB LOCATORS if context.scene.scs_props.display_locators: if prefab_locators: for obj in prefab_locators.values(): _locators.prefab.draw_prefab_locator(obj, context.scene.scs_props) # reset point size to 1.0 and set line width to 2.0 before drawing curves and lines glPointSize(1.0) glLineWidth(2.0) # CURVES AND LINES if context.scene.scs_props.display_connections: _connections_group_wrapper.draw(prefab_locators) # reset line width to 1.0 after drawing curves and lines glLineWidth(1.0) # COLLISION LOCATORS if context.scene.scs_props.display_locators: if collision_locators: for obj in collision_locators.values(): _locators.collider.draw_collision_locator(obj, context.scene.scs_props) # MODEL LOCATORS if context.scene.scs_props.display_locators: if model_locators: for obj in model_locators.values(): _locators.model.draw_model_locator(obj, context.scene.scs_props)
def offscreen_refresh(self, context): if self.offscreen is not None: self.offscreen.free() width = self.region.width height = self.region.height self.offscreen = gpu.types.GPUOffScreen(width, height) 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 with self.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()) self.draw_gems(context)
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 render_image(self): # Render the scene and load it into the script tmp_path = self.scene.render.filepath tmp_image = 'temp_img_store' + '.png' if tmp_image in bpy.data.images: bpy.data.images.remove(bpy.data.images[tmp_image]) self.scene.render.filepath = self.path + tmp_image bpy.ops.render.render(write_still=True) renderedImage = bpy.data.images.load(self.path + tmp_image) renderedImage.colorspace_settings.name = 'Linear' # Vertex shader for cubemap frontimage to equirectangular vertex_shader = ''' in vec3 aVertexPosition; in vec2 aVertexTextureCoord; out vec2 vTexCoord; void main() { vTexCoord = aVertexTextureCoord; gl_Position = vec4(aVertexPosition, 1); } ''' # Generate the OpenGL shader pos = [(-1.0, -1.0, -1.0), (-1.0, 1.0, -1.0), \ (1.0, -1.0, -1.0), (1.0, 1.0, -1.0)] coords = [(-2.0, -1.0), (-2.0, 1.0), \ (2.0, -1.0), (2.0, 1.0)] vertexIndices = [(0, 3, 1), (3, 0, 2)] shader = gpu.types.GPUShader(vertex_shader, self.frag_shader) batch = batch_for_shader(shader, 'TRIS', {"aVertexPosition": pos, \ "aVertexTextureCoord": coords}, \ indices=vertexIndices) # Load rendered image into OpenGL textures renderedImage.gl_load() # Create an offscreen render buffer and texture offscreen = gpu.types.GPUOffScreen(self.image_size[0], self.image_size[1]) with offscreen.bind(): #bgl.glClearColor(0,0,0,1) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) shader.bind() def bind_and_filter(tex, bindcode, image=None, imageNum=None): bgl.glActiveTexture(tex) bgl.glBindTexture(bgl.GL_TEXTURE_2D, bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) # Turn on GL_CLAMP_TO_BORDER and delete paint black codes in fragment shader # would give a transparent background #bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_BORDER) #bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_BORDER) # Really dont know how to change the border color #bgl.glTexParameterfv(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_BORDER_COLOR, color)#??? if image != None and imageNum != None: shader.uniform_int(image, imageNum) # Bind and filter the renderedImage bind_and_filter(bgl.GL_TEXTURE0, renderedImage.bindcode, "frontImage", 0) # Bind the resulting texture bind_and_filter(bgl.GL_TEXTURE1, offscreen.color_texture) # Render the image batch.draw(shader) # Unload the texture renderedImage.gl_free() # Read the resulting pixels into a buffer buffer = bgl.Buffer(bgl.GL_FLOAT, self.image_size[0] * self.image_size[1] * 4) bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # Unload the offscreen texture offscreen.free() # Remove the frontImage texture bpy.data.images.remove(renderedImage) # Turn on this line to delete tmp image everytime, turn off maybe will save some resource #os.remove(self.path + tmp_image) # Set file name image_name = "frameS{:06d}.png".format(self.scene.frame_current) # If it doesn't already exist, create an image object to store the resulting render if not image_name in bpy.data.images.keys(): imageResult = bpy.data.images.new(image_name, self.image_size[0], self.image_size[1]) imageResult = bpy.data.images[image_name] imageResult.scale(self.image_size[0], self.image_size[1]) # Copy the pixels from the buffer to an image object imageResult.pixels = buffer # Save to file imageResult.file_format = 'PNG' imageResult.filepath_raw = self.path + image_name imageResult.save() bpy.data.images.remove(imageResult) self.scene.render.filepath = tmp_path
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 execute(self, context): bgl.glEnable(bgl.GL_PROGRAM_POINT_SIZE) scene = context.scene render = scene.render image_settings = render.image_settings original_depth = image_settings.color_depth image_settings.color_depth = '8' scale = render.resolution_percentage / 100 width = int(render.resolution_x * scale) height = int(render.resolution_y * scale) pcv = context.object.point_cloud_visualizer cloud = PCVManager.cache[pcv.uuid] cam = scene.camera if (cam is None): self.report({'ERROR'}, "No camera found.") return {'CANCELLED'} render_suffix = pcv.render_suffix render_zeros = pcv.render_zeros offscreen = GPUOffScreen(width, height) offscreen.bind() try: gpu.matrix.load_matrix(Matrix.Identity(4)) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) o = cloud['object'] vs = cloud['vertices'] cs = cloud['colors'] ns = cloud['normals'] dp = pcv.render_display_percent l = int((len(vs) / 100) * dp) if (dp >= 99): l = len(vs) vs = vs[:l] cs = cs[:l] ns = ns[:l] # sort by depth mw = o.matrix_world depth = [] for i, v in enumerate(vs): vw = mw @ Vector(v) depth.append(world_to_camera_view(scene, cam, vw)[2]) zps = zip(depth, vs, cs, ns) sps = sorted(zps, key=lambda a: a[0]) # split and reverse vs = [a for _, a, b, c in sps][::-1] cs = [b for _, a, b, c in sps][::-1] ns = [c for _, a, b, c in sps][::-1] shader = GPUShader(vertex_shader, fragment_shader) batch = batch_for_shader(shader, 'POINTS', { "position": vs, "color": cs, "normal": ns, }) shader.bind() view_matrix = cam.matrix_world.inverted() camera_matrix = cam.calc_matrix_camera( bpy.context.depsgraph, x=render.resolution_x, y=render.resolution_y, scale_x=render.pixel_aspect_x, scale_y=render.pixel_aspect_y, ) perspective_matrix = camera_matrix @ view_matrix shader.uniform_float("perspective_matrix", perspective_matrix) shader.uniform_float("object_matrix", o.matrix_world) shader.uniform_float("point_size", pcv.render_point_size) shader.uniform_float("alpha_radius", pcv.alpha_radius) if (pcv.light_enabled and pcv.has_normals): cm = Matrix(( ( -1.0, 0.0, 0.0, 0.0, ), ( 0.0, -0.0, 1.0, 0.0, ), ( 0.0, -1.0, -0.0, 0.0, ), ( 0.0, 0.0, 0.0, 1.0, ), )) _, obrot, _ = o.matrix_world.decompose() mr = obrot.to_matrix().to_4x4() mr.invert() direction = cm @ pcv.light_direction direction = mr @ direction shader.uniform_float("light_direction", direction) inverted_direction = direction.copy() inverted_direction.negate() c = pcv.light_intensity shader.uniform_float("light_intensity", ( c, c, c, )) shader.uniform_float("shadow_direction", inverted_direction) c = pcv.shadow_intensity shader.uniform_float("shadow_intensity", ( c, c, c, )) shader.uniform_float("show_normals", float(pcv.show_normals)) else: z = (0, 0, 0) shader.uniform_float("light_direction", z) shader.uniform_float("light_intensity", z) shader.uniform_float("shadow_direction", z) shader.uniform_float("shadow_intensity", z) shader.uniform_float("show_normals", float(False)) batch.draw(shader) 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) except Exception as e: self.report({'ERROR'}, str(e)) return {'CANCELLED'} finally: offscreen.unbind() offscreen.free() # image from buffer image_name = "pcv_output" 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] # save as image file save_render( self, scene, image, render_suffix, render_zeros, ) # restore image_settings.color_depth = original_depth return {'FINISHED'}
def color_to_KK(color, lut_name): width = 1 height = 1 # Some Sauce vertex_default = ''' in vec2 a_position; void main() { gl_Position = vec4(a_position, 0.0, 1.0); } ''' # The Secret Sauce current_code = ''' uniform vec3 inputColor; uniform sampler2D lut; vec3 to_srgb(vec3 c){ c.rgb = max( 1.055 * pow( c.rgb, vec3(0.416666667,0.416666667,0.416666667) ) - 0.055, 0 ); return c; } void main() { vec3 color = inputColor / 255; const vec3 coord_scale = vec3(0.0302734375, 0.96875, 31.0); const vec3 coord_offset = vec3( 0.5/1024, 0.5/32, 0.0); const vec2 texel_height_X0 = vec2( 0.03125, 0.0 ); vec3 coord = color * coord_scale + coord_offset; vec3 coord_frac = fract( coord ); vec3 coord_floor = coord - coord_frac; vec2 coord_bot = coord.xy + coord_floor.zz * texel_height_X0; vec2 coord_top = coord_bot + texel_height_X0; vec3 lutcol_bot = texture( lut, coord_bot ).rgb; vec3 lutcol_top = texture( lut, coord_top ).rgb; vec3 lutColor = mix(lutcol_bot, lutcol_top, coord_frac.z); vec3 shaderColor = lutColor; gl_FragColor = vec4(shaderColor.rgb, 1); } ''' # This object gives access to off screen buffers. offscreen = gpu.types.GPUOffScreen(width, height) # Context manager to ensure balanced bind calls, even in the case of an error. # Only run if valid with offscreen.bind(): # Clear buffers to preset values bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # Initialize the shader # GPUShader combines multiple GLSL shaders into a program used for drawing. # It must contain a vertex and fragment shaders, with an optional geometry shader. shader = gpu.types.GPUShader(vertex_default, current_code) # Initialize the shader batch # It makes sure that all the vertex attributes necessary for a specific shader are provided. batch = batch_for_shader( shader, 'TRI_FAN', {'a_position': ((-1, -1), (1, -1), (1, 1), (-1, 1))}, ) # Bind the shader object. Required to be able to change uniforms of this shader. shader.bind() try: # Specify the value of a uniform variable for the current program object. # In this case, a color tuple. shader.uniform_float('inputColor', color) except ValueError: pass try: lut_image = bpy.data.images[lut_name] # Make sure image has a bindcode if lut_image.bindcode == 0: for i in range(0, 20): lut_image.gl_load() if lut_image.bindcode != 0: break # https://docs.blender.org/api/current/bgl.html bgl.glBindTexture(bgl.GL_TEXTURE_2D, lut_image.bindcode) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) # Specify the value of a uniform variable for the current program object. # In this case, an image. shader.uniform_int("lut", 0) except ValueError: pass # Run the drawing program with the parameters assigned to the batch. batch.draw(shader) # The Buffer object is simply a block of memory that is delineated and initialized by the user. buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 3) # Select a color buffer source for pixels. bgl.glReadBuffer(bgl.GL_BACK) # Read a block of pixels from the frame buffer. bgl.glReadPixels(0, 0, width, height, bgl.GL_RGB, bgl.GL_UNSIGNED_BYTE, buffer) # Free the offscreen object. The framebuffer, texture and render objects will no longer be accessible. offscreen.free() # Get and return the pixels from the final buffer final_color = [v for v in buffer] final_color = np.array(final_color).reshape(width, height, -1) return final_color[0][0] # RGBA (1, 1, 1, 1) to RGB as int (255, 255, 255) def RGBA_to_RGB_int(rgba): rgba = np.round(rgba * 255).astype('int') rgba = np.delete(rgba, 3) return rgba # Make sure not to select a transparent pixel def filter_pixel(index_list, image): for i in index_list: if image[i][3] == 1: index = i break return index ########## SETUP ########## exposure = np.array([exposure[0], exposure[1], exposure[2], 1]) # Init MC Texture mc_mask_data = np.array(mc_mask.pixels).reshape(-1, 4) mc_mask_data = mc_mask_data * exposure mc_mask_data = np.clip(mc_mask_data, 0, 1) # Init Main Texture bpy.data.images[texture.name].scale(mc_mask.size[0], mc_mask.size[1]) texture_data = np.array(texture.pixels).reshape(-1, 4) # Init MC Color indexes red_index = -1 green_index = -1 blue_index = -1 # Init MainTex Colors red_color = -1 green_color = -1 blue_color = -1 # Init converted colors (light) red_converted_color_light = np.array([255, 0, 0, 255]) green_converted_color_light = np.array([0, 255, 0, 255]) blue_converted_color_light = np.array([0, 0, 255, 255]) ########## FIND MC INDEXES ########## r, g, b = mc_mask_data[:, 0], mc_mask_data[:, 1], mc_mask_data[:, 2] r = r.max() g = g.max() b = b.max() # Red pixel_list = np.where(np.all(mc_mask_data == (r, 0, 0, 1), axis=-1))[0] if len(pixel_list) > 0: red_index = filter_pixel(pixel_list, texture_data) # Green pixel_list = np.where(np.all(mc_mask_data >= (0, g, 0, 1), axis=-1))[0] if len(pixel_list) > 0: green_index = filter_pixel(pixel_list, texture_data) else: # Green (Yellow) pixel_list = np.where(np.all(mc_mask_data == (r, g, 0, 1), axis=-1))[0] if len(pixel_list) > 0: green_index = filter_pixel(pixel_list, texture_data) # Blue pixel_list = np.where(np.all(mc_mask_data == (0, 0, b, 1), axis=-1))[0] if len(pixel_list) > 0: blue_index = filter_pixel(pixel_list, texture_data) else: # Blue (Cyan) pixel_list = np.where(np.all(mc_mask_data == (0, g, b, 1), axis=-1))[0] if len(pixel_list) > 0: blue_index = filter_pixel(pixel_list, texture_data) else: # Blue (Magenta) pixel_list = np.where(np.all(mc_mask_data == (r, 0, b, 1), axis=-1))[0] if len(pixel_list) > 0: blue_index = filter_pixel(pixel_list, texture_data) else: # Blue (White) pixel_list = np.where( np.all(mc_mask_data == (r, g, b, 1), axis=-1))[0] if len(pixel_list) > 0: blue_index = filter_pixel(pixel_list, texture_data) ########## SCALE INDEXES ########## # mc_w, mc_h = mc_mask.size # tex_w, tex_h = texture.size # scale = int((tex_w * tex_h) / (mc_w * mc_h)) # red_index = red_index * scale # green_index = green_index * scale # blue_index = blue_index * scale ########## GET AND CONVERT COLORS FROM MAIN TEXTURE ########## if red_index >= 0: red_color = texture_data[red_index] red_color = RGBA_to_RGB_int(red_color) red_converted_color_light = color_to_KK(red_color, lut) if green_index >= 0: green_color = texture_data[green_index] green_color = RGBA_to_RGB_int(green_color) green_converted_color_light = color_to_KK(green_color, lut) if blue_index >= 0: blue_color = texture_data[blue_index] blue_color = RGBA_to_RGB_int(blue_color) blue_converted_color_light = color_to_KK(blue_color, lut) # print(red_index) # print(green_index) # print(blue_index) # print(red_converted_color_light) # print(green_converted_color_light) # print(blue_converted_color_light) return red_converted_color_light / 255, green_converted_color_light / 255, blue_converted_color_light / 255
def generate_icon(name, verts=None, faces=None, coll="shape_types"): pcoll = preview_collections[coll] 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_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 = bpy.path.abspath(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 print("Rendering Depth Buffer") if sceneProps.vector_depthtest: with offscreen.bind(): # Clear Depth Buffer, set Clear Depth to Cameras Clip Distance set_OpenGL_Settings(True) 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_FLOAT, width * height) draw_scene(self, context, projection_matrix) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, width, height, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, texture_buffer) if 'depthbuffer' in sceneProps: del sceneProps['depthbuffer'] sceneProps['depthbuffer'] = texture_buffer offscreen.free() set_OpenGL_Settings(False) if False: imageName = 'depthBufferTest' if not imageName in bpy.data.images: bpy.data.images.new(imageName, width, height, alpha=False, float_buffer=True, is_data=True) image = bpy.data.images[imageName] image.scale(width, height) image.pixels = [v for v in texture_buffer] # Setup Output Path ren_path = path filename = "mit_vector" ftxt = "%04d" % scene.frame_current outpath = (ren_path + filename + ftxt + '.svg') view = get_view() paperWidth = width / sceneProps.default_resolution paperHeight = height / sceneProps.default_resolution try: if view.res_type == 'res_type_paper': paperWidth = round(view.width * 39.370078740196853, 3) paperHeight = round(view.height * 39.370078740196853, 3) except: print('No View Present, using default resolution') # Setup basic svg svg = svgwrite.Drawing( outpath, debug=False, size=('{}in'.format(paperWidth), '{}in'.format(paperHeight)), viewBox=('0 0 {} {}'.format(width, height)), id='root', ) if sceneProps.embed_scene_render: lastformat = scene.render.image_settings.file_format scene.render.image_settings.file_format = 'PNG' scene.render.use_file_extension = True bpy.ops.render.render(write_still=True) image_path = bpy.context.scene.render.filepath svg.add( svg.image(os.path.basename(image_path + '.png'), **{ 'width': width, 'height': height })) scene.render.image_settings.file_format = lastformat # ----------------------------- # Loop to draw all objects # ----------------------------- draw3d_loop(context, objlist, svg=svg) draw_titleblock(context, svg=svg) svg.save(pretty=True) # restore default value sceneProps.is_render_draw = False sceneProps.is_vector_draw = False return True
def render_main(self, context, animation=False): scene = context.scene sceneProps = scene.MeasureItArchProps sceneProps.is_render_draw = True clipdepth = context.scene.camera.data.clip_end 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) # Draw all lines in Offsecreen renderoffscreen = 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) set_OpenGL_Settings(True) with renderoffscreen.bind(): # Clear Depth Buffer, set Clear Depth to Cameras Clip Distance bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) bgl.glClearDepth(clipdepth) gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix_3d) gpu.matrix.load_projection_matrix(projection_matrix) # Draw Scene for the depth buffer draw_scene(self, context, projection_matrix) # Clear Color Buffer, we only need the depth info bgl.glClearColor(0, 0, 0, 0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # ----------------------------- # Loop to draw all objects # ----------------------------- draw3d_loop(context, objlist) draw_titleblock(context) 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) # ----------------------------- # Create image # ----------------------------- image_name = "measureit_arch_output" if image_name not in bpy.data.images: image = 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] renderoffscreen.free() # Saves image if image is not None and animation is True: ren_path = bpy.context.scene.render.filepath filename = "mit_frame" ftxt = "%04d" % scene.frame_current outpath = (ren_path + filename + ftxt + '.png') save_image(self, outpath, image) # restore default value set_OpenGL_Settings(False) sceneProps.is_render_draw = False return True, buffer
def draw_callback(self, context): """ :type context: bpy.types.Context """ prefs = QuickBooleanPreferences.get_instance() color = prefs.color snap_color = prefs.snap_color region = context.region glsettings = vagl.GLSettings(context) glsettings.push() bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(*color) show_reversed = False if self.reverse: if self.mode == 'POLYGON': if len(self.mouse_coords) >= 3: show_reversed = True else: if len(self.mouse_coords) >= 2: if self.mouse_coords[0] != self.mouse_coords[1]: show_reversed = True if show_reversed: bgl.glEnable(bgl.GL_DEPTH_TEST) bgl.glClearDepth(1.0) bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) bgl.glDepthMask(1) bgl.glColorMask(0, 0, 0, 0) lines = [] if self.mouse_coords: if self.mode == 'LINE': w = region.width h = region.height p1, p2 = self.mouse_coords line = (p2 - p1).normalized() normal = Vector([-line[1], line[0]]) corners = [Vector([0, 0]), Vector([w, 0]), Vector([w, h]), Vector([0, h])] corners_ofs = [v - p1 for v in corners] dists = [v.project(line).dot(line) for v in corners_ofs] i = dists.index(min(dists)) line_min = corners_ofs[i].project(line) + p1 i = dists.index(max(dists)) line_max = corners_ofs[i].project(line) + p1 dists = [v.project(normal).dot(normal) for v in corners_ofs] i = dists.index(max(dists)) normal_max_f = corners_ofs[i].project(normal).dot(normal) vec = normal * normal_max_f coords = [line_min, line_max, line_max + vec, line_min + vec] bgl.glBegin(bgl.GL_QUADS) for co in coords: bgl.glVertex2f(*co) bgl.glEnd() lines = self.mouse_coords elif self.mode == 'BOX': p1, p2 = self.mouse_coords bgl.glRectf(p1[0], p1[1], p2[0], p2[1]) lines = [p1, Vector((p2[0], p1[1])), Vector((p2[0], p2[1])), Vector((p1[0], p2[1])), p1] elif self.mode == 'CIRCLE': p1, p2 = self.mouse_coords bgl.glBegin(bgl.GL_TRIANGLE_FAN) bgl.glVertex2f(*p1) r = (p2 - p1).length coords = calc_circle_coords(p1, r, self.circle_segments, self.circle_direction) for co in coords: bgl.glVertex2f(*co) bgl.glVertex2f(*coords[0]) bgl.glEnd() lines = coords + [coords[0]] elif self.mode == 'POLYGON': if len(self.mouse_coords) >= 3: tris = mathutils.geometry.tessellate_polygon( [[co.to_3d() for co in self.mouse_coords]]) bgl.glBegin(bgl.GL_TRIANGLES) for tri in tris: for i in tri: bgl.glVertex2f(*self.mouse_coords[i]) bgl.glEnd() if len(self.mouse_coords) > 1: lines = self.mouse_coords + [self.mouse_coords[0]] if show_reversed: bgl.glColorMask(1, 1, 1, 1) bgl.glBegin(bgl.GL_QUADS) bgl.glVertex3f(0, 0, -1) bgl.glVertex3f(region.width, 0, -1) bgl.glVertex3f(region.width, region.height, -1) bgl.glVertex3f(0, region.height, -1) bgl.glEnd() bgl.glDisable(bgl.GL_DEPTH_TEST) bgl.glColor4f(*color[:3], 1.0) bgl.glPointSize(1) bgl.glLineWidth(1) if len(lines) > 1: bgl.glBegin(bgl.GL_LINE_STRIP) for co in lines: bgl.glVertex2f(*co) bgl.glEnd() if self.mode == 'POLYGON': if len(self.mouse_coords) == 1: bgl.glPointSize(5) bgl.glBegin(bgl.GL_POINTS) for co in self.mouse_coords: bgl.glVertex2f(*co) bgl.glEnd() bgl.glPointSize(1) bgl.glLineWidth(1) if self.mco_ctrl: SIZE = 12 bgl.glColor4f(*snap_color) bgl.glBegin(bgl.GL_LINE_LOOP) v = self.mco_mod x = v[0] - SIZE / 2 y = v[1] - SIZE / 2 bgl.glVertex2f(x, y) bgl.glVertex2f(x + SIZE, y) bgl.glVertex2f(x + SIZE, y + SIZE) bgl.glVertex2f(x, y + SIZE) bgl.glEnd() glsettings.pop() glsettings.font_size()
def modal(self, context, event): if event.type in {'ESC'}: self.cancel(context) return {'CANCELLED'} if event.type == 'TIMER': # If there is no reference to source on the text editor, create one if not self.source in bpy.data.texts: print(f'File name {self.source} not found. Will create an internal one') # If match an external file if self.file_exist(self.source): bpy.ops.text.open(filepath=self.source) # else create a internal file with the default fragment code else: bpy.data.texts.new(self.source) bpy.data.texts[self.source].write(self.default_code) # If the source file is external and it have been modify, reload it if not bpy.data.texts[self.source].is_in_memory and bpy.data.texts[self.source].is_modified: print(f'External file {self.source} have been modify. Reloading...') text = bpy.data.texts[self.source] ctx = context.copy() #Ensure context area is not None ctx['area'] = ctx['screen'].areas[0] oldAreaType = ctx['area'].type ctx['area'].type = 'TEXT_EDITOR' ctx['edit_text'] = text bpy.ops.text.resolve_conflict(ctx, resolution='RELOAD') #Restore context ctx['area'].type = oldAreaType render = False recompile = False now = context.scene.frame_float / context.scene.render.fps # If shader content change if self.current_code != bpy.data.texts[self.source].as_string(): recompile = True if self.current_time != now: render = True if render or recompile: self.current_code = bpy.data.texts[self.source].as_string() self.current_time = now offscreen = gpu.types.GPUOffScreen(self.width, self.height) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # If there is no shader or need to be recompiled if self.shader == None or recompile: try: self.shader = gpu.types.GPUShader(self.vertex_default, self.current_code) except Exception as Err: print(Err) self.shader = None # if there is a shader and no batch if (self.shader != None and self.batch == None): self.batch = batch_for_shader( self.shader, 'TRI_FAN', { 'a_position': ((-1, -1), (1, -1), (1, 1), (-1, 1)) }, ) if self.shader != None: self.shader.bind() try: self.shader.uniform_float('u_time', self.current_time) except ValueError: pass try: self.shader.uniform_float('u_resolution', (self.width, self.height)) except ValueError: pass self.batch.draw(self.shader) buffer = bgl.Buffer(bgl.GL_BYTE, self.width * self.height * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, self.width, self.height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) render = True offscreen.free() if render: name = self.source if not name in bpy.data.images: bpy.data.images.new(name, self.width, self.height) image = bpy.data.images[name] image.scale(self.width, self.height) image.pixels = [v / 255 for v in buffer] return {'PASS_THROUGH'}
import gpu import bgl import random from mathutils import Matrix from gpu_extras.presets import draw_circle_2d IMAGE_NAME = "Generated Image" WIDTH = 512 HEIGHT = 512 RING_AMOUNT = 10 offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) with gpu.matrix.push_pop(): # reset matrices -> use normalized device coordinates [-1, 1] gpu.matrix.load_matrix(Matrix.Identity(4)) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) for i in range(RING_AMOUNT): draw_circle_2d( (random.uniform(-1, 1), random.uniform(-1, 1)), (1, 1, 1, 1), random.uniform(0.1, 1), 20) 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()
def execute(self, refholder): # pass tr = self.nodeTree.properties.TextureResolution print("begining execution " + str(tr)) # compute A' mask = np.array([[0.05, 0.2, 0.05], [0.2, -1, 0.2], [0.05, 0.2, 0.05]]) # Input data pixels A = self.inputs[0].getPixels() B = self.inputs[1].getPixels() # print(A) bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, self.rdData[self.name]["prev_program"]) bgl.glUseProgram(self.rdData[self.name]["program"]) #set any uniforms needed bgl.glUniform1f(self.rdData[self.name]["feed_loc"], self.inputs[2].value) bgl.glUniform1f(self.rdData[self.name]["kill_loc"], self.inputs[3].value) bgl.glUniform1f(self.rdData[self.name]["da_loc"], self.inputs[4].value) bgl.glUniform1f(self.rdData[self.name]["db_loc"], self.inputs[5].value) bgl.glUniform1f(self.rdData[self.name]["dt_loc"], self.inputs[6].value) bgl.glUniform1f(self.rdData[self.name]["step_loc"], 1 / tr) bgl.glDisable(bgl.GL_SCISSOR_TEST) bgl.glViewport(0, 0, tr, tr) bgl.glMatrixMode(bgl.GL_MODELVIEW) bgl.glPushMatrix() bgl.glLoadIdentity() bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glPushMatrix() bgl.glLoadIdentity() bgl.gluOrtho2D(0, 1, 0, 1) bgl.glEnable(bgl.GL_TEXTURE_2D) bgl.glActiveTexture(bgl.GL_TEXTURE0) channels = [] if self.channels == '0': channels = [0] elif self.channels == '1': channels = [0, 1, 2] for j in channels: self.rdData[self.name]["npArray"][:, :, 0] = A[:, :, j] self.rdData[self.name]["npArray"][:, :, 1] = B[:, :, j] # Caution: Interfacing with Cython requires toList() self.rdData[self.name]["image"].pixels = self.rdData[ self.name]["npArray"].flatten() self.rdData[self.name]["image"].gl_load(0, bgl.GL_LINEAR, bgl.GL_LINEAR) bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.rdData[self.name]["image"].bindcode[0]) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_REPEAT) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_REPEAT) for i in range(self.inputs[7].value): bgl.glClearDepth(1.0) bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) bgl.glBegin(bgl.GL_TRIANGLES) bgl.glColor3f(1.0, 1.0, 1.0) bgl.glTexCoord2f(0.0, 0.0) bgl.glVertex2f(-1.0, -1.0) bgl.glTexCoord2f(1.0, 0.0) bgl.glVertex2f(1.0, -1.0) bgl.glTexCoord2f(1.0, 1.0) bgl.glVertex2f(1.0, 1.0) bgl.glColor3f(1.0, 1.0, 1.0) bgl.glTexCoord2f(0.0, 0.0) bgl.glVertex2f(-1.0, -1.0) bgl.glTexCoord2f(1.0, 1.0) bgl.glVertex2f(1.0, 1.0) bgl.glTexCoord2f(0.0, 1.0) bgl.glVertex2f(-1.0, 1.0) bgl.glEnd() bgl.glCopyTexImage2D( bgl.GL_TEXTURE_2D, #target 0, #level bgl.GL_RGBA, #internalformat 0, #x 0, #y tr, tr, 0 #border ) #glFlush glFinish or none here? bgl.glFinish() bgl.glReadPixels(0, 0, tr, tr, bgl.GL_RGBA, bgl.GL_FLOAT, self.rdData[self.name]["buffer"]) self.rdData[self.name]["image"].pixels = self.rdData[ self.name]["buffer"][:] #write the image channel npImage = np.asarray(self.rdData[self.name]["image"].pixels, dtype="float") self.rdData[self.name]["npArray"] = npImage.reshape( tr, tr, self.rdData[self.name]["image"].channels) self.outputs[0].setPackedImageFromChannels( self.rdData[self.name]["npArray"][:, :, 0], j, flatten=True) self.outputs[1].setPackedImageFromChannels( self.rdData[self.name]["npArray"][:, :, 1], j, flatten=True) self.outputs[2].setPackedImageFromPixels( self.rdData[self.name]["npArray"]) self.inputs[0].setPackedImageFromChannels( self.rdData[self.name]["npArray"][:, :, 0], j, flatten=True) self.inputs[1].setPackedImageFromChannels( self.rdData[self.name]["npArray"][:, :, 1], j, flatten=True) # ================================= Test bed # self.outputs[0].getTexture().image.copy() # self.outputs[1].getTexture().image.copy() # self.outputs[2].getTexture().image.copy() # nparr = np.asarray(self.outputs[0].getTexture().image.pixels, dtype="float") # nparr = nparr.reshape(tr, tr, 4) # print(nparr) self.rdData[self.name]["image"].gl_free() #restore the state so blender wont break bgl.glEnable(bgl.GL_SCISSOR_TEST) bgl.glUseProgram(self.rdData[self.name]["prev_program"][0]) bgl.glActiveTexture(bgl.GL_TEXTURE0)
def cubemap_to_equirectangular(self, imageList, outputName): # Define the vertex shader vertex_shader = ''' in vec3 aVertexPosition; in vec2 aVertexTextureCoord; out vec2 vTexCoord; void main() { vTexCoord = aVertexTextureCoord; gl_Position = vec4(aVertexPosition, 1); } ''' # Define the fragment shader for the 360 degree conversion fragment_shader_360 = ''' #define PI 3.1415926535897932384626 // Input cubemap textures uniform sampler2D cubeLeftImage; uniform sampler2D cubeRightImage; uniform sampler2D cubeBottomImage; uniform sampler2D cubeTopImage; uniform sampler2D cubeBackImage; uniform sampler2D cubeFrontImage; in vec2 vTexCoord; out vec4 fragColor; void main() { // Calculate the pointing angle float azimuth = vTexCoord.x * PI; float elevation = vTexCoord.y * PI / 2.0; // Calculate the pointing vector vec3 pt; pt.x = cos(elevation) * sin(azimuth); pt.y = sin(elevation); pt.z = cos(elevation) * cos(azimuth); // Select the correct pixel if ((abs(pt.x) >= abs(pt.y)) && (abs(pt.x) >= abs(pt.z))) { if (pt.x <= 0.0) { fragColor = texture(cubeLeftImage, vec2(((-pt.z/pt.x)+1.0)/2.0,((-pt.y/pt.x)+1.0)/2.0)); } else { fragColor = texture(cubeRightImage, vec2(((-pt.z/pt.x)+1.0)/2.0,((pt.y/pt.x)+1.0)/2.0)); } } else if (abs(pt.y) >= abs(pt.z)) { if (pt.y <= 0.0) { fragColor = texture(cubeBottomImage, vec2(((-pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/2.0)); } else { fragColor = texture(cubeTopImage, vec2(((pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/2.0)); } } else { if (pt.z <= 0.0) { fragColor = texture(cubeBackImage, vec2(((pt.x/pt.z)+1.0)/2.0,((-pt.y/pt.z)+1.0)/2.0)); } else { fragColor = texture(cubeFrontImage, vec2(((pt.x/pt.z)+1.0)/2.0,((pt.y/pt.z)+1.0)/2.0)); } } } ''' # Define the fragment shader for the 180 degree conversion fragment_shader_180 = ''' #define PI 3.1415926535897932384626 // Input cubemap textures uniform sampler2D cubeLeftImage; uniform sampler2D cubeRightImage; uniform sampler2D cubeBottomImage; uniform sampler2D cubeTopImage; uniform sampler2D cubeFrontImage; in vec2 vTexCoord; out vec4 fragColor; void main() {{ // Calculate the pointing angle float fovd = {0}; float fovfrac = fovd/360.0; float sidefrac = (fovd-90.0)/180; float azimuth = vTexCoord.x * PI * fovfrac; float elevation = vTexCoord.y * PI / 2.0; // Calculate the pointing vector vec3 pt; pt.x = cos(elevation) * sin(azimuth); pt.y = sin(elevation); pt.z = cos(elevation) * cos(azimuth); // Select the correct pixel if ((abs(pt.x) >= abs(pt.y)) && (abs(pt.x) >= abs(pt.z))) {{ if (pt.x <= 0.0) {{ fragColor = texture(cubeLeftImage, vec2((((-pt.z/pt.x))+(2.0*sidefrac-1.0))/(2.0*sidefrac),((-pt.y/pt.x)+1.0)/2.0)); }} else {{ fragColor = texture(cubeRightImage, vec2(((-pt.z/pt.x)+1.0)/(2.0*sidefrac),((pt.y/pt.x)+1.0)/2.0)); }} }} else if (abs(pt.y) >= abs(pt.z)) {{ if (pt.y <= 0.0) {{ fragColor = texture(cubeBottomImage, vec2(((-pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+(2.0*sidefrac-1.0))/(2.0*sidefrac))); }} else {{ fragColor = texture(cubeTopImage, vec2(((pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/(2.0*sidefrac))); }} }} else {{ fragColor = texture(cubeFrontImage, vec2(((pt.x/pt.z)+1.0)/2.0,((pt.y/pt.z)+1.0)/2.0)); }} }} '''.format(self.FOV) # Define the fragment shader for the dome conversion fragment_shader_dome = ''' #define PI 3.1415926535897932384626 // Input cubemap textures uniform sampler2D cubeLeftImage; uniform sampler2D cubeRightImage; uniform sampler2D cubeBottomImage; uniform sampler2D cubeTopImage; uniform sampler2D cubeFrontImage; uniform sampler2D cubeBackImage; in vec2 vTexCoord; out vec4 fragColor; void main() {{ float fovd = {0}; float fovfrac = fovd/360.0; float sidefrac = (fovd-90.0)/180; float hfov = fovfrac*PI; vec2 d = vTexCoord.xy; float r = length( d ); if( r > 1.0 ) {{ fragColor = vec4(0.0, 0.0, 0.0, 1.0); return; }} vec2 dunit = normalize( d ); float phi = r * hfov; vec3 pt = vec3( 1.0, 1.0, 1.0 ); pt.xy = dunit * sin( phi ); pt.z = cos( phi ); // Select the correct pixel // Select the correct pixel if ((abs(pt.x) >= abs(pt.y)) && (abs(pt.x) >= abs(pt.z))) {{ if (pt.x <= 0.0) {{ fragColor = texture(cubeLeftImage, vec2((((-pt.z/pt.x))+(2.0*sidefrac-1.0))/(2.0*sidefrac),((-pt.y/pt.x)+1.0)/2.0)); }} else {{ fragColor = texture(cubeRightImage, vec2(((-pt.z/pt.x)+1.0)/(2.0*sidefrac),((pt.y/pt.x)+1.0)/2.0)); }} }} else if (abs(pt.y) >= abs(pt.z)) {{ if (pt.y <= 0.0) {{ fragColor = texture(cubeBottomImage, vec2(((-pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+(2.0*sidefrac-1.0))/(2.0*sidefrac))); }} else {{ fragColor = texture(cubeTopImage, vec2(((pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/(2.0*sidefrac))); }} }} else {{ if (pt.z <= 0.0) {{ fragColor = texture(cubeBackImage, vec2(((pt.x/pt.z)+1.0)/2.0,((-pt.y/pt.z)+1.0)/2.0)); }} else {{ fragColor = texture(cubeFrontImage, vec2(((pt.x/pt.z)+1.0)/2.0,((pt.y/pt.z)+1.0)/2.0)); }} }} }} '''.format(self.FOV) # Generate the OpenGL shader pos = [ (-1.0, -1.0, -1.0), # left, bottom, back (-1.0, 1.0, -1.0), # left, top, back (1.0, -1.0, -1.0), # right, bottom, back (1.0, 1.0, -1.0) ] # right, top, back coords = [ (-1.0, -1.0), # left, bottom (-1.0, 1.0), # left, top (1.0, -1.0), # right, bottom (1.0, 1.0) ] # right, top vertexIndices = [(0, 3, 1), (3, 0, 2)] if self.is_dome: shader = gpu.types.GPUShader(vertex_shader, fragment_shader_dome) else: if self.no_back_image: shader = gpu.types.GPUShader(vertex_shader, fragment_shader_180) else: shader = gpu.types.GPUShader(vertex_shader, fragment_shader_360) batch = batch_for_shader(shader, 'TRIS', {"aVertexPosition": pos,\ "aVertexTextureCoord": coords},\ indices=vertexIndices) # Change the color space of all of the images to Linear # and load them into OpenGL textures imageLeft = imageList[0] imageLeft.colorspace_settings.name = 'Linear' imageLeft.gl_load() imageRight = imageList[1] imageRight.colorspace_settings.name = 'Linear' imageRight.gl_load() imageBottom = imageList[2] imageBottom.colorspace_settings.name = 'Linear' imageBottom.gl_load() imageTop = imageList[3] imageTop.colorspace_settings.name = 'Linear' imageTop.gl_load() imageFront = imageList[4] imageFront.colorspace_settings.name = 'Linear' imageFront.gl_load() if not self.no_back_image: imageBack = imageList[5] imageBack.colorspace_settings.name = 'Linear' imageBack.gl_load() # set the size of the final image width = self.image_size[0] height = self.image_size[1] # Create an offscreen render buffer and texture offscreen = gpu.types.GPUOffScreen(width, height) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) shader.bind() # Bind all of the cubemap textures and enable correct filtering and wrapping # to prevent seams bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageLeft.bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) shader.uniform_int("cubeLeftImage", 0) bgl.glActiveTexture(bgl.GL_TEXTURE1) bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageRight.bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) shader.uniform_int("cubeRightImage", 1) bgl.glActiveTexture(bgl.GL_TEXTURE2) bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageBottom.bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) shader.uniform_int("cubeBottomImage", 2) bgl.glActiveTexture(bgl.GL_TEXTURE3) bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageTop.bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) shader.uniform_int("cubeTopImage", 3) bgl.glActiveTexture(bgl.GL_TEXTURE4) bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageFront.bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) shader.uniform_int("cubeFrontImage", 4) if not self.no_back_image: bgl.glActiveTexture(bgl.GL_TEXTURE5) bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageBack.bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) shader.uniform_int("cubeBackImage", 5) # Bind the resulting texture bgl.glActiveTexture(bgl.GL_TEXTURE6) bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) # Render the image batch.draw(shader) # Unload the textures imageLeft.gl_free() imageRight.gl_free() imageBottom.gl_free() imageTop.gl_free() imageFront.gl_free() if not self.no_back_image: imageBack.gl_free() # Read the resulting pixels into a buffer buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # Unload the offscreen texture offscreen.free() # Remove the cubemap textures: for image in imageList: bpy.data.images.remove(image) # Copy the pixels from the buffer to an image object if not outputName in bpy.data.images.keys(): bpy.data.images.new(outputName, width, height) imageRes = bpy.data.images[outputName] imageRes.scale(width, height) imageRes.pixels = buffer return imageRes
def update_all(self): self.drawn_count = 0 self._offset_cur = 1 bgl.glClearColor(0.0, 0.0, 0.0, 0.0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT)
def execute(self, context): # import cProfile, pstats, io # pr = cProfile.Profile() # pr.enable() bgl.glEnable(bgl.GL_PROGRAM_POINT_SIZE) scene = context.scene render = scene.render image_settings = render.image_settings original_depth = image_settings.color_depth image_settings.color_depth = '8' scale = render.resolution_percentage / 100 width = int(render.resolution_x * scale) height = int(render.resolution_y * scale) pcv = context.object.point_cloud_visualizer cloud = PCVManager.cache[pcv.uuid] cam = scene.camera if (cam is None): self.report({'ERROR'}, "No camera found.") return {'CANCELLED'} render_suffix = pcv.render_suffix render_zeros = pcv.render_zeros offscreen = GPUOffScreen(width, height) offscreen.bind() # with offscreen.bind(): try: gpu.matrix.load_matrix(Matrix.Identity(4)) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) o = cloud['object'] vs = cloud['vertices'] cs = cloud['colors'] dp = pcv.display_percent l = int((len(vs) / 100) * dp) if (dp >= 99): l = len(vs) vs = vs[:l] cs = cs[:l] # sort by depth mw = o.matrix_world depth = [] for i, v in enumerate(vs): vw = mw @ Vector(v) depth.append(world_to_camera_view(scene, cam, vw)[2]) zps = zip(depth, vs, cs) sps = sorted(zps, key=lambda a: a[0]) # split and reverse vs = [a for _, a, b in sps][::-1] cs = [b for _, a, b in sps][::-1] shader = GPUShader(vertex_shader, fragment_shader) batch = batch_for_shader(shader, 'POINTS', { "position": vs, "color": cs, }) shader.bind() view_matrix = cam.matrix_world.inverted() camera_matrix = cam.calc_matrix_camera( bpy.context.depsgraph, x=render.resolution_x, y=render.resolution_y, scale_x=render.pixel_aspect_x, scale_y=render.pixel_aspect_y, ) perspective_matrix = camera_matrix @ view_matrix shader.uniform_float("perspective_matrix", perspective_matrix) shader.uniform_float("object_matrix", o.matrix_world) # shader.uniform_float("point_size", pcv.point_size) shader.uniform_float("point_size", pcv.render_point_size) shader.uniform_float("alpha_radius", pcv.alpha_radius) batch.draw(shader) buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) # bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) except Exception as e: self.report({'ERROR'}, str(e)) return {'CANCELLED'} finally: offscreen.unbind() offscreen.free() # offscreen.free() # image from buffer image_name = "pcv_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] # save as image file save_render( self, scene, image, render_suffix, render_zeros, ) # restore image_settings.color_depth = original_depth # pr.disable() # s = io.StringIO() # sortby = 'cumulative' # ps = pstats.Stats(pr, stream=s).sort_stats(sortby) # ps.print_stats() # print(s.getvalue()) return {'FINISHED'}
def _execute_inner(self, obs): dim = self.dim dimhalf = dim * .5 offbuf = gpu.types.GPUOffScreen(dim, dim) sample = sample_sphere if self.dom == 'SPHERE' \ else sample_hemisphere # Construct depthpass shader shader = gpu.types.GPUShader( vertexcode=''' uniform mat4 mvp; in vec3 pos; void main() { gl_Position = mvp * vec4(pos, 1); }''', fragcode=''' out vec4 col; void main() { col = vec4(0, 0, 1, 1); }''' ) shader.bind() # Create batch from all objects in edit mode verts, indcs, geoinfo = combine_meshes(obs) batch = batch_for_shader( shader, 'TRIS', {"pos": verts}, indices=indcs, ) batch.program_set(shader) # Find the center and bounds of all objects to calculate the # encompassing radius of the (hemi-)sphere on which render # positions will be sampled bounds, centr = get_bounds_and_center(verts) rad = np.linalg.norm(bounds[:2]) * .5 + 1 del indcs, bounds # Spawn debug sphere with calculated radius if self._debug_spawn_sphere: bpy.ops.mesh.primitive_uv_sphere_add( radius=rad, location=centr, ) # Render the objects from several views and mark seen vertices visibl = np.zeros(len(verts), dtype=np.bool) for _ in range(self.samplecnt): # Generate random points on the chosen domain from which # to render the objects # Chose rotation so the 'camera' looks to the center samplepos, (theta, phi) = sample(rad) view_mat_inv = make_transf_mat( transl=samplepos + centr, rot=(phi, 0, theta + np.pi * .5), ) # Spawn debug camera at sampled position if self._debug_spawn_cams: bpy.ops.object.camera_add() bpy.context.object.matrix_world = Matrix(view_mat_inv) # Build the Model View Projection matrix from chosen # render position and radius # The model matrix has already been applied to the vertices # befor creating the batch mvp = make_proj_mat( fov=90, clip_start=rad * .25, clip_end=rad * 1.5, dimx=dim, dimy=dim, ) @ np.linalg.inv(view_mat_inv) shader.uniform_float("mvp", Matrix(mvp)) del view_mat_inv, samplepos, theta, phi with offbuf.bind(): # Render the selected objects into the offscreen buffer bgl.glDepthMask(bgl.GL_TRUE) bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) bgl.glEnable(bgl.GL_DEPTH_TEST) batch.draw() # Write texture back to CPU pxbuf = bgl.Buffer(bgl.GL_FLOAT, dim * dim) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, dim, dim, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, pxbuf) # Map depth values from [0, 1] to [-1, 1] pxbuf = np.asanyarray(pxbuf) * 2 - 1 pxbuf.shape = (dim, dim) # Transform verts of active object to clip space tverts = mvp @ append_one(verts).T # Perspective divide to transform to NDCs [-1, 1] tverts /= tverts[3] # Find pixel coordinates of each vertex' projected position # by remapping x and y coordinates from NDCs to [0, dim] # Add .5 to make sure the flooring from conversion to int # is actually rounding uvs = tverts[:2] * dimhalf + (dimhalf + .5) uvs = uvs.astype(np.int32) # Map all vertices outside the view frustum to (0, 0) # so they don't sample the pixel array out of bounds invalid = np.any((uvs < 0) | (dim <= uvs), axis=0) uvs.T[invalid] = (0, 0) # For each vertex, get the depth at its projected pixel # and its distance to the render position imgdpth = pxbuf[(uvs[1], uvs[0])] camdist = tverts[2] # Set the distance of invalid vertices past [-1, 1] so they # won't be selected camdist[invalid] = 2 # A vertex is visible if it's inside the view frustum # (valid) and not occluded by any face. # A vertex is occluded when its depth sampled from the # image is smaller than its distance to the camera. # A small error margin is added to prevent self-occlusion. # The result is logically or-ed with the result from other # render positions. visibl |= camdist <= (imgdpth + .001) # Create debug image of the rendered view if self._debug_create_img: # Grayscale to RGBA and [-1, 1] to [0, 1] pxbuf = np.repeat(pxbuf, 4) * .5 + .5 pxbuf.shape = (dim, dim, 4) # Alpha channel is 1 pxbuf[:, :, 3] = 1 # Mark projected vertex positions in red pxbuf[(uvs[1], uvs[0])] = (1, 0, 0, 1) imgname = "Debug" if imgname not in bpy.data.images: bpy.data.images.new(imgname, dim, dim) image = bpy.data.images[imgname] image.scale(dim, dim) image.pixels = pxbuf.ravel() # Split visible flag list back in original objects offbuf.free() start = 0 for o, (end, _) in zip(obs, geoinfo): o.data.vertices.foreach_set('select', visibl[start:end]) start = end
def make_equirectangular_from_sky(base_path, sky_name): textures = [ sky_name + "_up", sky_name + "_dn", sky_name + "_ft", sky_name + "_bk", sky_name + "_lf", sky_name + "_rt" ] cube = [None for x in range(6)] biggest_h = 1 biggest_w = 1 for index, tex in enumerate(textures): image = Image.load_file(base_path + "/" + tex) if image != None: cube[index] = image if image.gl_load(): raise Exception() if biggest_h < image.size[1]: biggest_h = image.size[1] if biggest_w < image.size[0]: biggest_w = image.size[0] equi_w = min(8192, biggest_w * 4) equi_h = min(4096, biggest_h * 2) offscreen = gpu.types.GPUOffScreen(equi_w, equi_h) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) with gpu.matrix.push_pop(): # reset matrices -> use normalized device coordinates [-1, 1] gpu.matrix.load_matrix(Matrix.Identity(4)) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) if cube[0] != None: bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, cube[0].bindcode) if cube[1] != None: bgl.glActiveTexture(bgl.GL_TEXTURE1) bgl.glBindTexture(bgl.GL_TEXTURE_2D, cube[1].bindcode) if cube[2] != None: bgl.glActiveTexture(bgl.GL_TEXTURE2) bgl.glBindTexture(bgl.GL_TEXTURE_2D, cube[2].bindcode) if cube[3] != None: bgl.glActiveTexture(bgl.GL_TEXTURE3) bgl.glBindTexture(bgl.GL_TEXTURE_2D, cube[3].bindcode) if cube[4] != None: bgl.glActiveTexture(bgl.GL_TEXTURE4) bgl.glBindTexture(bgl.GL_TEXTURE_2D, cube[4].bindcode) if cube[5] != None: bgl.glActiveTexture(bgl.GL_TEXTURE5) bgl.glBindTexture(bgl.GL_TEXTURE_2D, cube[5].bindcode) #now draw shader.bind() shader.uniform_int("tex_up", 0) shader.uniform_int("tex_dn", 1) shader.uniform_int("tex_ft", 2) shader.uniform_int("tex_bk", 3) shader.uniform_int("tex_lf", 4) shader.uniform_int("tex_rt", 5) shader.uniform_float("clamp_value", 1.0 / biggest_h) batch.draw(shader) buffer = bgl.Buffer(bgl.GL_FLOAT, equi_w * equi_h * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, equi_w, equi_h, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) offscreen.free() image = bpy.data.images.get(sky_name) if image == None: image = bpy.data.images.new(sky_name, width=equi_w, height=equi_h) image.scale(equi_w, equi_h) image.pixels = buffer image.pack() return image
def image_to_KK(image, lut_name): width = image.size[0] height = image.size[1] # Some Sauce vertex_default = ''' in vec2 a_position; in vec2 a_texcoord; void main() { gl_Position = vec4(a_position, 0.0, 1.0); } ''' # The Secret Sauce current_code = ''' uniform sampler2D tex0; uniform sampler2D lut; uniform vec2 u_resolution; vec3 to_srgb(vec3 c){ c.rgb = max( 1.055 * pow( c.rgb, vec3(0.416666667,0.416666667,0.416666667) ) - 0.055, 0 ); return c; } vec3 apply_lut(vec3 color) { const vec3 coord_scale = vec3(0.0302734375, 0.96875, 31.0); const vec3 coord_offset = vec3( 0.5/1024, 0.5/32, 0.0); const vec2 texel_height_X0 = vec2( 0.03125, 0.0 ); vec3 coord = color * coord_scale + coord_offset; vec3 coord_frac = fract( coord ); vec3 coord_floor = coord - coord_frac; vec2 coord_bot = coord.xy + coord_floor.zz * texel_height_X0; vec2 coord_top = coord_bot + texel_height_X0; vec3 lutcol_bot = texture2D( lut, coord_bot ).rgb; vec3 lutcol_top = texture2D( lut, coord_top ).rgb; vec3 lutColor = mix(lutcol_bot, lutcol_top, coord_frac.z); return lutColor; } void main() { vec4 texRGBA = texture2D(tex0, gl_FragCoord.xy / u_resolution); vec3 texColor = to_srgb(texRGBA.rgb); vec3 newColor = apply_lut(texColor); newColor = to_srgb(newColor); gl_FragColor = vec4(newColor.rgb, texRGBA.a); } ''' # This object gives access to off screen buffers. offscreen = gpu.types.GPUOffScreen(width, height) # Context manager to ensure balanced bind calls, even in the case of an error. # Only run if valid with offscreen.bind(): # Clear buffers to preset values bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # Initialize the shader # GPUShader combines multiple GLSL shaders into a program used for drawing. # It must contain a vertex and fragment shaders, with an optional geometry shader. shader = gpu.types.GPUShader(vertex_default, current_code) # Initialize the shader batch # It makes sure that all the vertex attributes necessary for a specific shader are provided. batch = batch_for_shader( shader, 'TRI_FAN', {'a_position': ((-1, -1), (1, -1), (1, 1), (-1, 1))}, ) # Bind the shader object. Required to be able to change uniforms of this shader. shader.bind() bgl.glUniform1i(bgl.glGetUniformLocation(shader.program, "tex0"), 0) bgl.glUniform1i(bgl.glGetUniformLocation(shader.program, "lut"), 1) try: # Make sure image has a bindcode if image.bindcode == 0: for i in range(0, 20): image.gl_load() if image.bindcode != 0: break # https://docs.blender.org/api/current/bgl.html bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) # Specify the value of a uniform variable for the current program object. # In this case, an image. shader.uniform_int("tex0", 0) except ValueError: pass try: lut_image = bpy.data.images[lut_name] # Make sure image has a bindcode if lut_image.bindcode == 0: for i in range(0, 20): lut_image.gl_load() if lut_image.bindcode != 0: break # https://docs.blender.org/api/current/bgl.html bgl.glActiveTexture(bgl.GL_TEXTURE1) bgl.glBindTexture(bgl.GL_TEXTURE_2D, lut_image.bindcode) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) # Specify the value of a uniform variable for the current program object. # In this case, an image. shader.uniform_int("lut", 1) except ValueError: pass try: shader.uniform_float('u_resolution', (width, height)) except ValueError: pass # Run the drawing program with the parameters assigned to the batch. batch.draw(shader) # The Buffer object is simply a block of memory that is delineated and initialized by the user. buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4) # Select a color buffer source for pixels. bgl.glReadBuffer(bgl.GL_BACK) # Read a block of pixels from the frame buffer. bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) # Free the offscreen object. The framebuffer, texture and render objects will no longer be accessible. offscreen.free() # Return the final buffer-pixels pixels = [v / 255 for v in buffer] return pixels, width, height
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 draw_lasso_shader(self): # create batches vertices = [Vector(v) for v in self.lasso_poly] vertices.append(Vector(self.lasso_poly[0])) lengths = [0] for a, b in zip(vertices[:-1], vertices[1:]): lengths.append(lengths[-1] + (a - b).length) bbox_vertices = ((self.lasso_xmin, self.lasso_ymax), (self.lasso_xmin, self.lasso_ymin), (self.lasso_xmax, self.lasso_ymin), (self.lasso_xmax, self.lasso_ymax)) fill_batch = batch_for_shader(fill_shader, 'TRI_FAN', {"pos": vertices}) border_batch = batch_for_shader(border_shader, 'LINE_STRIP', { "pos": vertices, "len": lengths }) stencil_batch = batch_for_shader(fill_shader, 'TRI_FAN', {"pos": bbox_vertices}) matrix = gpu.matrix.get_projection_matrix() segment_color = (1.0, 1.0, 1.0, 1.0) gap_color = (0.2, 0.2, 0.2, 1.0) shadow_color = (0.3, 0.3, 0.3, 1.0) fill_color = (1.0, 1.0, 1.0, 0.04) # stencil mask # https://stackoverflow.com/a/25468363/5106051 glClear(GL_STENCIL_BUFFER_BIT) glEnable(GL_STENCIL_TEST) glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) glStencilFunc(GL_ALWAYS, 0, 1) glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT) glStencilMask(1) fill_shader.bind() fill_shader.uniform_float("u_ViewProjectionMatrix", matrix) fill_shader.uniform_vector_float(self.unif_fill_color, pack("4f", *fill_color), 4) fill_batch.draw(fill_shader) glStencilFunc(GL_EQUAL, 1, 1) glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) # fill glEnable(GL_BLEND) stencil_batch.draw(fill_shader) glDisable(GL_BLEND) dashed = 0 if self.curr_behavior == 'CONTAIN' else 1 if not dashed: # solid border shadow glLineWidth(3) border_shader.bind() border_shader.uniform_float("u_ViewProjectionMatrix", matrix) border_shader.uniform_int("u_Dashed", dashed) border_shader.uniform_vector_float(self.unif_segment_color, pack("4f", *shadow_color), 4) border_batch.draw(border_shader) glLineWidth(1) # solid border glDisable(GL_STENCIL_TEST) border_shader.uniform_vector_float(self.unif_segment_color, pack("4f", *segment_color), 4) border_batch.draw(border_shader) else: # dashed border glDisable(GL_STENCIL_TEST) border_shader.bind() border_shader.uniform_float("u_ViewProjectionMatrix", matrix) border_shader.uniform_int("u_Dashed", dashed) border_shader.uniform_vector_float(self.unif_segment_color, pack("4f", *segment_color), 4) border_shader.uniform_vector_float(self.unif_gap_color, pack("4f", *gap_color), 4) border_batch.draw(border_shader)
def draw(self, context): log("Draw") if not self.is_synced: return stage = self.stage if not stage: return view_settings = ViewSettings(context) if view_settings.width * view_settings.height == 0: return gf_camera = view_settings.export_camera() self.renderer.SetCameraState( gf_camera.frustum.ComputeViewMatrix(), gf_camera.frustum.ComputeProjectionMatrix()) self.renderer.SetRenderViewport( (*view_settings.border[0], *view_settings.border[1])) self.renderer.SetRendererAov('color') self.render_params.renderResolution = (view_settings.width, view_settings.height) self.render_params.clipPlanes = [ Gf.Vec4d(i) for i in gf_camera.clippingPlanes ] if self.shading_data.type == 'MATERIAL' and self.is_gl_delegate: l = Glf.SimpleLight() l.ambient = (0, 0, 0, 0) l.position = (*gf_camera.frustum.position, 1) mat = Glf.SimpleMaterial() self.renderer.SetLightingState((l, ), mat, (0, 0, 0, 0)) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) self.render_engine.bind_display_space_shader(context.scene) if usd_utils.get_renderer_percent_done(self.renderer) == 0.0: self.time_begin = time.perf_counter() try: self.renderer.Render(stage.GetPseudoRoot(), self.render_params) except Exception as e: if isinstance(e, Tf.ErrorException ) and "GL error: invalid operation" in str(e): pass # we won't log error "GL error: invalid operation" else: log.error(e) self.render_engine.unbind_display_space_shader() # additional clear of GL depth buffer which provides blender to draw viewport grid bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) elapsed_time = time_str(time.perf_counter() - self.time_begin) if not self.renderer.IsConverged(): self.notify_status( f"Time: {elapsed_time} | " f"Done: {int(usd_utils.get_renderer_percent_done(self.renderer))}%", "Render") else: self.notify_status(f"Time: {elapsed_time}", "Rendering Done", False)
def render_main(self, context, animation=False): # Save old info bgl.glEnable(bgl.GL_MULTISAMPLE) settings = bpy.context.scene.render.image_settings depth = settings.color_depth settings.color_depth = '16' scene = context.scene 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) # -------------------------------------- # 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]]) view_matrix_3d = scene.camera.matrix_world.inverted() projection_matrix = scene.camera.calc_matrix_camera(context.view_layer.depsgraph, x=width, y=height) scene.measureit_arch_is_render_draw = True with offscreen.bind(): # Clear Depth Buffer, set Clear Depth to Cameras Clip Distance bgl.glClearDepth(clipdepth) bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) # Draw Scene If Necessary if scene.measureit_arch_use_depth_clipping is True: draw_scene(self, context, projection_matrix) # Clear Color Keep on depth info bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # ----------------------------- # Loop to draw all objects # ----------------------------- for myobj in objlist: if myobj.visible_get() is True: if 'DimensionGenerator' in myobj: measureGen = myobj.DimensionGenerator[0] for linDim in measureGen.alignedDimensions: draw_alignedDimension(context, myobj, measureGen,linDim) for dim in measureGen.angleDimensions: draw_angleDimension(context, myobj, measureGen,dim) if 'LineGenerator' in myobj: # Set 3D Projection Martix gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix_3d) gpu.matrix.load_projection_matrix(projection_matrix) # Draw Line Groups op = myobj.LineGenerator[0] draw_line_group(context, myobj, op) if 'AnnotationGenerator' in myobj: # Set 3D Projection Martix gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix_3d) gpu.matrix.load_projection_matrix(projection_matrix) # Draw Line Groups op = myobj.AnnotationGenerator[0] draw_annotation(context, myobj, op) # ----------------------------- # Loop to draw all debug # ----------------------------- if scene.measureit_arch_debug is True: selobj = bpy.context.selected_objects for myobj in selobj: if scene.measureit_arch_debug_objects is True: draw_object(context, myobj, None, None) elif scene.measureit_arch_debug_object_loc is True: draw_object(context, myobj, None, None) if scene.measureit_arch_debug_vertices is True: draw_vertices(context, myobj, None, None) elif scene.measureit_arch_debug_vert_loc is True: draw_vertices(context, myobj, None, None) if scene.measureit_arch_debug_edges is True: draw_edges(context, myobj, None, None) if scene.measureit_arch_debug_faces is True or scene.measureit_arch_debug_normals is True: draw_faces(context, myobj, None, None) # ----------------------------- # Draw a rectangle frame # ----------------------------- if scene.measureit_arch_rf is True: rfcolor = scene.measureit_arch_rf_color rfborder = scene.measureit_arch_rf_border rfline = scene.measureit_arch_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)) 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() scene.measureit_arch_is_render_draw = False # ----------------------------- # Create image # ----------------------------- image_name = "measureit_arch_output" 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] # Saves image if image is not None and (scene.measureit_arch_render is True or animation is True): ren_path = bpy.context.scene.render.filepath filename = "mit_frame" ftxt = "%04d" % scene.frame_current outpath = (ren_path + filename + ftxt + ".png") save_image(self, outpath, image) # restore default value settings.color_depth = depth
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_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, filepath=temp_filepath, compression=15) 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})
#. Draw the generated texture using the new shader. """ import bpy import gpu import bgl from mathutils import Matrix from gpu_extras.batch import batch_for_shader from gpu_extras.presets import draw_circle_2d # Create and fill offscreen ########################################## offscreen = gpu.types.GPUOffScreen(512, 512) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) with gpu.matrix.push_pop(): # reset matrices -> use normalized device coordinates [-1, 1] gpu.matrix.load_matrix(Matrix.Identity(4)) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) amount = 10 for i in range(-amount, amount + 1): x_pos = i / amount draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200) # Drawing the generated texture in 3D space ############################################# vertex_shader = '''
def render_main(self, context, animation=False): # Save old info scene = context.scene sceneProps= scene.MeasureItArchProps sceneProps.is_render_draw = True bgl.glEnable(bgl.GL_MULTISAMPLE) clipdepth = context.scene.camera.data.clip_end 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) # -------------------------------------- # 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]]) view_matrix_3d = scene.camera.matrix_world.inverted() projection_matrix = scene.camera.calc_matrix_camera(context.view_layer.depsgraph, x=width, y=height) 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) draw_scene(self, context, projection_matrix) # Clear Color Keep on depth info bgl.glClearColor(0,0,0,0) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) # ----------------------------- # Loop to draw all objects # ----------------------------- for myobj in objlist: if myobj.visible_get() is True: mat = myobj.matrix_world sheetGen = myobj.SheetGenerator for sheet_view in sheetGen.sheet_views: draw_sheet_views(context,myobj,sheetGen,sheet_view,mat) if 'DimensionGenerator' in myobj: measureGen = myobj.DimensionGenerator[0] if 'alignedDimensions' in measureGen: for linDim in measureGen.alignedDimensions: draw_alignedDimension(context, myobj, measureGen,linDim,mat) if 'angleDimensions' in measureGen: for dim in measureGen.angleDimensions: draw_angleDimension(context, myobj, measureGen,dim,mat) if 'axisDimensions' in measureGen: for dim in measureGen.axisDimensions: draw_axisDimension(context, myobj, measureGen,dim,mat) if 'boundsDimensions' in measureGen: for dim in measureGen.boundsDimensions: draw_boundsDimension(context, myobj, measureGen,dim,mat) if 'arcDimensions' in measureGen: for dim in measureGen.arcDimensions: draw_arcDimension(context, myobj, measureGen,dim,mat) if 'areaDimensions' in measureGen: for dim in measureGen.areaDimensions: draw_areaDimension(context, myobj, measureGen,dim,mat) if 'LineGenerator' in myobj: # Set 3D Projection Martix gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix_3d) gpu.matrix.load_projection_matrix(projection_matrix) # Draw Line Groups op = myobj.LineGenerator[0] draw_line_group(context, myobj, op, mat) if 'AnnotationGenerator' in myobj: # Set 3D Projection Martix gpu.matrix.reset() gpu.matrix.load_matrix(view_matrix_3d) gpu.matrix.load_projection_matrix(projection_matrix) # Draw Line Groups op = myobj.AnnotationGenerator[0] draw_annotation(context, myobj, op, mat) # 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) 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_arch_output" 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] # Saves image if image is not None and (scene.measureit_arch_render is True or animation is True): ren_path = bpy.context.scene.render.filepath filename = "mit_frame" ftxt = "%04d" % scene.frame_current outpath = (ren_path + filename + ftxt + '.png') save_image(self, outpath, image) # restore default value sceneProps.is_render_draw = False return True, buffer
def draw_callback(self, context): """ :type context: bpy.types.Context """ prefs = QuickBooleanPreferences.get_instance() color = prefs.color snap_color = prefs.snap_color region = context.region glsettings = vagl.GLSettings(context) glsettings.push() bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(*color) show_reversed = False if self.reverse: if self.mode == 'POLYGON': if len(self.mouse_coords) >= 3: show_reversed = True else: if len(self.mouse_coords) >= 2: if self.mouse_coords[0] != self.mouse_coords[1]: show_reversed = True if show_reversed: bgl.glEnable(bgl.GL_DEPTH_TEST) bgl.glClearDepth(1.0) bgl.glClear(bgl.GL_DEPTH_BUFFER_BIT) bgl.glDepthMask(1) bgl.glColorMask(0, 0, 0, 0) lines = [] if self.mouse_coords: if self.mode == 'LINE': w = region.width h = region.height p1, p2 = self.mouse_coords line = (p2 - p1).normalized() normal = Vector([-line[1], line[0]]) corners = [ Vector([0, 0]), Vector([w, 0]), Vector([w, h]), Vector([0, h]) ] corners_ofs = [v - p1 for v in corners] dists = [v.project(line).dot(line) for v in corners_ofs] i = dists.index(min(dists)) line_min = corners_ofs[i].project(line) + p1 i = dists.index(max(dists)) line_max = corners_ofs[i].project(line) + p1 dists = [v.project(normal).dot(normal) for v in corners_ofs] i = dists.index(max(dists)) normal_max_f = corners_ofs[i].project(normal).dot(normal) vec = normal * normal_max_f coords = [line_min, line_max, line_max + vec, line_min + vec] bgl.glBegin(bgl.GL_QUADS) for co in coords: bgl.glVertex2f(*co) bgl.glEnd() lines = self.mouse_coords elif self.mode == 'BOX': p1, p2 = self.mouse_coords bgl.glRectf(p1[0], p1[1], p2[0], p2[1]) lines = [ p1, Vector((p2[0], p1[1])), Vector((p2[0], p2[1])), Vector((p1[0], p2[1])), p1 ] elif self.mode == 'CIRCLE': p1, p2 = self.mouse_coords bgl.glBegin(bgl.GL_TRIANGLE_FAN) bgl.glVertex2f(*p1) r = (p2 - p1).length coords = calc_circle_coords(p1, r, self.circle_segments, self.circle_direction) for co in coords: bgl.glVertex2f(*co) bgl.glVertex2f(*coords[0]) bgl.glEnd() lines = coords + [coords[0]] elif self.mode == 'POLYGON': if len(self.mouse_coords) >= 3: tris = mathutils.geometry.tessellate_polygon( [[co.to_3d() for co in self.mouse_coords]]) bgl.glBegin(bgl.GL_TRIANGLES) for tri in tris: for i in tri: bgl.glVertex2f(*self.mouse_coords[i]) bgl.glEnd() if len(self.mouse_coords) > 1: lines = self.mouse_coords + [self.mouse_coords[0]] if show_reversed: bgl.glColorMask(1, 1, 1, 1) bgl.glBegin(bgl.GL_QUADS) bgl.glVertex3f(0, 0, -1) bgl.glVertex3f(region.width, 0, -1) bgl.glVertex3f(region.width, region.height, -1) bgl.glVertex3f(0, region.height, -1) bgl.glEnd() bgl.glDisable(bgl.GL_DEPTH_TEST) bgl.glColor4f(*color[:3], 1.0) bgl.glPointSize(1) bgl.glLineWidth(1) if len(lines) > 1: bgl.glBegin(bgl.GL_LINE_STRIP) for co in lines: bgl.glVertex2f(*co) bgl.glEnd() if self.mode == 'POLYGON': if len(self.mouse_coords) == 1: bgl.glPointSize(5) bgl.glBegin(bgl.GL_POINTS) for co in self.mouse_coords: bgl.glVertex2f(*co) bgl.glEnd() bgl.glPointSize(1) bgl.glLineWidth(1) if self.mco_ctrl: SIZE = 12 bgl.glColor4f(*snap_color) bgl.glBegin(bgl.GL_LINE_LOOP) v = self.mco_mod x = v[0] - SIZE / 2 y = v[1] - SIZE / 2 bgl.glVertex2f(x, y) bgl.glVertex2f(x + SIZE, y) bgl.glVertex2f(x + SIZE, y + SIZE) bgl.glVertex2f(x, y + SIZE) bgl.glEnd() glsettings.pop() glsettings.font_size()
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 glsl_draw(self) -> None: glsl_draw_obj: Optional[GlslDrawObj] = None if GlslDrawObj.myinstance is None and GlslDrawObj.draw_func is None: glsl_draw_obj = GlslDrawObj() glsl_draw_obj.build_scene() else: glsl_draw_obj = GlslDrawObj.myinstance if glsl_draw_obj is None: raise Exception("glsl draw obj is None") light = glsl_draw_obj.light if light is None: raise Exception("no light exists") model_offset = Matrix.Translation((glsl_draw_obj.draw_x_offset, 0, 0)) light_pos = [ i + n for i, n in zip(light.location, [-glsl_draw_obj.draw_x_offset, 0, 0]) ] batches = glsl_draw_obj.batches if batches is None: raise Exception("batches is None") depth_shader = glsl_draw_obj.depth_shader if depth_shader is None: raise Exception("depth shader is None") toon_shader = glsl_draw_obj.toon_shader if toon_shader is None: raise Exception("toon shader is None") offscreen = glsl_draw_obj.offscreen if offscreen is None: raise Exception("offscreen is None") # need bone etc changed only update depth_matrix = None light_lookat = light.rotation_euler.to_quaternion() @ Vector((0, 0, -1)) # TODO このへん tar = light_lookat.normalized() up = light.rotation_euler.to_quaternion() @ Vector((0, 1, 0)) tmp_bound_len = Vector(glsl_draw_obj.bounding_center).length camera_bias = 0.2 loc = Vector( [ glsl_draw_obj.bounding_center[i] + tar[i] * (tmp_bound_len + camera_bias) for i in range(3) ] ) loc = model_offset @ loc v_matrix = lookat_cross(loc, tar, up) const_proj = 2 * max(glsl_draw_obj.bounding_size) / 2 p_matrix = ortho_proj_mat( -const_proj, const_proj, -const_proj, const_proj, -const_proj, const_proj ) depth_matrix = v_matrix @ p_matrix # reuse in main shader depth_matrix.transpose() # region shader depth path with offscreen.bind(): bgl.glClearColor(10, 10, 10, 1) bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) for bat in batches: mat = bat[0] mat.update() depth_bat = bat[2] depth_shader.bind() bgl.glEnable(bgl.GL_BLEND) if mat.alpha_method == "TRANSPARENT": bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) bgl.glDepthMask(bgl.GL_TRUE) bgl.glEnable(bgl.GL_DEPTH_TEST) elif mat.alpha_method == "OPAQUE": bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO) bgl.glDepthMask(bgl.GL_TRUE) bgl.glEnable(bgl.GL_DEPTH_TEST) elif mat.alpha_method == "CLIP": bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO) bgl.glDepthMask(bgl.GL_TRUE) bgl.glEnable(bgl.GL_DEPTH_TEST) if mat.cull_mode == "BACK": bgl.glEnable(bgl.GL_CULL_FACE) bgl.glCullFace(bgl.GL_BACK) else: bgl.glDisable(bgl.GL_CULL_FACE) bgl.glEnable(bgl.GL_CULL_FACE) # そも輪郭線がの影は落ちる? bgl.glCullFace(bgl.GL_BACK) depth_shader.uniform_float( "obj_matrix", model_offset ) # obj.matrix_world) depth_shader.uniform_float("depthMVP", depth_matrix) depth_bat.draw(depth_shader) # endregion shader depth path # region shader main vp_mat = bpy.context.region_data.perspective_matrix projection_mat = bpy.context.region_data.window_matrix view_dir = bpy.context.region_data.view_matrix[2][:3] view_up = bpy.context.region_data.view_matrix[1][:3] normal_world_to_view_matrix = ( bpy.context.region_data.view_matrix.inverted_safe().transposed() ) aspect = bpy.context.area.width / bpy.context.area.height for is_outline in [0, 1]: for bat in batches: toon_bat = bat[1] toon_shader.bind() mat = bat[0] if is_outline == 1 and mat.float_dic["OutlineWidthMode"] == 0: continue # mat.update() #already in depth path bgl.glEnable(bgl.GL_BLEND) bgl.glDepthMask(bgl.GL_TRUE) bgl.glEnable(bgl.GL_DEPTH_TEST) if mat.alpha_method == "TRANSPARENT": bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) elif mat.alpha_method == "OPAQUE": bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO) elif mat.alpha_method == "CLIP": bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO) if is_outline == 0: if mat.cull_mode == "BACK": bgl.glEnable(bgl.GL_CULL_FACE) bgl.glCullFace(bgl.GL_BACK) else: bgl.glDisable(bgl.GL_CULL_FACE) else: bgl.glEnable(bgl.GL_CULL_FACE) bgl.glCullFace(bgl.GL_BACK) toon_shader.uniform_float( "obj_matrix", model_offset ) # obj.matrix_world) toon_shader.uniform_float("projectionMatrix", projection_mat) toon_shader.uniform_float("viewProjectionMatrix", vp_mat) toon_shader.uniform_float("viewDirection", view_dir) toon_shader.uniform_float("viewUpDirection", view_up) toon_shader.uniform_float( "normalWorldToViewMatrix", normal_world_to_view_matrix ) toon_shader.uniform_float("depthMVP", depth_matrix) toon_shader.uniform_float("lightpos", light_pos) toon_shader.uniform_float("aspect", aspect) toon_shader.uniform_float("is_outline", is_outline) toon_shader.uniform_float("isDebug", 0.0) toon_shader.uniform_float( "is_cutout", 1.0 if mat.alpha_method == "CLIP" else 0.0 ) float_keys = [ "CutoffRate", "BumpScale", "ReceiveShadowRate", "ShadeShift", "ShadeToony", "RimLightingMix", "RimFresnelPower", "RimLift", "ShadingGradeRate", "LightColorAttenuation", "IndirectLightIntensity", "OutlineWidth", "OutlineScaleMaxDistance", "OutlineLightingMix", "UV_Scroll_X", "UV_Scroll_Y", "UV_Scroll_Rotation", "OutlineWidthMode", "OutlineColorMode", ] for k in float_keys: toon_shader.uniform_float(k, mat.float_dic[k]) for k, v in mat.vector_dic.items(): toon_shader.uniform_float(k, v) bgl.glActiveTexture(bgl.GL_TEXTURE0) bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture) bgl.glTexParameteri( bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE ) # TODO bgl.glTexParameteri( bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE ) toon_shader.uniform_int("depth_image", 0) for i, k in enumerate(mat.texture_dic.keys()): bgl.glActiveTexture(bgl.GL_TEXTURE1 + i) texture = mat.texture_dic[k] bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.bindcode) bgl.glTexParameteri( bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE ) # TODO bgl.glTexParameteri( bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE ) toon_shader.uniform_int(k, 1 + i) toon_bat.draw(toon_shader)
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, do_unlink=True) 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, do_unlink=True) # 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 modal(self, context, event): # if event.type in {'ESC'}: # self.cancel(context) # return {'CANCELLED'} if event.type == 'TIMER': if not self.source in bpy.data.texts: print( f'File name {self.source} not found. Ready to create one') if self.file_exist(self.source): print("It's a file") bpy.ops.text.open(filepath=self.source) self.fromFile = True else: bpy.data.texts.new(self.source) print("It's not a file, populate with the default shader") bpy.data.texts[self.source].write(self.default_shader) recompile = False if not bpy.data.texts[self.source].is_in_memory and bpy.data.texts[ self.source].is_modified: print("Have been modify") # bpy.ops.text.resolve_conflict(resolution='RELOAD') # self.file_reload(self.source) text = bpy.data.texts[self.source] ctx = context.copy() # ctx["edit_text"] = text # bpy.ops.text.reload(ctx) #Ensure context area is not None ctx['area'] = ctx['screen'].areas[0] oldAreaType = ctx['area'].type ctx['area'].type = 'TEXT_EDITOR' ctx['edit_text'] = text bpy.ops.text.resolve_conflict(ctx, resolution='RELOAD') #Restore context ctx['area'].type = oldAreaType if self.current_shader != bpy.data.texts[self.source].as_string(): recompile = True if recompile: print("Recompile... ") fragment_shader = bpy.data.texts[self.source].as_string() self.current_shader = fragment_shader offscreen = gpu.types.GPUOffScreen(self.width, self.height) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) try: shader = gpu.types.GPUShader(self.vertex_shader, fragment_shader) except Exception as Err: print(Err) recompile = False if recompile: batch = batch_for_shader( shader, 'TRI_FAN', { 'a_position': ((-1, -1), (1, -1), (1, 1), (-1, 1)) }, ) shader.bind() # try: # shader.uniform_float('u_time', bpy.context.scene.frame_float/bpy.context.scene.render.fps) # except ValueError: # print('Uniform: u_time not used') try: shader.uniform_float('u_resolution', (self.width, self.height)) except ValueError: print('Uniform: u_resolution not used') batch.draw(shader) buffer = bgl.Buffer(bgl.GL_BYTE, self.width * self.height * 4) bgl.glReadBuffer(bgl.GL_BACK) bgl.glReadPixels(0, 0, self.width, self.height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) offscreen.free() if recompile: print("Success recompiling") name = self.source.split(".")[0] if not name in bpy.data.images: bpy.data.images.new(name, self.width, self.height) image = bpy.data.images[name] image.scale(self.width, self.height) image.pixels = [v / 255 for v in buffer] return {'PASS_THROUGH'}
def cubemap_to_equirectangular(self, imageList, outputName): # Define the vertex shader vertex_shader = ''' in vec3 aVertexPosition; in vec2 aVertexTextureCoord; out vec2 vTexCoord; void main() { vTexCoord = aVertexTextureCoord; gl_Position = vec4(aVertexPosition, 1); } ''' # Generate the OpenGL shader pos = [ (-1.0, -1.0, -1.0), # left, bottom, back (-1.0, 1.0, -1.0), # left, top, back (1.0, -1.0, -1.0), # right, bottom, back (1.0, 1.0, -1.0) ] # right, top, back coords = [ (-1.0, -1.0), # left, bottom (-1.0, 1.0), # left, top (1.0, -1.0), # right, bottom (1.0, 1.0) ] # right, top vertexIndices = [(0, 3, 1), (3, 0, 2)] shader = gpu.types.GPUShader(vertex_shader, self.frag_shader) batch = batch_for_shader(shader, 'TRIS', {"aVertexPosition": pos,\ "aVertexTextureCoord": coords},\ indices=vertexIndices) # Change the color space of all of the images to Linear # and load them into OpenGL textures for image in imageList: image.colorspace_settings.name = 'Linear' image.gl_load() # set the size of the final image width = self.image_size[0] height = self.image_size[1] # Create an offscreen render buffer and texture offscreen = gpu.types.GPUOffScreen(width, height) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) shader.bind() def bind_and_filter(tex, bindcode, image=None, imageNum=None): bgl.glActiveTexture(tex) bgl.glBindTexture(bgl.GL_TEXTURE_2D, bindcode) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_EDGE) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_EDGE) if image != None and imageNum != None: shader.uniform_int(image, imageNum) # Bind all of the cubemap textures and enable correct filtering and wrapping # to prevent seams bind_and_filter(bgl.GL_TEXTURE0, imageList[0].bindcode, "cubeLeftImage", 0) bind_and_filter(bgl.GL_TEXTURE1, imageList[1].bindcode, "cubeRightImage", 1) bind_and_filter(bgl.GL_TEXTURE2, imageList[2].bindcode, "cubeBottomImage", 2) bind_and_filter(bgl.GL_TEXTURE3, imageList[3].bindcode, "cubeTopImage", 3) bind_and_filter(bgl.GL_TEXTURE4, imageList[4].bindcode, "cubeFrontImage", 4) if not self.no_back_image: bind_and_filter(bgl.GL_TEXTURE5, imageList[5].bindcode, "cubeBackImage", 5) # Bind the resulting texture bind_and_filter(bgl.GL_TEXTURE6, offscreen.color_texture) # Render the image batch.draw(shader) # Unload the textures for image in imageList: image.gl_free() # Read the resulting pixels into a buffer buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4) bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buffer) # Unload the offscreen texture offscreen.free() # Remove the cubemap textures: for image in imageList: bpy.data.images.remove(image) # Copy the pixels from the buffer to an image object if not outputName in bpy.data.images.keys(): bpy.data.images.new(outputName, width, height) imageRes = bpy.data.images[outputName] imageRes.scale(width, height) imageRes.pixels = buffer return imageRes
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