GithubHelp home page GithubHelp logo

anvaka / pplay Goto Github PK

View Code? Open in Web Editor NEW
80.0 6.0 7.0 6.79 MB

Create, play and share pixels. Online WebGL shader editor.

Home Page: https://anvaka.github.io/pplay/

License: MIT License

JavaScript 28.42% HTML 0.43% Vue 13.54% GLSL 54.92% Shell 0.08% Stylus 2.61%

pplay's Introduction

Pixel Play

This website allows you to play with pixels on the screen using WebGL. All you need to do is fill in a function that takes a point and returns its color:

f(coordinate) => color

You can immediately see the scene, pan and zoom around (as if it was Google Maps):

demo

Once you like what you've created - you can simply copy the link and share it with the world (e.g. /r/pplay).

Example

If you click "Randomize" button, the website will generate a fractal.

randomize demo

It is very easy to generate a fractal with just couple lines. All you need to do is update a sum inside the loop.

vec4 get_color(vec2 p) {
  float t = 0.;
  vec2 z = vec2(0.);
  vec2 c = p;

  for(int i = 0; i < 32; ++i) {
    if (length(z) > 2.) break;
    // Change this line to get a new fractal
    z = c_mul(z, z) + c;
    t = float(i);
  }

  return length((z)) * vec4(t * vec3(1./64., 1./32., 1./24.), 1.0);
}

Changing initial condition (variable c) or the final color code (where we return vec4) often produces very different and beautiful fractals.

Here are just a few examples. Click on any image above to explore fractal and try to find any difference between code - it is going to be very small.

zz zz_tanh zz_p_mul zz_inv_sin

Not only fractals

To be honest, this is a very generic tool. All it does is that one function. Take a coordinate of a point, and output a color.

Coordinate of a point is given by variable vec2 p, so you can get p.x, and p.y.

The color is returned from the main function return vec4(r, g, b, a) - each component of this vector corresponds to color, and ranges between 0 and 1.

Given this information, we can change the output to anything we want:

live edit

Here we first set color to a blue-ish color vec4(0.1, 0.2, 0.4, 1.), and then mixed it with coordinates of a point.

I have also used a special variable called iFrame - it is always equal to the current frame number (increases with time). So we can use a periodic function like sin to get animation. You can find more special variables below

You can use this tool to quickly visualize implicit curves too.

Extended functionality

Pixel play comes with small library of functions and variables.

External variables

Variables are modeled after shadertoy.com conventions and are available for you to use in your code:

// Current frame number, counted from launch of the program
uniform float iFrame;

// How many seconds passed since program launch
uniform float iTime;

// Mouse (or touch) coordinates. `.xy` - current, `.zw` - last clicked.
// Note: To translate coordinates to scene coordinates use
// screen2scene(iMouse.xy) -> vec2 method.
uniform vec4 iMouse;

// screen resolution
uniform vec2 iResolution;

Complex numbers math

Each complex number is a 2d vector (vec2 type). Standard GLSL multiplication/division rules cannot be applied to complex numbers, so we have a helper function: c_mul(z1, z2) and c_div(z0, z1) multiplies and divides two complex numbers.

Other trigonometric functions are available with prefix c_. (e.g. c_sin(z), c_cos(z), c_tanh(z), and so on).

You can find the list of them all here.

Query string limit

By default your code is saved in the query string. However, if it exceeds 1,000 characters it cannot be saved (as browsers do not support long query strings). This shouldn't be a problem if you don't want to share your code.

But if you want to share what you've created you will need to save your code with .glsl extension on https://gist.github.com/ and then update the query string of the PixelPlay:

  1. Delete fc query argument (if present)
  2. Add gist=gistId

When you save a gist it will give you the url like this: https://gist.github.com/anvaka/0f11251039eb366630bc7ca08ce0eefd

  • those numbers are your gistId. The final url will look like this:

https://anvaka.github.io/pplay/?gist=0f11251039eb366630bc7ca08ce0eefd&tx=0.284&ty=0.284&scale=0.471

Audio channel

It is possible to make audio channel accessible to a shader. I'm still not sure what is the best way to model this (your suggestions are appreciated!), but here is how it is constructed now.

Each of the 512 columns in the texture row represent a frequency, encoded in rgba format:

  • r - immediate frequency value
  • g - average frequency value (calculated as g = prev_g * 0.5 + r * 0.5)
  • b - "long" average frequency value (calculated as b = 0.9 * prev_b + r * 0.1)
  • a - is not used at the moment.

Immediate value is usually very "spiky", while b is smoothed out.

First two rows of the texture alternate between current and previous rendering frame. On odd frame number row 0 represent current audio buffer, and 1 is previous buffer. On even frame number this is inverse ( current audio signal will be in the row 1, while previous signal is in the row 0). This alternation is done to preserve CPU cycles and not move data unnecessarily.

