A few shader samples

This commit is contained in:
Emily 2020-02-12 13:11:57 +01:00
parent 84088247b4
commit c90938efbd
7 changed files with 145 additions and 63 deletions

67
main.py
View File

@ -2,72 +2,15 @@
import os import os
import math import math
from pixel import Pixel, Screen from pixel import Screen
WIDTH, HEIGHT = 100, 30 from shaders import eyeblower
WIDTH, HEIGHT = 100, 30 # Set to -1, -1 for dynamic resolution
STD_HANDLE = 1 # Would want this to be 0, but it can cause issues STD_HANDLE = 1 # Would want this to be 0, but it can cause issues
def shad_background(pixel: Pixel, x: int, y: int, time: float):
uv = (x / WIDTH, y / HEIGHT)
h = math.sin(uv[0] * math.pi + uv[1] * 10.0 + time + math.cos(uv[0] * uv[1] + uv[1] * 7.1823) * math.sin(uv[0] * 14.2))
pixel.background_color.set(h, h, h)
def shad_wave(pixel: Pixel, x: int, y: int, time: float): # https://www.shadertoy.com/view/Wd23W3
uv = (x / WIDTH, y / HEIGHT)
def hsv2rgb(h, s, v) -> tuple:
r,g,b = 0,0,0
i = int(h * 6)
f = h * 6 - i
p = v * (1 - s)
q = v * (1 - f * s)
t = v * (1 - (1 - f) * s)
o = i % 6
if o == 0:
r,g,b = v,t,p
elif o == 1:
r,g,b = q,v,p
elif o == 2:
r,g,b = p,v,t
elif o == 3:
r,g,b = p,q,v
elif o == 4:
r,g,b = t,p,v
else:
r,g,b = v,p,q
return r, g, b
def step(edge: float, value: float) -> float:
return 1.0 if value > edge else 0.0
def strip(h: float, thickness: float, y: float) -> float:
return step(y + h - thickness, step(1., y + h + thickness))
col = [0.0, 0.0, 0.0]
f = 0.0
while f < math.pi * 2:
a = strip(.5 + math.cos(uv[0] * 2. + time * 3.) * .15,
.005,
uv[1] + math.cos(uv[0] * 3. + time * 2. + f) * .25)
_col = hsv2rgb(f / math.pi / 2., 1., 1.)
for i in range(3):
col[i] += a * _col[i]
f += math.pi / 4.
pixel.text_color.set(*col)
screen = Screen(WIDTH, HEIGHT, STD_HANDLE, [ screen = Screen(WIDTH, HEIGHT, STD_HANDLE, [
shad_background eyeblower.main
#shad_wave
]) ])
screen.mainloop() screen.mainloop()

View File

@ -80,6 +80,8 @@ class Screen:
self.time_start = datetime.datetime.now() self.time_start = datetime.datetime.now()
self.buffer = "" self.buffer = ""
self.dynamic = self.height < 0 and self.width < 0
def get_time(self): def get_time(self):
return (datetime.datetime.now() - self.time_start).total_seconds() return (datetime.datetime.now() - self.time_start).total_seconds()
@ -95,6 +97,10 @@ class Screen:
while True: while True:
width, height = os.get_terminal_size(self.std_handle) width, height = os.get_terminal_size(self.std_handle)
if self.dynamic:
self.width, self.height = width, height
if width < self.width or height < self.height: if width < self.width or height < self.height:
Screen.clear() Screen.clear()
print("Unable to print the screen, a terminal with %dx%d (and above) chars are required to continue" % (self.width, self.height)) print("Unable to print the screen, a terminal with %dx%d (and above) chars are required to continue" % (self.width, self.height))
@ -103,10 +109,11 @@ class Screen:
time = self.get_time() time = self.get_time()
resolution = (self.width, self.height)
for y in range(self.height): for y in range(self.height):
for x in range(self.width): for x in range(self.width):
for render_func in self.render_funcs: for render_func in self.render_funcs:
render_func(pixel, x, y, time) render_func(pixel, resolution, (x, y), time)
self.write(str(pixel)) self.write(str(pixel))
pixel.reset() pixel.reset()
self.write("\x1b[0m\n") # newline self.write("\x1b[0m\n") # newline

8
shaders/background.py Normal file
View File

@ -0,0 +1,8 @@
import math
from pixel import Pixel
def main(pixel: Pixel, resolution: tuple, frag_coord: tuple, time: float):
uv = (frag_coord[0] / resolution[0], frag_coord[1] / resolution[1])
h = math.sin(uv[0] * math.pi + uv[1] * 10.0 + time + math.cos(uv[0] * uv[1] + uv[1] * 7.1823) * math.sin(uv[0] * 14.2))
pixel.background_color.set(h, h, h)

