예제 #1
0
def test_shader_load_compute(vfs, ramdir):
    # Try non-existent first.
    shad0 = Shader.load_compute(Shader.SL_GLSL, "/nonexistent.glsl")
    assert shad0 is None

    comp_file = Filename(ramdir, "shader.glsl")

    # Now write some actual content to the shader file.
    vfs.write_file(comp_file, b"#version 100\nvoid main() {}\n", False)

    shad1 = Shader.load_compute(Shader.SL_GLSL, comp_file)
    assert shad1 is not None
    assert shad1.this

    # Load the same shader, it should return the cached result.
    shad2 = Shader.load_compute(Shader.SL_GLSL, comp_file)
    assert shad2 is not None
    assert shad1.this == shad2.this

    # After waiting a second to make the timestamp different, modify the
    # shader and load again, it should result in a different object now
    time.sleep(1.0)
    vfs.write_file(comp_file, b"#version 110\nvoid main() {}\n", False)

    shad2 = Shader.load_compute(Shader.SL_GLSL, comp_file)

    assert shad2.this != shad1.this
예제 #2
0
    def __init__(self, size, source_tex, normalization_factor):
        """ Creates a new fft instance. The source texture has to specified
        from the begining, as the shaderAttributes are pregenerated for
        performance reasons """

        self.size = size
        self.log2_size = int(math.log(size, 2))
        self.normalization_factor = normalization_factor

        # Create a ping and a pong texture, because we can't write to the
        # same texture while reading to it (that would lead to unexpected
        # behaviour, we could solve that by using an appropriate thread size,
        # but it works fine so far)
        self.ping_texture = Texture("FFTPing")
        self.ping_texture.setup_2d_texture(self.size, self.size,
                                           Texture.TFloat, Texture.FRgba32)
        self.pong_texture = Texture("FFTPong")
        self.pong_texture.setup_2d_texture(self.size, self.size,
                                           Texture.TFloat, Texture.FRgba32)
        self.source_tex = source_tex

        for tex in [self.ping_texture, self.pong_texture, source_tex]:
            tex.set_minfilter(Texture.FTNearest)
            tex.set_magfilter(Texture.FTNearest)
            tex.set_wrap_u(Texture.WMClamp)
            tex.set_wrap_v(Texture.WMClamp)

        # Pregenerate weights & indices for the shaders
        self._compute_weighting()

        # Pre generate the shaders, we have 2 passes: Horizontal and Vertical
        # which both execute log2(N) times with varying radii
        self.horizontal_fft_shader = Shader.load_compute(
            Shader.SLGLSL, "/$$rp/rpcore/water/shader/horizontal_fft.compute")
        self.horizontal_fft = NodePath("HorizontalFFT")
        self.horizontal_fft.set_shader(self.horizontal_fft_shader)
        self.horizontal_fft.set_shader_input("precomputedWeights",
                                             self.weights_lookup_tex)
        self.horizontal_fft.set_shader_input("N", LVecBase2i(self.size))

        self.vertical_fft_shader = Shader.load_compute(
            Shader.SLGLSL, "/$$rp/rpcore/water/shader/vertical_fft.compute")
        self.vertical_fft = NodePath("VerticalFFT")
        self.vertical_fft.set_shader(self.vertical_fft_shader)
        self.vertical_fft.set_shader_input("precomputedWeights",
                                           self.weights_lookup_tex)
        self.vertical_fft.set_shader_input("N", LVecBase2i(self.size))

        # Create a texture where the result is stored
        self.result_texture = Texture("Result")
        self.result_texture.setup2dTexture(self.size, self.size,
                                           Texture.TFloat, Texture.FRgba16)
        self.result_texture.set_minfilter(Texture.FTLinear)
        self.result_texture.set_magfilter(Texture.FTLinear)

        # Prepare the shader attributes, so we don't have to regenerate them
        # every frame -> That is VERY slow (3ms per fft instance)
        self._prepare_attributes()