Rows 3 and 4 are also alternating between current and previous frame, but they serve as aggregation mechanism:

  • Columns 0 .. 255 store average value of frequency pairs. I.e. column(i) = (freq[i] + freq[i + 1])/2
  • Columns 256 .. 383 store average value of average pairs in the first 256 columns. I.e. column(256 + i/2) = column(i) + column(i + 1)
  • .. and so on ..

For example, consider the following row of original frequencies:

Original row:    2    2    1    3    4    6    1    3
 Aggregation:       2         2         5         2

As you can see, we only need four elements to store aggregated pairs of the first row, so, let's use remaining columns in the aggregation row, to aggregate aggregations:

       Aggregation:      2         2         5         2
Aggregation (cont):            2                 3.5
Aggregation (cont):                  2.75

Or, if we flatten aggregation row out:

Original row:    2    2    1    3    4    6    1    3
 Aggregation:    2    2    5    2    2   3.5  2.75 nil

This aggregation row is created to avoid summation and cycles in the shader. If you need to know average volume of the sound, you can just look at second to the last value, you don't need to

(2 + 2 + 1 + 3 + 4 + 6 + 1 + 3)/8 = 2.75

You just look at the second to the last column in the aggregation row. Here is a snippet to fetch audio frequency at a given column/row:

vec4 getBandValue(float bandId, float row) {
  // assuming sound is bound to `iChannel0`
  return texture2D(iChannel0, vec2((bandId + 0.5)/512., (row + 0.5)/4.));
}
// then you can use it like so:

// This takes current frequency value in bin 42.
vec4 imm = getBandValue(42., mod(iFrame + 1., 2.));
// This takes previous frame frequency value in bin 42.
vec4 imm_prev = getBandValue(42., mod(iFrame, 2.));

// To get average volume of the current frame:
vec4 avg_Volume = getBandValue(510., mod(iFrame + 1., 2.) + 2.);

// To get average aggregated low frequency of the current frame (bass)
// 498. = 512. - 2. - 4. - 8.
vec4 avg_bass = getBandValue(498., mod(iFrame + 1., 2.) + 2.);

Here is an example of the three histograms:

histogram

  • The first row is a smoothed, long average (b component).
  • The second row is an average value (g component);
  • The last row is immediate value (r component)

From left to right the histograms represent average value of the previous histogram:

original <- avg <- avg of avg <- avg of avg of avg ...

If you are using a desktop computer, you can click on the image above to open it and see interactive play. Why desktop? Because of the following caveat:

Caveat

Keep in mind, that Apple does not support audio element analysis in iOS.

Thanks

Thank you for reading this!

I hope you find this project useful and fun to play with. Please don't forget to share what you find or learn.

Local build

# install dependencies
npm install

# serve with hot reload at localhost:8889
npm start

License

MIT

pplay's People

Contributors

anvaka avatar

Stargazers

Victor Anton Dominguez avatar  avatar Alex avatar  avatar  avatar stagas avatar Igor Strozzi avatar elliot avatar Waleed AlMalki avatar Ryan Atkinson avatar jinho park avatar Sebastian Björkqvist avatar Manuela Malasaña avatar Dylan Hogg avatar zuiidea avatar Zach Gawlik avatar Marcello Seri avatar Alvar Hansen avatar I. J. Kennedy avatar Robert Khayat avatar Alexander Karren avatar  avatar Clément avatar Takeshi Sato avatar Simon Lecoq avatar 3Domse3 avatar Basil Papadimas avatar Mike Sosa avatar  avatar Rose Kay avatar  avatar  avatar Leon avatar William C Bonner avatar 阿译长官(川军团副团长、督导林译) avatar  avatar  avatar  avatar Chizard avatar SHIMIZU Taku avatar makoto avatar  avatar Zudo avatar Volodymyr avatar Strider avatar Spencer Yue avatar  avatar L avatar  avatar Wolfger Schramm avatar Brian Yang avatar Andros avatar Eric Kennedy avatar Jesse Talavera avatar Nick Porcino avatar Brian Moore avatar J. Deck avatar David Hirmes avatar Michael Sumner avatar timelyportfolio avatar  avatar Taras Novak avatar  avatar Deam avatar Frank Blendinger avatar Chris Cajas avatar Justin Sisley avatar lyrachord avatar Markus Kohler avatar Hogan Kangas avatar Athan avatar Jamil avatar Denis Denisov avatar Daniel Lewan avatar Nikita avatar A avatar Nicola Del Gobbo avatar Guillaume Gomez avatar Luis Sevillano avatar Aydin avatar

Watchers

 avatar Nick Porcino avatar Andros avatar timelyportfolio avatar James Cloos avatar  avatar

pplay's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.