Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add iDate builtin to Shadertoy utility #428

Merged
merged 8 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions examples/shadertoy_glsl_clock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from wgpu.utils.shadertoy import Shadertoy

shader_code = """
// source: https://www.shadertoy.com/view/MdVcRd

// See https://www.shadertoy.com/view/ldKGRR

// Computes a smooth-edged diamond pixel value (Manhattan distance)
#define P(i, j, b) \
vec2(.1, b).xyxy * smoothstep(0., 9. / R.y, .1 - abs(i) - abs(j))

// Computes a segment value (length = 0.5)
#define S(i, j, b) \
P(i - clamp(i, 0., .5), j, b & 1)

// Colon render
#define C \
x += .5; O += P(x, y + .3, i.w / 50) + P(x, y - .3, i.w / 50); t /= 60

// Hyphen render
#define H(b) \
++x; O += S(x, y, b)

// Computes the horizontal and vertical segments based on a denary digit
#define X(i, j, b) \
S(x - i, y - j, b)
#define Y(i, j, b) \
S(y - j, x - i, b)
#define D(n) \
H(892>>n) \
+ X(0., .7, 1005>>n) \
+ X(0., -.7, 877>>n) \
+ Y(-.1, .1, 881>>n) \
+ Y(.6, .1, 927>>n) \
+ Y(-.1, -.6, 325>>n) \
+ Y(.6, -.6, 1019>>n);

// Two-digit render
#define Z(n) ; D(n % 10) D(n / 10)

void mainImage(out vec4 O, vec2 U)
{
vec2 R = iResolution.xy;
U += U - R;
U /= R.y / 3.; // Global scaling with aspect ratio correction
O-=O; // Zero the pixel

float x = U.x - U.y * .2 - 2.8, // Slight skew to slant the digits
y = --U.y;
ivec4 i = ivec4(iDate); // Convert everything to integers
int t = i.w;
i.w = int(iDate.w * 100.) % 100 // Replace with centiseconds

// Seconds (preceded by a colon)
Z(t % 60)
C

// Minutes (preceded by a colon)
Z(t % 60)
C

// Hours
Z(t)

// Smaller digits
x /= .6;
y /= .6;
R *= .6;

// Centiseconds
x -= 14.;
y += .53
Z(i.w)

// Day (preceded by a hyphen)
x -= .8;
y += 3.
Z(i.z)
H(1)

// Month (preceded by a hyphen)
Z((i.y + 1)) // Is it a bug in shadertoy that we have to add one?
H(1)

// Year
Z(i.x % 100)
Z(i.x / 100)
}

""" # noqa
shader = Shadertoy(shader_code)

if __name__ == "__main__":
shader.show()
41 changes: 31 additions & 10 deletions wgpu/utils/shadertoy.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,20 @@
builtin_variables_glsl = """
#version 450 core

vec3 i_resolution;
vec4 i_mouse;
vec4 i_date;
vec3 i_resolution;
float i_time;
float i_time_delta;
int i_frame;

// Shadertoy compatibility, see we can use the same code copied from shadertoy website

#define iTime i_time
#define iMouse i_mouse
#define iDate i_date
#define iResolution i_resolution
#define iTime i_time
#define iTimeDelta i_time_delta
#define iMouse i_mouse
#define iFrame i_frame

#define mainImage shader_main
Expand All @@ -52,6 +54,7 @@

struct ShadertoyInput {
vec4 mouse;
vec4 date;
vec3 resolution;
float time;
float time_delta;
Expand All @@ -62,13 +65,13 @@
out vec4 FragColor;
void main(){

i_time = input.time;
i_mouse = input.mouse;
i_date = input.date;
i_resolution = input.resolution;
i_time = input.time;
i_time_delta = input.time_delta;
i_mouse = input.mouse;
i_frame = input.frame;


vec2 uv = vec2(uv.x, 1.0 - uv.y);
vec2 frag_coord = uv * i_resolution.xy;

Expand Down Expand Up @@ -107,8 +110,9 @@

builtin_variables_wgsl = """

var<private> i_resolution: vec3<f32>;
var<private> i_mouse: vec4<f32>;
var<private> i_date: vec4<f32>;
var<private> i_resolution: vec3<f32>;
var<private> i_time_delta: f32;
var<private> i_time: f32;
var<private> i_frame: u32;
Expand All @@ -123,6 +127,7 @@

struct ShadertoyInput {
mouse: vec4<f32>,
date: vec4<f32>,
resolution: vec3<f32>,
time: f32,
time_delta: f32,
Expand All @@ -141,10 +146,11 @@
@fragment
fn main(in: Varyings) -> @location(0) vec4<f32> {

i_time = input.time;
i_mouse = input.mouse;
i_date = input.date;
i_resolution = input.resolution;
i_time = input.time;
i_time_delta = input.time_delta;
i_mouse = input.mouse;
i_frame = input.frame;


Expand All @@ -169,6 +175,8 @@ class UniformArray:
"""Convenience class to create a uniform array.

Maybe we can make it a public util at some point.
Ensure that the order matches structs in the shader code.
See https://www.w3.org/TR/WGSL/#alignment-and-size for reference on alignment.
"""

def __init__(self, *args):
Expand Down Expand Up @@ -239,8 +247,9 @@ class Shadertoy:
* ``i_frame``: the frame number
* ``i_resolution``: the resolution of the shadertoy
* ``i_mouse``: the mouse position in pixels
* ``i_date``: the current date and time as a vec4 (year, month, day, seconds)

For GLSL, you can also use the aliases ``iTime``, ``iTimeDelta``, ``iFrame``, ``iResolution``, and ``iMouse`` of these built-in variables,
For GLSL, you can also use the aliases ``iTime``, ``iTimeDelta``, ``iFrame``, ``iResolution``, ``iMouse`` and ``iDate`` of these built-in variables,
the entry point function also has an alias ``mainImage``, so you can use the shader code copied from shadertoy website without making any changes.
"""

Expand All @@ -251,6 +260,7 @@ class Shadertoy:
def __init__(self, shader_code, resolution=(800, 450), offscreen=False) -> None:
self._uniform_data = UniformArray(
("mouse", "f", 4),
("date", "f", 4),
("resolution", "f", 3),
("time", "f", 1),
("time_delta", "f", 1),
Expand Down Expand Up @@ -429,6 +439,17 @@ def _update(self):
if not hasattr(self, "_frame"):
self._frame = 0

time_struct = time.localtime()
self._uniform_data["date"] = (
float(time_struct.tm_year),
float(time_struct.tm_mon - 1),
float(time_struct.tm_mday),
time_struct.tm_hour * 3600
+ time_struct.tm_min * 60
+ time_struct.tm_sec
+ now % 1,
)

self._uniform_data["frame"] = self._frame
self._frame += 1

Expand Down
Loading