예제 #3
0
    def __init__(self):
        load_prc_file_data(
            "", """
            textures-power-2 none
            window-type offscreen
            win-size 100 100
            gl-coordinate-system default
            notify-level-display error
            print-pipe-types #f
        """)

        ShowBase.__init__(self)

        dest_tex = Texture()
        dest_tex.setup_2d_texture(2048, 2048, Texture.T_unsigned_byte,
                                  Texture.F_rgba8)
        cshader = Shader.load_compute(Shader.SL_GLSL, "grain.compute.glsl")
        node = NodePath("")
        node.set_shader(cshader)
        node.set_shader_input("DestTex", dest_tex)
        attr = node.get_attrib(ShaderAttrib)
        self.graphicsEngine.dispatch_compute((2048 // 16, 2048 // 16, 1), attr,
                                             self.win.get_gsg())

        base.graphicsEngine.extract_texture_data(dest_tex, base.win.get_gsg())

        # Convert to single channel
        img = PNMImage(2048, 2048, 1, 255)
        dest_tex.store(img)
        img.set_num_channels(1)

        tex = Texture()
        tex.load(img)
        tex.write("grain.txo.pz")
예제 #4
0
    def __init__(self):
        load_prc_file_data("", """
            textures-power-2 none
            window-type offscreen
            win-size 100 100
            gl-coordinate-system default
            notify-level-display error
            print-pipe-types #f
        """)

        ShowBase.__init__(self)

        dest_tex = Texture()
        dest_tex.setup_2d_texture(2048, 2048, Texture.T_unsigned_byte, Texture.F_rgba8)
        cshader = Shader.load_compute(Shader.SL_GLSL, "grain.compute.glsl")
        node = NodePath("")
        node.set_shader(cshader)
        node.set_shader_input("DestTex", dest_tex)
        attr = node.get_attrib(ShaderAttrib)
        self.graphicsEngine.dispatch_compute(
            (2048 // 16, 2048 // 16, 1), attr, self.win.get_gsg())

        base.graphicsEngine.extract_texture_data(dest_tex, base.win.get_gsg())

        # Convert to single channel
        img = PNMImage(2048, 2048, 1, 255)
        dest_tex.store(img)
        img.set_num_channels(1)

        tex = Texture()
        tex.load(img)
        tex.write("grain.txo.pz")
예제 #5
0
 def _create_shaders(self):
     """ Creates all the shaders used for precomputing """
     self._shaders = {}
     resource_path = self._handle.get_shader_resource("eric_bruneton")
     for fname in listdir(resource_path):
         fpath = join(resource_path, fname)
         if isfile(fpath) and fname.endswith(".compute.glsl"):
             shader_name = fname.split(".")[0]
             shader_obj = Shader.load_compute(Shader.SL_GLSL, fpath)
             self._shaders[shader_name] = shader_obj
예제 #6
0
    def _late_init(self, task):
        """ Gets called after the pipeline initialized, this extracts the
        exposure texture from the stage manager """

        stage_mgr = self._pipeline.stage_mgr

        if not stage_mgr.has_pipe("Exposure"):
            self.debug("Disabling exposure widget, could not find the exposure data.")
            self._node.remove_node()
            return

        self._node.show()

        exposure_tex = stage_mgr.get_pipe("Exposure")
        self._cshader = Shader.load_compute(Shader.SL_GLSL, "Shader/GUI/VisualizeExposure.compute.glsl")
        self._cshader_np.set_shader(self._cshader)
        self._cshader_np.set_shader_input("DestTex", self._storage_tex)
        self._cshader_np.set_shader_input("ExposureTex", exposure_tex)
 def load_shader(cls, *args):
     """ Loads a shader from disk """
     with timed_loading_operation(args):
         if len(args) == 1:
             return Shader.load_compute(Shader.SL_GLSL, args[0])
         return Shader.load(Shader.SL_GLSL, *args)
예제 #8
0
 def load_shader(cls, *args):
     """ Loads a shader from disk """
     with timed_loading_operation(args):
         if len(args) == 1:
             return Shader.load_compute(Shader.SL_GLSL, args[0])
         return Shader.load(Shader.SL_GLSL, *args)
예제 #9
0
    def __init__(self, water_options):
        self.options = water_options
        self.options.size = 512
        self.options.wind_dir.normalize()
        self.options.wave_amplitude *= 1e-7

        self.displacement_tex = Texture("Displacement")
        self.displacement_tex.setup_2d_texture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)

        self.normal_tex = Texture("Normal")
        self.normal_tex.setup_2d_texture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)

        self.combine_shader = Shader.load_compute(Shader.SLGLSL,
                                                  "/$$rp/rpcore/water/shader/combine.compute")

        self.pta_time = PTAFloat.emptyArray(1)

        # Create a gaussian random texture, as shaders aren't well suited
        # for that
        setRandomSeed(523)
        self.random_storage = PNMImage(self.options.size, self.options.size, 4)
        self.random_storage.setMaxval((2 ** 16) - 1)

        for x in range(self.options.size):
            for y in range(self.options.size):
                rand1 = self._get_gaussian_random() / 10.0 + 0.5
                rand2 = self._get_gaussian_random() / 10.0 + 0.5
                self.random_storage.setXel(x, y, float(rand1), float(rand2), 0)
                self.random_storage.setAlpha(x, y, 1.0)

        self.random_storage_tex = Texture("RandomStorage")
        self.random_storage_tex.load(self.random_storage)
        self.random_storage_tex.set_format(Texture.FRgba16)
        self.random_storage_tex.set_minfilter(Texture.FTNearest)
        self.random_storage_tex.set_magfilter(Texture.FTNearest)

        # Create the texture wwhere the intial height (H0 + Omega0) is stored.
        self.tex_initial_height = Texture("InitialHeight")
        self.tex_initial_height.setup_2d_texture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)
        self.tex_initial_height.set_minfilter(Texture.FTNearest)
        self.tex_initial_height.set_magfilter(Texture.FTNearest)

        # Create the shader which populates the initial height texture
        self.shader_initial_height = Shader.load_compute(Shader.SLGLSL,
                                                         "/$$rp/rpcore/water/shader/initial_height.compute")
        self.node_initial_height = NodePath("initialHeight")
        self.node_initial_height.set_shader(self.shader_initial_height)
        self.node_initial_height.set_shader_input("dest", self.tex_initial_height)
        self.node_initial_height.set_shader_input(
            "N", LVecBase2i(self.options.size))
        self.node_initial_height.set_shader_input(
            "patchLength", self.options.patch_length)
        self.node_initial_height.set_shader_input("windDir", self.options.wind_dir)
        self.node_initial_height.set_shader_input(
            "windSpeed", self.options.wind_speed)
        self.node_initial_height.set_shader_input(
            "waveAmplitude", self.options.wave_amplitude)
        self.node_initial_height.set_shader_input(
            "windDependency", self.options.wind_dependency)
        self.node_initial_height.set_shader_input(
            "randomTex", self.random_storage_tex)

        self.attr_initial_height = self.node_initial_height.get_attrib(ShaderAttrib)

        self.height_textures = []
        for i in range(3):
            tex = Texture("Height")
            tex.setup_2d_texture(self.options.size, self.options.size,
                                 Texture.TFloat, Texture.FRgba16)
            tex.set_minfilter(Texture.FTNearest)
            tex.set_magfilter(Texture.FTNearest)
            tex.set_wrap_u(Texture.WMClamp)
            tex.set_wrap_v(Texture.WMClamp)
            self.height_textures.append(tex)

        # Also create the shader which updates the spectrum
        self.shader_update = Shader.load_compute(Shader.SLGLSL,
                                                 "/$$rp/rpcore/water/shader/update.compute")
        self.node_update = NodePath("update")
        self.node_update.set_shader(self.shader_update)
        self.node_update.set_shader_input("outH0x", self.height_textures[0])
        self.node_update.set_shader_input("outH0y", self.height_textures[1])
        self.node_update.set_shader_input("outH0z", self.height_textures[2])
        self.node_update.set_shader_input("initialHeight", self.tex_initial_height)
        self.node_update.set_shader_input("N", LVecBase2i(self.options.size))
        self.node_update.set_shader_input("time", self.pta_time)
        self.attr_update = self.node_update.get_attrib(ShaderAttrib)

        # Create 3 FFTs
        self.fftX = GPUFFT(self.options.size, self.height_textures[0],
                           self.options.normalization_factor)
        self.fftY = GPUFFT(self.options.size, self.height_textures[1],
                           self.options.normalization_factor)
        self.fftZ = GPUFFT(self.options.size, self.height_textures[2],
                           self.options.normalization_factor)

        self.combine_node = NodePath("Combine")
        self.combine_node.set_shader(self.combine_shader)
        self.combine_node.set_shader_input(
            "displacementX", self.fftX.get_result_texture())
        self.combine_node.set_shader_input(
            "displacementY", self.fftY.get_result_texture())
        self.combine_node.set_shader_input(
            "displacementZ", self.fftZ.get_result_texture())
        self.combine_node.set_shader_input("normalDest", self.normal_tex)
        self.combine_node.set_shader_input(
            "displacementDest", self.displacement_tex)
        self.combine_node.set_shader_input(
            "N", LVecBase2i(self.options.size))
        self.combine_node.set_shader_input(
            "choppyScale", self.options.choppy_scale)
        self.combine_node.set_shader_input(
            "gridLength", self.options.patch_length)
        # Store only the shader attrib as this is way faster
        self.attr_combine = self.combine_node.get_attrib(ShaderAttrib)