def _make_maps(self): """ Internal method to create the cubemap storage """ # Create the cubemaps for the diffuse and specular components self._prefilter_map = Image.create_cube( self._name + "IBLPrefDiff", CubemapFilter.PREFILTER_CUBEMAP_SIZE, "R11G11B10") self._diffuse_map = Image.create_cube( self._name + "IBLDiff", CubemapFilter.DIFFUSE_CUBEMAP_SIZE, "R11G11B10") self._spec_pref_map = Image.create_cube( self._name + "IBLPrefSpec", self._size, "R11G11B10") self._specular_map = Image.create_cube( self._name + "IBLSpec", self._size, "R11G11B10") # Set the correct filtering modes for tex in [self._diffuse_map, self._specular_map, self._prefilter_map, self._spec_pref_map]: tex.set_minfilter(SamplerState.FT_linear) tex.set_magfilter(SamplerState.FT_linear) tex.set_clear_color(Vec4(0)) tex.clear_image() # Use mipmaps for the specular cubemap self._spec_pref_map.set_minfilter(SamplerState.FT_linear_mipmap_linear) self._specular_map.set_minfilter(SamplerState.FT_linear_mipmap_linear)
def init_internal_manager(self): """ Creates the light storage manager and the buffer to store the light data """ self.internal_mgr = InternalLightManager() self.internal_mgr.set_shadow_update_distance( self.pipeline.settings["shadows.max_update_distance"]) # Storage for the Lights per_light_vec4s = 4 self.img_light_data = Image.create_buffer( "LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16") self.img_light_data.set_clear_color(0) self.img_light_data.clear_image() self.pta_max_light_index = PTAInt.empty_array(1) self.pta_max_light_index[0] = 0 # Storage for the shadow sources per_source_vec4s = 5 self.img_source_data = Image.create_buffer( "ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA16") self.img_light_data.set_clear_color(0) self.img_light_data.clear_image() # Register the buffer inputs = self.pipeline.stage_mgr.inputs inputs["AllLightsData"] = self.img_light_data inputs["ShadowSourceData"] = self.img_source_data inputs["maxLightIndex"] = self.pta_max_light_index
def init_internal_manager(self): """ Creates the light storage manager and the buffer to store the light data """ self.internal_mgr = InternalLightManager() self.internal_mgr.set_shadow_update_distance( self.pipeline.settings["shadows.max_update_distance"]) # Storage for the Lights per_light_vec4s = 4 self.img_light_data = Image.create_buffer( "LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16") self.img_light_data.clear_image() self.pta_max_light_index = PTAInt.empty_array(1) self.pta_max_light_index[0] = 0 # Storage for the shadow sources per_source_vec4s = 5 # IMPORTANT: RGBA32 is really required here. Otherwise artifacts and bad # shadow filtering occur due to precision issues self.img_source_data = Image.create_buffer( "ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA32") self.img_light_data.clear_image() # Register the buffer inputs = self.pipeline.stage_mgr.inputs inputs["AllLightsData"] = self.img_light_data inputs["ShadowSourceData"] = self.img_source_data inputs["maxLightIndex"] = self.pta_max_light_index
def _create_components(self): """ Internal method to init the widgets components """ # Create the buffer which stores the last FPS values self._storage_buffer = Image.create_buffer("FPSValues", 250, "R16") self._storage_buffer.set_clear_color(Vec4(0)) self._storage_buffer.clear_image() self._store_index = PTAInt.empty_array(1) self._store_index[0] = 0 self._current_ftime = PTAFloat.empty_array(1) self._current_ftime[0] = 16.0 self._chart_ms_max = PTAFloat.empty_array(1) self._chart_ms_max[0] = 40 # Create the texture where the gui component is rendered inside self._display_tex = Image.create_2d("FPSChartRender", 250, 120, "RGBA8") self._display_tex.set_clear_color(Vec4(0)) self._display_tex.clear_image() self._display_img = Sprite(image=self._display_tex, parent=self._node, w=250, h=120, x=10, y=10) # Defer the further loading Globals.base.taskMgr.doMethodLater(0.3, self._late_init, "FPSChartInit")
def init(self): """ Creates the cubemap storage """ # Storage for the specular components (with mipmaps) self.cubemap_storage = Image.create_cube_array("EnvmapStorage", self.resolution, self.max_probes, "RGBA16") self.cubemap_storage.set_minfilter( SamplerState.FT_linear_mipmap_linear) self.cubemap_storage.set_magfilter(SamplerState.FT_linear) self.cubemap_storage.set_clear_color(Vec4(1.0, 0.0, 0.1, 1.0)) self.cubemap_storage.clear_image() # Storage for the diffuse component self.diffuse_storage = Image.create_cube_array("EnvmapDiffStorage", self.diffuse_resolution, self.max_probes, "RGBA16") self.diffuse_storage.set_clear_color(Vec4(1, 0, 0.2, 1.0)) self.diffuse_storage.clear_image() # Data-storage to store all cubemap properties self.dataset_storage = Image.create_buffer("EnvmapData", self.max_probes * 5, "RGBA32") self.dataset_storage.set_clear_color(Vec4(0)) self.dataset_storage.clear_image()
def _make_maps(self): """ Internal method to create the cubemap storage """ # Create the cubemaps for the diffuse and specular components self._prefilter_map = Image.create_cube( self._name + "IBLPrefDiff", CubemapFilter.PREFILTER_CUBEMAP_SIZE, "R11G11B10") self._diffuse_map = Image.create_cube( self._name + "IBLDiff", CubemapFilter.DIFFUSE_CUBEMAP_SIZE, "R11G11B10") self._spec_pref_map = Image.create_cube(self._name + "IBLPrefSpec", self._size, "R11G11B10") self._specular_map = Image.create_cube(self._name + "IBLSpec", self._size, "R11G11B10") # Set the correct filtering modes for tex in [ self._diffuse_map, self._specular_map, self._prefilter_map, self._spec_pref_map ]: tex.set_minfilter(SamplerState.FT_linear) tex.set_magfilter(SamplerState.FT_linear) tex.set_clear_color(Vec4(0)) tex.clear_image() # Use mipmaps for the specular cubemap self._spec_pref_map.set_minfilter(SamplerState.FT_linear_mipmap_linear) self._specular_map.set_minfilter(SamplerState.FT_linear_mipmap_linear)
def _create_components(self): """ Internal method to init the widgets components """ # Create the buffer which stores the last FPS values self._storage_buffer = Image.create_buffer("FPSValues", 250, "R16") self._storage_buffer.set_clear_color(Vec4(0)) self._storage_buffer.clear_image() self._store_index = PTAInt.empty_array(1) self._store_index[0] = 0 self._current_ftime = PTAFloat.empty_array(1) self._current_ftime[0] = 16.0 self._chart_ms_max = PTAFloat.empty_array(1) self._chart_ms_max[0] = 40 # Create the texture where the gui component is rendered inside self._display_tex = Image.create_2d("FPSChartRender", 250, 120, "RGBA8") self._display_tex.set_clear_color(Vec4(0)) self._display_tex.clear_image() self._display_img = Sprite( image=self._display_tex, parent=self._node, w=250, h=120, x=10, y=10) # Defer the further loading Globals.base.taskMgr.doMethodLater(0.3, self._late_init, "FPSChartInit")
def init_internal_manager(self): """ Creates the light storage manager and the buffer to store the light data """ self.internal_mgr = InternalLightManager() self.internal_mgr.set_shadow_update_distance( self.pipeline.settings["shadows.max_update_distance"]) # Storage for the Lights per_light_vec4s = 4 self.img_light_data = Image.create_buffer( "LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16") self.img_light_data.set_clear_color(0) self.img_light_data.clear_image() self.pta_max_light_index = PTAInt.empty_array(1) self.pta_max_light_index[0] = 0 # Storage for the shadow sources per_source_vec4s = 5 # IMPORTANT: RGBA32 is really required here. Otherwise artifacts and bad # shadow filtering occur due to precision issues self.img_source_data = Image.create_buffer( "ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA32") self.img_light_data.set_clear_color(0) self.img_light_data.clear_image() # Register the buffer inputs = self.pipeline.stage_mgr.inputs inputs["AllLightsData"] = self.img_light_data inputs["ShadowSourceData"] = self.img_source_data inputs["maxLightIndex"] = self.pta_max_light_index
def create(self): self.target = self.create_target("CollectUsedCells") self.target.size = 0, 0 self.target.prepare_buffer() self.cell_list_buffer = Image.create_buffer("CellList", 0, "R32I") self.cell_index_buffer = Image.create_2d_array("CellIndices", 0, 0, 0, "R32I") self.target.set_shader_inputs( CellListBuffer=self.cell_list_buffer, CellListIndices=self.cell_index_buffer)
def create(self): # Construct the voxel texture self._cloud_voxels = Image.create_3d("CloudVoxels", self._voxel_res_xy, self._voxel_res_xy, self._voxel_res_z, "RGBA8") self._cloud_voxels.set_wrap_u(SamplerState.WM_repeat) self._cloud_voxels.set_wrap_v(SamplerState.WM_repeat) self._cloud_voxels.set_wrap_w(SamplerState.WM_border_color) self._cloud_voxels.set_border_color(Vec4(0, 0, 0, 0)) # Construct the target which populates the voxel texture self._grid_target = self.create_target("CreateVoxels") self._grid_target.size = self._voxel_res_xy, self._voxel_res_xy self._grid_target.prepare_buffer() self._grid_target.quad.set_instance_count(self._voxel_res_z) self._grid_target.set_shader_input("CloudVoxels", self._cloud_voxels) # Construct the target which shades the voxels self._shade_target = self.create_target("ShadeVoxels") self._shade_target.size = self._voxel_res_xy, self._voxel_res_xy self._shade_target.prepare_buffer() self._shade_target.quad.set_instance_count(self._voxel_res_z) self._shade_target.set_shader_input("CloudVoxels", self._cloud_voxels) self._shade_target.set_shader_input("CloudVoxelsDest", self._cloud_voxels)
def create(self): if self.remove_fireflies: self.target_firefly = self.create_target("RemoveFireflies") self.target_firefly.add_color_attachment(bits=16) self.target_firefly.prepare_buffer() self.scene_target_img = Image.create_2d("BloomDownsample", 0, 0, "RGBA16") self.scene_target_img.set_minfilter( SamplerState.FT_linear_mipmap_linear) self.scene_target_img.set_magfilter(SamplerState.FT_linear) self.scene_target_img.set_wrap_u(SamplerState.WM_clamp) self.scene_target_img.set_wrap_v(SamplerState.WM_clamp) self.scene_target_img.set_clear_color(Vec4(0.1, 0.0, 0.0, 1.0)) self.scene_target_img.clear_image() self.target_extract = self.create_target("ExtractBrightSpots") self.target_extract.prepare_buffer() self.target_extract.set_shader_input("DestTex", self.scene_target_img, False, True, -1, 0) if self.remove_fireflies: self.target_extract.set_shader_input("ShadedScene", self.target_firefly.color_tex, 1000) self.downsample_targets = [] self.upsample_targets = [] # Downsample passes for i in range(self.num_mips): scale_multiplier = 2**(1 + i) target = self.create_target("Downsample:Step-" + str(i)) target.size = -scale_multiplier, -scale_multiplier target.prepare_buffer() target.set_shader_input("sourceMip", i) target.set_shader_input("SourceTex", self.scene_target_img) target.set_shader_input("DestTex", self.scene_target_img, False, True, -1, i + 1) self.downsample_targets.append(target) # Upsample passes for i in range(self.num_mips): scale_multiplier = 2**(self.num_mips - i - 1) target = self.create_target("Upsample:Step-" + str(i)) target.size = -scale_multiplier, -scale_multiplier target.prepare_buffer() target.set_shader_input("FirstUpsamplePass", i == 0) target.set_shader_input("sourceMip", self.num_mips - i) target.set_shader_input("SourceTex", self.scene_target_img) target.set_shader_input("DestTex", self.scene_target_img, False, True, -1, self.num_mips - i - 1) self.upsample_targets.append(target) self.target_apply = self.create_target("ApplyBloom") self.target_apply.add_color_attachment(bits=16) self.target_apply.prepare_buffer() self.target_apply.set_shader_input("BloomTex", self.scene_target_img)
def create(self): # Create the target which converts the scene color to a luminance self.target_lum = self.create_target("GetLuminance") self.target_lum.size = -4 self.target_lum.add_color_attachment(bits=(16, 0, 0, 0)) self.target_lum.prepare_buffer() self.mip_targets = [] # Create the storage for the exposure, this stores the current and last # frames exposure # XXX: We have to use F_r16 instead of F_r32 because of a weird nvidia # driver bug! However, 16 bits should be enough for sure. self.tex_exposure = Image.create_buffer("ExposureStorage", 1, "R16") self.tex_exposure.set_clear_color(Vec4(0.5)) self.tex_exposure.clear_image() # Create the target which extracts the exposure from the average brightness self.target_analyze = self.create_target("AnalyzeBrightness") self.target_analyze.size = 1, 1 self.target_analyze.prepare_buffer() self.target_analyze.set_shader_input("ExposureStorage", self.tex_exposure) # Create the target which applies the generated exposure to the scene self.target_apply = self.create_target("ApplyExposure") self.target_apply.add_color_attachment(bits=16, alpha=True) self.target_apply.prepare_buffer() self.target_apply.set_shader_input("Exposure", self.tex_exposure)
def _create_components(self): """ Internal method to init the widgets components """ self._node.hide() # Create the texture where the gui component is rendered inside self._storage_tex = Image.create_2d("ExposureDisplay", 140, 20, "RGBA8") self._storage_tex.set_clear_color(Vec4(0.2, 0.6, 1.0, 1.0)) self._storage_tex.clear_image() self._bg_frame = DirectFrame( parent=self._node, frameColor=(0.1, 0.1, 0.1, 1.0), frameSize=(200, 0, -10, -85), pos=(0, 0, 0)) self._display_img = Sprite( image=self._storage_tex, parent=self._node, w=140, h=20, x=20, y=50) self._display_txt = Text( text="Current Exposure".upper(), parent=self._node, x=160, y=40, size=13, color=Vec3(0.8), align="right") # Create the shader which generates the visualization texture self._cshader_node = ComputeNode("ExposureWidget") self._cshader_node.add_dispatch(140 // 10, 20 // 4, 1) self._cshader_np = self._node.attach_new_node(self._cshader_node) # Defer the further loading Globals.base.taskMgr.doMethodLater(1.0, self._late_init, "ExposureLateInit")
def create(self): # Create the target which converts the scene color to a luminance self.target_lum = self.create_target("GetLuminance") self.target_lum.size = -4 self.target_lum.add_color_attachment(bits=(16, 0, 0, 0)) self.target_lum.prepare_buffer() self.mip_targets = [] # Create the storage for the exposure, this stores the current and last # frames exposure # XXX: We have to use F_r16 instead of F_r32 because of a weird nvidia # driver bug! However, 16 bits should be enough for sure. self.tex_exposure = Image.create_buffer("ExposureStorage", 1, "R16") self.tex_exposure.set_clear_color(Vec4(0.5)) self.tex_exposure.clear_image() # Create the target which extracts the exposure from the average brightness self.target_analyze = self.create_target("AnalyzeBrightness") self.target_analyze.size = 1, 1 self.target_analyze.prepare_buffer() self.target_analyze.set_shader_input("ExposureStorage", self.tex_exposure) # Create the target which applies the generated exposure to the scene self.target_apply = self.create_target("ApplyExposure") self.target_apply.add_color_attachment(bits=16) self.target_apply.prepare_buffer() self.target_apply.set_shader_input("Exposure", self.tex_exposure)
def _create_data_storage(self): """ Creates the buffer used to transfer commands """ command_buffer_size = self._commands_per_frame * 32 self.debug("Allocating command buffer of size", command_buffer_size) self._data_texture = Image.create_buffer("CommandQueue", command_buffer_size, "R32") self._data_texture.set_clear_color(0)
def create(self): self.target = self.create_target("FlagUsedCells") self.target.prepare_buffer() self.cell_grid_flags = Image.create_2d_array( "CellGridFlags", 0, 0, self._pipeline.settings["lighting.culling_grid_slices"], "R8") self.target.set_shader_input("cellGridFlags", self.cell_grid_flags)
def create(self): self.target_visible = self.create_target("GetVisibleLights") self.target_visible.size = 16, 16 self.target_visible.prepare_buffer() # TODO: Use no oversized triangle in this stage self.target_cull = self.create_target("CullLights") self.target_cull.size = 0, 0 self.target_cull.prepare_buffer() # TODO: Use no oversized triangle in this stage self.target_group = self.create_target("GroupLightsByClass") self.target_group.size = 0, 0 self.target_group.prepare_buffer() self.frustum_lights_ctr = Image.create_counter("VisibleLightCount") self.frustum_lights = Image.create_buffer( "FrustumLights", self._pipeline.light_mgr.MAX_LIGHTS, "R16UI") self.per_cell_lights = Image.create_buffer("PerCellLights", 0, "R16UI") self.per_cell_light_counts = Image.create_buffer( "PerCellLightCounts", 0, "R32I") self.grouped_cell_lights = Image.create_buffer("GroupedPerCellLights", 0, "R16UI") self.target_visible.set_shader_input("FrustumLights", self.frustum_lights) self.target_visible.set_shader_input("FrustumLightsCount", self.frustum_lights_ctr) self.target_cull.set_shader_input("PerCellLightsBuffer", self.per_cell_lights) self.target_cull.set_shader_input("PerCellLightCountsBuffer", self.per_cell_light_counts) self.target_cull.set_shader_input("FrustumLights", self.frustum_lights) self.target_cull.set_shader_input("FrustumLightsCount", self.frustum_lights_ctr) self.target_group.set_shader_input("PerCellLightsBuffer", self.per_cell_lights) self.target_group.set_shader_input("PerCellLightCountsBuffer", self.per_cell_light_counts) self.target_group.set_shader_input("GroupedCellLightsBuffer", self.grouped_cell_lights) self.target_cull.set_shader_input("threadCount", self.cull_threads) self.target_group.set_shader_input("threadCount", 1)
def create(self): if self.remove_fireflies: self.target_firefly = self.create_target("RemoveFireflies") self.target_firefly.add_color_attachment(bits=16) self.target_firefly.prepare_buffer() self.scene_target_img = Image.create_2d( "BloomDownsample", Globals.resolution.x, Globals.resolution.y, "R11G11B10") self.scene_target_img.set_minfilter(SamplerState.FT_linear_mipmap_linear) self.scene_target_img.set_magfilter(SamplerState.FT_linear) self.scene_target_img.set_wrap_u(SamplerState.WM_clamp) self.scene_target_img.set_wrap_v(SamplerState.WM_clamp) self.scene_target_img.set_clear_color(Vec4(0.1, 0.0, 0.0, 1.0)) self.scene_target_img.clear_image() self.target_extract = self.create_target("ExtractBrightSpots") self.target_extract.prepare_buffer() self.target_extract.set_shader_input("DestTex", self.scene_target_img, False, True, -1, 0) if self.remove_fireflies: self.target_extract.set_shader_input("ShadedScene", self.target_firefly.color_tex, 1000) self.downsample_targets = [] self.upsample_targets = [] # Downsample passes for i in range(self.num_mips): scale_multiplier = 2 ** (1 + i) target = self.create_target("Downsample:Step-" + str(i)) target.size = -scale_multiplier, -scale_multiplier target.prepare_buffer() target.set_shader_input("sourceMip", i) target.set_shader_input("SourceTex", self.scene_target_img) target.set_shader_input("DestTex", self.scene_target_img, False, True, -1, i + 1) self.downsample_targets.append(target) # Upsample passes for i in range(self.num_mips): scale_multiplier = 2 ** (self.num_mips - i - 1) target = self.create_target("Upsample:Step-" + str(i)) target.size = -scale_multiplier, -scale_multiplier target.prepare_buffer() target.set_shader_input("FirstUpsamplePass", i == 0) target.set_shader_input("sourceMip", self.num_mips - i) target.set_shader_input("SourceTex", self.scene_target_img) target.set_shader_input("DestTex", self.scene_target_img, False, True, -1, self.num_mips - i - 1) self.upsample_targets.append(target) self.target_apply = self.create_target("ApplyBloom") self.target_apply.add_color_attachment(bits=16) self.target_apply.prepare_buffer() self.target_apply.set_shader_input("BloomTex", self.scene_target_img)
def create(self): tile_amount = self._pipeline.light_mgr.num_tiles self.target = self.create_target("CollectUsedCells") self.target.size = tile_amount.x, tile_amount.y self.target.prepare_buffer() num_slices = self._pipeline.settings["lighting.culling_grid_slices"] max_cells = tile_amount.x * tile_amount.y * num_slices self.debug("Allocating", max_cells, "cells") self._cell_list_buffer = Image.create_buffer("CellList", 1 + max_cells, "R32I") self._cell_list_buffer.set_clear_color(0) self._cell_index_buffer = Image.create_2d_array( "CellIndices", tile_amount.x, tile_amount.y, num_slices, "R32I") self._cell_index_buffer.set_clear_color(0) self.target.set_shader_input("CellListBuffer", self._cell_list_buffer) self.target.set_shader_input("CellListIndices", self._cell_index_buffer)
def create(self): # TODO: Use no oversized triangle in this stage self.target = self.create_target("CullProbes") self.target.size = 0, 0 self.target.prepare_buffer() self.per_cell_probes = Image.create_buffer("PerCellProbes", 0, "R32I") self.per_cell_probes.clear_image() self.target.set_shader_input("PerCellProbes", self.per_cell_probes) self.target.set_shader_input("threadCount", 1)
def _create_storage(self): """ Internal method to create the storage for the profile dataset textures """ self._storage_tex = Image.create_3d("IESDatasets", 512, 512, self._max_entries, "R16") self._storage_tex.set_minfilter(SamplerState.FT_linear) self._storage_tex.set_magfilter(SamplerState.FT_linear) self._storage_tex.set_wrap_u(SamplerState.WM_clamp) self._storage_tex.set_wrap_v(SamplerState.WM_repeat) self._storage_tex.set_wrap_w(SamplerState.WM_clamp) self._pipeline.stage_mgr.inputs["IESDatasetTex"] = self._storage_tex self._pipeline.stage_mgr.defines["MAX_IES_PROFILES"] = self._max_entries
def create(self): self.target = self.create_target("FlagUsedCells") self.target.prepare_buffer() tile_amount = self._pipeline.light_mgr.num_tiles self.cell_grid_flags = Image.create_2d_array( "CellGridFlags", tile_amount.x, tile_amount.y, self._pipeline.settings["lighting.culling_grid_slices"], "R8") self.cell_grid_flags.set_clear_color(0) self.target.set_shader_input("cellGridFlags", self.cell_grid_flags)
def init(self): """ Creates the cubemap storage """ # Storage for the specular components (with mipmaps) self.cubemap_storage = Image.create_cube_array( "EnvmapStorage", self.resolution, self.max_probes, "RGBA16") self.cubemap_storage.set_minfilter(SamplerState.FT_linear_mipmap_linear) self.cubemap_storage.set_magfilter(SamplerState.FT_linear) self.cubemap_storage.set_clear_color(Vec4(1.0, 0.0, 0.1, 1.0)) self.cubemap_storage.clear_image() # Storage for the diffuse component self.diffuse_storage = Image.create_cube_array( "EnvmapDiffStorage", self.diffuse_resolution, self.max_probes, "RGBA16") self.diffuse_storage.set_clear_color(Vec4(1, 0, 0.2, 1.0)) self.diffuse_storage.clear_image() # Data-storage to store all cubemap properties self.dataset_storage = Image.create_buffer( "EnvmapData", self.max_probes * 5, "RGBA32") self.dataset_storage.set_clear_color(Vec4(0)) self.dataset_storage.clear_image()
def _bind_pipes_to_stage(self, stage): """ Sets all required pipes on a stage """ for pipe in stage.required_pipes: # Check if there is an input block named like the pipe if pipe in self.input_blocks: self.input_blocks[pipe].bind_to(stage) continue if pipe.startswith("PreviousFrame::"): # Special case: Pipes from the previous frame. We assume those # pipes have the same size as the window and a format of # F_rgba16. Could be subject to change. pipe_name = pipe.split("::")[-1] if pipe_name not in self.previous_pipes: tex_format = "RGBA16" # XXX: Assuming we have a depth texture whenever "depth" # occurs in the textures name if "depth" in pipe_name.lower(): tex_format = "R32" pipe_tex = Image.create_2d("Prev-" + pipe_name, Globals.resolution.x, Globals.resolution.y, tex_format) pipe_tex.clear_image() self.previous_pipes[pipe_name] = pipe_tex stage.set_shader_input("Previous_" + pipe_name, self.previous_pipes[pipe_name]) continue elif pipe.startswith("FuturePipe::"): # Special case: Future Pipes which are not available yet. # They will contain the unmodified data from the last # frame. pipe_name = pipe.split("::")[-1] self.debug("Awaiting future pipe", pipe_name) self.future_bindings.append((pipe_name, stage)) continue if pipe not in self.pipes: self.fatal("Pipe '" + pipe + "' is missing for", stage) return False pipe_value = self.pipes[pipe] if isinstance(pipe_value, list) or isinstance(pipe_value, tuple): stage.set_shader_input(pipe, *pipe_value) else: stage.set_shader_input(pipe, pipe_value) return True
def create(self): max_cells = self._pipeline.light_mgr.total_tiles self.num_rows = int(math.ceil(max_cells / float(self.slice_width))) self.target = self.create_target("CullProbes") # TODO: Use no oversized triangle in this stage self.target.size = self.slice_width, self.num_rows self.target.prepare_buffer() self.per_cell_probes = Image.create_buffer( "PerCellProbes", max_cells * self.max_probes_per_cell, "R32I") self.per_cell_probes.set_clear_color(0) self.per_cell_probes.clear_image() self.target.set_shader_input("PerCellProbes", self.per_cell_probes)
def create(self): # Create the target which converts the scene color to a luminance self.target_lum = self.create_target("GetLuminance") self.target_lum.size = -4 self.target_lum.add_color_attachment(bits=(16, 0, 0, 0)) self.target_lum.prepare_buffer() # Get the current quarter-window size wsize_x = (Globals.resolution.x + 3) // 4 wsize_y = (Globals.resolution.y + 3) // 4 # Create the targets which downscale the luminance mipmaps self.mip_targets = [] last_tex = self.target_lum.color_tex while wsize_x >= 4 or wsize_y >= 4: wsize_x = (wsize_x+3) // 4 wsize_y = (wsize_y+3) // 4 mip_target = self.create_target("DScaleLum:S" + str(wsize_x)) mip_target.add_color_attachment(bits=(16, 0, 0, 0)) mip_target.size = wsize_x, wsize_y mip_target.prepare_buffer() mip_target.set_shader_input("SourceTex", last_tex) self.mip_targets.append(mip_target) last_tex = mip_target.color_tex # Create the storage for the exposure, this stores the current and last # frames exposure # XXX: We have to use F_r16 instead of F_r32 because of a weird nvidia # driver bug! However, 16 bits should be enough for sure. self.tex_exposure = Image.create_buffer("ExposureStorage", 1, "R16") self.tex_exposure.set_clear_color(Vec4(0.5)) self.tex_exposure.clear_image() # Create the target which extracts the exposure from the average brightness self.target_analyze = self.create_target("AnalyzeBrightness") self.target_analyze.size = 1, 1 self.target_analyze.prepare_buffer() self.target_analyze.set_shader_input( "ExposureStorage", self.tex_exposure) self.target_analyze.set_shader_input("DownscaledTex", last_tex) # Create the target which applies the generated exposure to the scene self.target_apply = self.create_target("ApplyExposure") self.target_apply.add_color_attachment(bits=16) self.target_apply.prepare_buffer() self.target_apply.set_shader_input("Exposure", self.tex_exposure)
def _bind_pipes_to_stage(self, stage): """ Sets all required pipes on a stage """ for pipe in stage.required_pipes: # Check if there is an input block named like the pipe if pipe in self.input_blocks: self.input_blocks[pipe].bind_to(stage) continue if pipe.startswith("PreviousFrame::"): # Special case: Pipes from the previous frame. We assume those # pipes have the same size as the window and a format of # F_rgba16. Could be subject to change. pipe_name = pipe.split("::")[-1] if pipe_name not in self.previous_pipes: tex_format = "RGBA16" # XXX: Assuming we have a depth texture whenever "depth" # occurs in the textures name if "depth" in pipe_name.lower(): tex_format = "R32" pipe_tex = Image.create_2d( "Prev-" + pipe_name, Globals.resolution.x, Globals.resolution.y, tex_format) pipe_tex.clear_image() self.previous_pipes[pipe_name] = pipe_tex stage.set_shader_input("Previous_" + pipe_name, self.previous_pipes[pipe_name]) continue elif pipe.startswith("FuturePipe::"): # Special case: Future Pipes which are not available yet. # They will contain the unmodified data from the last # frame. pipe_name = pipe.split("::")[-1] self.debug("Awaiting future pipe", pipe_name) self.future_bindings.append((pipe_name, stage)) continue if pipe not in self.pipes: self.fatal("Pipe '" + pipe + "' is missing for", stage) return False pipe_value = self.pipes[pipe] if isinstance(pipe_value, list) or isinstance(pipe_value, tuple): stage.set_shader_input(pipe, *pipe_value) else: stage.set_shader_input(pipe, pipe_value) return True
def create(self): max_cells = self._pipeline.light_mgr.total_tiles self.num_rows = int(math.ceil(max_cells / float(self.slice_width))) self.target = self.create_target("CullLights") # TODO: Use no oversized triangle in this stage self.target.size = self.slice_width, self.num_rows self.target.prepare_buffer() self.per_cell_lights = Image.create_buffer( "PerCellLights", max_cells * (self.max_lights_per_cell + self.num_light_classes), "R32I") self.per_cell_lights.set_clear_color(0) self.target.set_shader_input("PerCellLightsBuffer", self.per_cell_lights) self.debug("Using", self.num_rows, "culling lines")
def _create_store_targets(self): """ Creates the targets which copy the result texture into the actual storage """ self.target_store = self.create_target("StoreCubemap") self.target_store.size = self.resolution * 6, self.resolution self.target_store.prepare_buffer() self.target_store.set_shader_input("SourceTex", self.target.color_tex) self.target_store.set_shader_input("DestTex", self.storage_tex) self.target_store.set_shader_input("currentIndex", self.pta_index) self.temporary_diffuse_map = Image.create_cube("DiffuseTemp", self.resolution, "RGBA16") self.target_store_diff = self.create_target("StoreCubemapDiffuse") self.target_store_diff.size = self.resolution * 6, self.resolution self.target_store_diff.prepare_buffer() self.target_store_diff.set_shader_input("SourceTex", self.target.color_tex) self.target_store_diff.set_shader_input("DestTex", self.temporary_diffuse_map) self.target_store_diff.set_shader_input("currentIndex", self.pta_index)
def _create_store_targets(self): """ Creates the targets which copy the result texture into the actual storage """ self.target_store = self.create_target("StoreCubemap") self.target_store.size = self.resolution * 6, self.resolution self.target_store.prepare_buffer() self.target_store.set_shader_inputs( SourceTex=self.target.color_tex, DestTex=self.storage_tex, currentIndex=self.pta_index) self.temporary_diffuse_map = Image.create_cube("DiffuseTemp", self.resolution, "RGBA16") self.target_store_diff = self.create_target("StoreCubemapDiffuse") self.target_store_diff.size = self.resolution * 6, self.resolution self.target_store_diff.prepare_buffer() self.target_store_diff.set_shader_inputs( SourceTex=self.target.color_tex, DestTex=self.temporary_diffuse_map, currentIndex=self.pta_index)
def create(self): # Construct the voxel texture self._cloud_voxels = Image.create_3d( "CloudVoxels", self._voxel_res_xy, self._voxel_res_xy, self._voxel_res_z, "RGBA8") self._cloud_voxels.set_wrap_u(SamplerState.WM_repeat) self._cloud_voxels.set_wrap_v(SamplerState.WM_repeat) self._cloud_voxels.set_wrap_w(SamplerState.WM_border_color) self._cloud_voxels.set_border_color(Vec4(0, 0, 0, 0)) # Construct the target which populates the voxel texture self._grid_target = self.create_target("CreateVoxels") self._grid_target.size = self._voxel_res_xy, self._voxel_res_xy self._grid_target.prepare_buffer() self._grid_target.quad.set_instance_count(self._voxel_res_z) self._grid_target.set_shader_input("CloudVoxels", self._cloud_voxels) # Construct the target which shades the voxels self._shade_target = self.create_target("ShadeVoxels") self._shade_target.size = self._voxel_res_xy, self._voxel_res_xy self._shade_target.prepare_buffer() self._shade_target.quad.set_instance_count(self._voxel_res_z) self._shade_target.set_shader_input("CloudVoxels", self._cloud_voxels) self._shade_target.set_shader_input("CloudVoxelsDest", self._cloud_voxels)
def create(self): self.target_visible = self.create_target("GetVisibleLights") self.target_visible.size = 16, 16 self.target_visible.prepare_buffer() # TODO: Use no oversized triangle in this stage self.target_cull = self.create_target("CullLights") self.target_cull.size = 0, 0 self.target_cull.prepare_buffer() # TODO: Use no oversized triangle in this stage self.target_group = self.create_target("GroupLightsByClass") self.target_group.size = 0, 0 self.target_group.prepare_buffer() self.frustum_lights_ctr = Image.create_counter("VisibleLightCount") self.frustum_lights = Image.create_buffer( "FrustumLights", self._pipeline.light_mgr.MAX_LIGHTS, "R16UI") self.per_cell_lights = Image.create_buffer( "PerCellLights", 0, "R16UI") self.per_cell_light_counts = Image.create_buffer( "PerCellLightCounts", 0, "R32I") # Needs to be R32 for atomic add in cull stage self.grouped_cell_lights = Image.create_buffer( "GroupedPerCellLights", 0, "R16UI") self.grouped_cell_lights_counts = Image.create_buffer( "GroupedPerCellLightsCount", 0, "R16UI") self.target_visible.set_shader_inputs( FrustumLights=self.frustum_lights, FrustumLightsCount=self.frustum_lights_ctr) self.target_cull.set_shader_inputs( PerCellLightsBuffer=self.per_cell_lights, PerCellLightCountsBuffer=self.per_cell_light_counts, FrustumLights=self.frustum_lights, FrustumLightsCount=self.frustum_lights_ctr, threadCount=self.cull_threads) self.target_group.set_shader_inputs( PerCellLightsBuffer=self.per_cell_lights, PerCellLightCountsBuffer=self.per_cell_light_counts, GroupedCellLightsBuffer=self.grouped_cell_lights, GroupedPerCellLightsCountBuffer=self.grouped_cell_lights_counts, threadCount=1)
def create(self): # Create the voxel grid used to generate the voxels self.voxel_temp_grid = Image.create_3d("VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_temp_grid.set_clear_color(Vec4(0)) self.voxel_temp_nrm_grid = Image.create_3d("VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "R11G11B10") self.voxel_temp_nrm_grid.set_clear_color(Vec4(0)) # Create the voxel grid which is a copy of the temporary grid, but stable self.voxel_grid = Image.create_3d("Voxels", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_grid.set_clear_color(Vec4(0)) self.voxel_grid.set_minfilter(SamplerState.FT_linear_mipmap_linear) # Create the camera for voxelization self.voxel_cam = Camera("VoxelizeCam") self.voxel_cam.set_camera_mask( self._pipeline.tag_mgr.get_voxelize_mask()) self.voxel_cam_lens = OrthographicLens() self.voxel_cam_lens.set_film_size(-2.0 * self.voxel_world_size, 2.0 * self.voxel_world_size) self.voxel_cam_lens.set_near_far(0.0, 2.0 * self.voxel_world_size) self.voxel_cam.set_lens(self.voxel_cam_lens) self.voxel_cam_np = Globals.base.render.attach_new_node(self.voxel_cam) self._pipeline.tag_mgr.register_camera("voxelize", self.voxel_cam) # Create the voxelization target self.voxel_target = self.create_target("VoxelizeScene") self.voxel_target.size = self.voxel_resolution self.voxel_target.prepare_render(self.voxel_cam_np) # Create the target which copies the voxel grid self.copy_target = self.create_target("CopyVoxels") self.copy_target.size = self.voxel_resolution self.copy_target.prepare_buffer() # TODO! Does not work with the new render target yet - maybe add option # to post process region for instances? self.copy_target.instance_count = self.voxel_resolution self.copy_target.set_shader_input("SourceTex", self.voxel_temp_grid) self.copy_target.set_shader_input("DestTex", self.voxel_grid) # Create the target which generates the mipmaps self.mip_targets = [] mip_size, mip = self.voxel_resolution, 0 while mip_size > 1: mip_size, mip = mip_size // 2, mip + 1 mip_target = self.create_target("GenMipmaps:" + str(mip)) mip_target.size = mip_size mip_target.prepare_buffer() mip_target.instance_count = mip_size mip_target.set_shader_input("SourceTex", self.voxel_grid) mip_target.set_shader_input("sourceMip", mip - 1) mip_target.set_shader_input("DestTex", self.voxel_grid, False, True, -1, mip, 0) self.mip_targets.append(mip_target) # Create the initial state used for rendering voxels initial_state = NodePath("VXGIInitialState") initial_state.set_attrib( CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000) initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000) initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000) self.voxel_cam.set_initial_state(initial_state.get_state()) Globals.base.render.set_shader_input("voxelGridPosition", self.pta_next_grid_pos) Globals.base.render.set_shader_input("VoxelGridDest", self.voxel_temp_grid)
def present(self, tex): """ "Presents" a given texture and shows the window """ self._current_tex = tex self.set_title(tex.get_name()) # tex.write(tex.get_name() + ".png") # Remove old content self._content_node.node().remove_all_children() w, h = tex.get_x_size(), tex.get_y_size() if h > 1: scale_x = (self._width - 40.0) / w scale_y = (self._height - 110.0) / h scale_f = min(scale_x, scale_y) display_w = scale_f * w display_h = scale_f * h else: display_w = self._width - 40 display_h = self._height - 110 image = Sprite( image=tex, parent=self._content_node, x=20, y=90, w=display_w, h=display_h, any_filter=False, transparent=False) description = "" # Image size description += "{:d} x {:d} x {:d}".format( tex.get_x_size(), tex.get_y_size(), tex.get_z_size()) # Image type description += ", {:s}, {:s}".format( Image.format_format(tex.get_format()).upper(), Image.format_component_type(tex.get_component_type()).upper()) Text(text=description, parent=self._content_node, x=17, y=70, size=16, color=Vec3(0.6, 0.6, 0.6)) estimated_bytes = tex.estimate_texture_memory() size_desc = "Estimated memory: {:2.2f} MB".format( estimated_bytes / (1024.0 ** 2)) Text(text=size_desc, parent=self._content_node, x=self._width - 20.0, y=70, size=18, color=Vec3(0.34, 0.564, 0.192), align="right") x_pos = len(size_desc) * 9 + 140 # Slider for viewing different mipmaps if tex.uses_mipmaps(): max_mips = tex.get_expected_num_mipmap_levels() - 1 self._mip_slider = Slider( parent=self._content_node, size=140, min_value=0, max_value=max_mips, callback=self._set_mip, x=x_pos, y=65, value=0) x_pos += 140 + 5 self._mip_text = Text( text="MIP: 5", parent=self._content_node, x=x_pos, y=72, size=18, color=Vec3(1, 0.4, 0.4), may_change=1) x_pos += 50 + 30 # Slider for viewing different Z-layers if tex.get_z_size() > 1: self._slice_slider = Slider( parent=self._content_node, size=250, min_value=0, max_value=tex.get_z_size() - 1, callback=self._set_slice, x=x_pos, y=65, value=0) x_pos += 250 + 5 self._slice_text = Text( text="Z: 5", parent=self._content_node, x=x_pos, y=72, size=18, color=Vec3(0.4, 1, 0.4), may_change=1) x_pos += 50 + 30 # Slider to adjust brightness self._bright_slider = Slider( parent=self._content_node, size=140, min_value=-14, max_value=14, callback=self._set_brightness, x=x_pos, y=65, value=0) x_pos += 140 + 5 self._bright_text = Text( text="Bright: 1", parent=self._content_node, x=x_pos, y=72, size=18, color=Vec3(0.4, 0.4, 1), may_change=1) x_pos += 100 + 30 # Slider to enable reinhard tonemapping self._tonemap_box = LabeledCheckbox( parent=self._content_node, x=x_pos, y=60, text="Tonemap", text_color=Vec3(1, 0.4, 0.4), chb_checked=False, chb_callback=self._set_enable_tonemap, text_size=18, expand_width=90) x_pos += 90 + 30 image.set_shader_inputs( slice=0, mipmap=0, brightness=1, tonemap=False) preview_shader = DisplayShaderBuilder.build(tex, display_w, display_h) image.set_shader(preview_shader) self._preview_image = image self.show()
def create(self): # Create the voxel grid used to generate the voxels self.voxel_temp_grid = Image.create_3d( "VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_temp_grid.set_clear_color(Vec4(0)) self.voxel_temp_nrm_grid = Image.create_3d( "VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "R11G11B10") self.voxel_temp_nrm_grid.set_clear_color(Vec4(0)) # Create the voxel grid which is a copy of the temporary grid, but stable self.voxel_grid = Image.create_3d( "Voxels", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_grid.set_clear_color(Vec4(0)) self.voxel_grid.set_minfilter(SamplerState.FT_linear_mipmap_linear) # Create the camera for voxelization self.voxel_cam = Camera("VoxelizeCam") self.voxel_cam.set_camera_mask(self._pipeline.tag_mgr.get_voxelize_mask()) self.voxel_cam_lens = OrthographicLens() self.voxel_cam_lens.set_film_size( -2.0 * self.voxel_world_size, 2.0 * self.voxel_world_size) self.voxel_cam_lens.set_near_far(0.0, 2.0 * self.voxel_world_size) self.voxel_cam.set_lens(self.voxel_cam_lens) self.voxel_cam_np = Globals.base.render.attach_new_node(self.voxel_cam) self._pipeline.tag_mgr.register_camera("voxelize", self.voxel_cam) # Create the voxelization target self.voxel_target = self.create_target("VoxelizeScene") self.voxel_target.size = self.voxel_resolution self.voxel_target.prepare_render(self.voxel_cam_np) # Create the target which copies the voxel grid self.copy_target = self.create_target("CopyVoxels") self.copy_target.size = self.voxel_resolution self.copy_target.prepare_buffer() # TODO! Does not work with the new render target yet - maybe add option # to post process region for instances? self.copy_target.instance_count = self.voxel_resolution self.copy_target.set_shader_input("SourceTex", self.voxel_temp_grid) self.copy_target.set_shader_input("DestTex", self.voxel_grid) # Create the target which generates the mipmaps self.mip_targets = [] mip_size, mip = self.voxel_resolution, 0 while mip_size > 1: mip_size, mip = mip_size // 2, mip + 1 mip_target = self.create_target("GenMipmaps:" + str(mip)) mip_target.size = mip_size mip_target.prepare_buffer() mip_target.instance_count = mip_size mip_target.set_shader_input("SourceTex", self.voxel_grid) mip_target.set_shader_input("sourceMip", mip - 1) mip_target.set_shader_input("DestTex", self.voxel_grid, False, True, -1, mip, 0) self.mip_targets.append(mip_target) # Create the initial state used for rendering voxels initial_state = NodePath("VXGIInitialState") initial_state.set_attrib(CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000) initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000) initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000) self.voxel_cam.set_initial_state(initial_state.get_state()) Globals.base.render.set_shader_input("voxelGridPosition", self.pta_next_grid_pos) Globals.base.render.set_shader_input("VoxelGridDest", self.voxel_temp_grid)
def create(self): x_size, y_size = Globals.resolution.x, Globals.resolution.y self.target = self.create_target("ComputeSSR") self.target.size = -2 self.target.add_color_attachment(bits=16) self.target.prepare_buffer() self.target.color_tex.set_minfilter(SamplerState.FT_nearest) self.target.color_tex.set_magfilter(SamplerState.FT_nearest) self.target_velocity = self.create_target("ReflectionVelocity") self.target_velocity.add_color_attachment(bits=(16, 16, 0, 0)) self.target_velocity.prepare_buffer() self.target_velocity.set_shader_input("TraceResult", self.target.color_tex) self.mipchain = Image.create_2d("SSRMipchain", x_size, y_size, "RGBA16") self.mipchain.set_minfilter(SamplerState.FT_linear_mipmap_linear) self.mipchain.set_wrap_u(SamplerState.WM_clamp) self.mipchain.set_wrap_v(SamplerState.WM_clamp) self.mipchain.set_clear_color(Vec4(0)) self.mipchain.clear_image() self.target_copy_lighting = self.create_target("CopyLighting") self.target_copy_lighting.prepare_buffer() self.target_copy_lighting.set_shader_input("DestTex", self.mipchain, False, True, -1, 0) self.blur_targets = [] for i in range(min(7, self.mipchain.get_expected_num_mipmap_levels() - 1)): target_blur = self.create_target("BlurSSR-" + str(i)) target_blur.size = - (2 ** i) target_blur.prepare_buffer() target_blur.set_shader_input("SourceTex", self.mipchain) target_blur.set_shader_input("sourceMip", i) target_blur.set_shader_input("DestTex", self.mipchain, False, True, -1, i + 1) self.blur_targets.append(target_blur) self.noise_reduce_targets = [] curr_tex = self.target.color_tex for i in range(0): target_remove_noise = self.create_target("RemoveNoise") target_remove_noise.size = -2 target_remove_noise.add_color_attachment(bits=16, alpha=True) target_remove_noise.prepare_buffer() target_remove_noise.set_shader_input("SourceTex", curr_tex) curr_tex = target_remove_noise.color_tex self.noise_reduce_targets.append(target_remove_noise) self.fill_hole_targets = [] for i in range(0): fill_target = self.create_target("FillHoles-" + str(i)) fill_target.size = -2 fill_target.add_color_attachment(bits=16, alpha=True) fill_target.prepare_buffer() fill_target.set_shader_input("SourceTex", curr_tex) curr_tex = fill_target.color_tex self.fill_hole_targets.append(fill_target) self.target_upscale = self.create_target("UpscaleSSR") self.target_upscale.add_color_attachment(bits=16, alpha=True) self.target_upscale.prepare_buffer() self.target_upscale.set_shader_input("SourceTex", curr_tex) self.target_upscale.set_shader_input("MipChain", self.mipchain) self.target_resolve = self.create_target("ResolveSSR") self.target_resolve.add_color_attachment(bits=16, alpha=True) self.target_resolve.prepare_buffer() self.target_resolve.set_shader_input("CurrentTex", self.target_upscale.color_tex) self.target_resolve.set_shader_input("VelocityTex", self.target_velocity.color_tex) self.target_post_blur = self.create_target("SSRPostBlur") self.target_post_blur.add_color_attachment(bits=16, alpha=True) self.target_post_blur.prepare_buffer() self.target_post_blur.set_shader_input("CurrentTex", self.target_resolve.color_tex) AmbientStage.required_pipes.append("SSRSpecular")
def present(self, tex): """ "Presents" a given texture and shows the window """ self._current_tex = tex self.set_title(tex.get_name()) # tex.write(tex.get_name() + ".png") # Remove old content self._content_node.node().remove_all_children() w, h = tex.get_x_size(), tex.get_y_size() if h > 1: scale_x = (self._width - 40.0) / w scale_y = (self._height - 110.0) / h scale_f = min(scale_x, scale_y) display_w = scale_f * w display_h = scale_f * h else: display_w = self._width - 40 display_h = self._height - 110 image = Sprite( image=tex, parent=self._content_node, x=20, y=90, w=display_w, h=display_h, any_filter=False, transparent=False) description = "" # Image size description += "{:d} x {:d} x {:d}".format( tex.get_x_size(), tex.get_y_size(), tex.get_z_size()) # Image type description += ", {:s}, {:s}".format( Image.format_format(tex.get_format()).upper(), Image.format_component_type(tex.get_component_type()).upper()) Text(text=description, parent=self._content_node, x=17, y=70, size=16, color=Vec3(0.6, 0.6, 0.6)) estimated_bytes = tex.estimate_texture_memory() size_desc = "Estimated memory: {:2.2f} MB".format( estimated_bytes / (1024.0 ** 2)) Text(text=size_desc, parent=self._content_node, x=self._width - 20.0, y=70, size=18, color=Vec3(0.34, 0.564, 0.192), align="right") x_pos = len(size_desc) * 9 + 140 # Slider for viewing different mipmaps if tex.uses_mipmaps(): max_mips = tex.get_expected_num_mipmap_levels() - 1 self._mip_slider = Slider( parent=self._content_node, size=140, min_value=0, max_value=max_mips, callback=self._set_mip, x=x_pos, y=65, value=0) x_pos += 140 + 5 self._mip_text = Text( text="MIP: 5", parent=self._content_node, x=x_pos, y=72, size=18, color=Vec3(1, 0.4, 0.4), may_change=1) x_pos += 50 + 30 # Slider for viewing different Z-layers if tex.get_z_size() > 1: self._slice_slider = Slider( parent=self._content_node, size=250, min_value=0, max_value=tex.get_z_size() - 1, callback=self._set_slice, x=x_pos, y=65, value=0) x_pos += 250 + 5 self._slice_text = Text( text="Z: 5", parent=self._content_node, x=x_pos, y=72, size=18, color=Vec3(0.4, 1, 0.4), may_change=1) x_pos += 50 + 30 # Slider to adjust brightness self._bright_slider = Slider( parent=self._content_node, size=140, min_value=-14, max_value=14, callback=self._set_brightness, x=x_pos, y=65, value=0) x_pos += 140 + 5 self._bright_text = Text( text="Bright: 1", parent=self._content_node, x=x_pos, y=72, size=18, color=Vec3(0.4, 0.4, 1), may_change=1) x_pos += 100 + 30 # Slider to enable reinhard tonemapping self._tonemap_box = LabeledCheckbox( parent=self._content_node, x=x_pos, y=60, text="Tonemap", text_color=Vec3(1, 0.4, 0.4), chb_checked=False, chb_callback=self._set_enable_tonemap, text_size=18, expand_width=90) x_pos += 90 + 30 image.set_shader_input("slice", 0) image.set_shader_input("mipmap", 0) image.set_shader_input("brightness", 1) image.set_shader_input("tonemap", False) preview_shader = DisplayShaderBuilder.build(tex, display_w, display_h) image.set_shader(preview_shader) self._preview_image = image self.show()