11
shaders/default.py Normal file
View File

@ -0,0 +1,11 @@
import math
from pixel import Pixel
def main(pixel: Pixel, resolution: tuple, frag_coord: tuple, time: float):
uv = (frag_coord[0] / resolution[0], frag_coord[1] / resolution[1])
pixel.background_color.set(
0.5 + 0.5 * math.cos(time + uv[0]),
0.5 + 0.5 * math.cos(time + uv[1] + 2),
0.5 + 0.5 * math.cos(time + uv[0] + 4)
)

40
shaders/eyeblower.py Normal file
View File

@ -0,0 +1,40 @@
import math
from pixel import Pixel
FREQUENCY = 20.0
COLOR_A = (1.0, 0.5, 0.9)
COLOR_B = (0.5, 0.1, 0.3)
def distance(a: tuple, b: tuple) -> float:
if len(a) != len(b):
raise TypeError("Mismatching dimentional vector passed")
dist = 0
for i in range(len(a)):
d = b[i] - a[i]
dist += d * d
return dist ** 0.5
def sign(v: float) -> float:
return 1.0 if v >= 0 else 0.0
def main(pixel: Pixel, resolution: tuple, frag_coord: tuple, time: float): # https://www.shadertoy.com/view/ldX3DN
uv = tuple(-1.0 + 2.0 * x for x in (frag_coord[0] / resolution[0], frag_coord[1] / resolution[1]))
homo_coords = (uv[0], 2.0 * frag_coord[1] / resolution[0])
moving_origin1 = (math.sin(time * 0.7), math.sin(time * 1.7))
moving_origin2 = (-math.cos(time * 2.0), -math.sin(time * 3.0))
wave_point1 = math.sin( distance(moving_origin1, homo_coords) * FREQUENCY )
wave_point2 = math.sin( distance(moving_origin2, homo_coords) * FREQUENCY )
black_or_white1 = sign(wave_point1)
black_or_white2 = sign(wave_point2)
composite = black_or_white1 * black_or_white2
col = tuple(max(COLOR_A[i] * composite, COLOR_B[i]) for i in range(3))
pixel.background_color.set( *col )

20
shaders/ripples.py Normal file
View File

@ -0,0 +1,20 @@
import math
from pixel import Pixel
def main(pixel: Pixel, resolution: tuple, frag_coord: tuple, time: float): # https://www.shadertoy.com/view/ldX3zr
invAr = resolution[1] / resolution[0]
uv = (frag_coord[0] / resolution[0], frag_coord[1] / resolution[1])
col = [*uv, 0.5 + 0.5 * math.sin(time)]
x = 0.5 - uv[0]
y = (0.5 - uv[1]) * invAr
r = -(x * x + y * y)
z = 1.0 + 0.5 * math.sin((r + time * 0.035) / 0.013)
for i in range(3):
col[i] *= z
pixel.background_color.set( *col )

53
shaders/wave.py Normal file
View File

@ -0,0 +1,53 @@
import math
from pixel import Pixel
def main(pixel: Pixel, resolution: tuple, frag_coord: tuple, time: float):
uv = (frag_coord[0] / resolution[0], frag_coord[1] / resolution[1])
def hsv2rgb(h, s, v) -> tuple:
r,g,b = 0,0,0
i = int(h * 6)
f = h * 6 - i
p = v * (1 - s)
q = v * (1 - f * s)
t = v * (1 - (1 - f) * s)
o = i % 6
if o == 0:
r,g,b = v,t,p
elif o == 1:
r,g,b = q,v,p
elif o == 2:
r,g,b = p,v,t
elif o == 3:
r,g,b = p,q,v
elif o == 4:
r,g,b = t,p,v
else:
r,g,b = v,p,q
return r, g, b
def step(edge: float, value: float) -> float:
return 1.0 if value > edge else 0.0
def strip(h: float, thickness: float, y: float) -> float:
return step(y + h - thickness, step(1., y + h + thickness))
col = [0.0, 0.0, 0.0]
f = 0.0
while f < math.pi * 2:
a = strip(.5 + math.cos(uv[0] * 2. + time * 3.) * .15,
.005,
uv[1] + math.cos(uv[0] * 3. + time * 2. + f) * .25)
_col = hsv2rgb(f / math.pi / 2., 1., 1.)
for i in range(3):
col[i] += a * _col[i]
f += math.pi / 4.
pixel.background_color.set(*col)