Skip to content

File: ShaderFlow/Modules/Noise.py

ShaderFlow.Modules.Noise

ShaderNoise

Bases: ShaderModule

Source code in Projects/ShaderFlow/ShaderFlow/Modules/Noise.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@define
class ShaderNoise(ShaderModule):
    name: str = "Noise"
    seed: int = Factory(functools.partial(random.randint, 0, 10000))

    # TODO: Convert these to BrokenSecondOrderShaderDynamics?

    # Maximum amplitude (roughly)
    amplitude: float = 1
    frequency: float = 1
    octaves:   int   = 1
    roughness: float = 1

    # # Number of dimensions for this noise

    __dimensions__: int = 1

    @property
    def dimensions(self):
        return self.__dimensions__

    @dimensions.setter
    def dimensions(self, value):
        self.__dimensions__ = value
        self.__simplex__ = [
            opensimplex.OpenSimplex(seed=self.seed + dimension*1000)
            for dimension in range(self.dimensions)
        ]

    @property
    def type(self) -> str:
        return {
            1: "float",
            2: "vec2",
            3: "vec3",
        }[self.dimensions]

    # Noise generator
    __simplex__: opensimplex.OpenSimplex = None

    def __init__(self, dimensions: int=1, *args, **kwargs):
        self.__attrs_init__(*args, **kwargs)
        self.dimensions = dimensions

    def at(self, x: float=0, y: float=0, z: float=0) -> float:
        """Internal function to return a noise value for three dimensions"""
        noise = numpy.zeros(self.dimensions, dtype=numpy.float32)

        for dimension in range(self.dimensions):
            for octave in range(self.octaves):

                # The "position velocity" due frequency of this octave
                # · One octave up, double the frequency
                # · Scale linearly with self.frequency
                k = (2**octave) * self.frequency

                # Amplitude of this octave so noise remains bounded
                # · Double the octave, half the amplitude
                amplitude = self.amplitude * (self.roughness)**octave

                # Sum this octave's noise to the total
                # Fixme: x=0, y=0, z=0 yields the same noise for all octaves
                noise[dimension] += self.__simplex__[dimension].noise3(x*k, y*k, z*k) * amplitude

        return noise

    def pipeline(self) -> Iterable[ShaderVariable]:
        yield Uniform(self.type, f"i{self.name}", self.at(self.scene.time))

name

name: str = 'Noise'

seed

seed: int = Factory(
    functools.partial(random.randint, 0, 10000)
)

amplitude

amplitude: float = 1

frequency

frequency: float = 1

octaves

octaves: int = 1

roughness

roughness: float = 1

__dimensions__

__dimensions__: int = 1

type

type: str

__simplex__

__simplex__: opensimplex.OpenSimplex = None

__init__

__init__(dimensions: int = 1, *args, **kwargs)
Source code in Projects/ShaderFlow/ShaderFlow/Modules/Noise.py
53
54
55
def __init__(self, dimensions: int=1, *args, **kwargs):
    self.__attrs_init__(*args, **kwargs)
    self.dimensions = dimensions

dimensions

dimensions = dimensions

at

at(x: float = 0, y: float = 0, z: float = 0) -> float

Internal function to return a noise value for three dimensions

Source code in Projects/ShaderFlow/ShaderFlow/Modules/Noise.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def at(self, x: float=0, y: float=0, z: float=0) -> float:
    """Internal function to return a noise value for three dimensions"""
    noise = numpy.zeros(self.dimensions, dtype=numpy.float32)

    for dimension in range(self.dimensions):
        for octave in range(self.octaves):

            # The "position velocity" due frequency of this octave
            # · One octave up, double the frequency
            # · Scale linearly with self.frequency
            k = (2**octave) * self.frequency

            # Amplitude of this octave so noise remains bounded
            # · Double the octave, half the amplitude
            amplitude = self.amplitude * (self.roughness)**octave

            # Sum this octave's noise to the total
            # Fixme: x=0, y=0, z=0 yields the same noise for all octaves
            noise[dimension] += self.__simplex__[dimension].noise3(x*k, y*k, z*k) * amplitude

    return noise

pipeline

pipeline() -> Iterable[ShaderVariable]
Source code in Projects/ShaderFlow/ShaderFlow/Modules/Noise.py
79
80
def pipeline(self) -> Iterable[ShaderVariable]:
    yield Uniform(self.type, f"i{self.name}", self.at(self.scene.time))