Skip to content

Commit

Permalink
added custom glsl stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
ojack committed Dec 2, 2023
1 parent f842624 commit b6cf243
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 21 deletions.
Empty file.
142 changes: 121 additions & 21 deletions content/docs/learning/extending-hydra/glsl.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,138 @@ title: Custom GLSL

## Using custom GLSL functions

Hydra is built using GLSL (a language for generating a program, or shader, that runs directly on the graphics card using WebGl). Each javascript function in hydra corresponds directly to a snippet of shader code. Hydra has a unique way of adding custom source and transform functions which we will explain here.
Hydra is built using GLSL (a language for generating a program, or shader, that runs directly on the graphics card using WebGl). Each javascript function in hydra corresponds directly to a snippet of shader code. There are four possible types in hydra: src, coord (geometry), combine (blend), combineCoord (modulate). Each string of functions is composited based on its type into a single string of fragment shader code.

### setFunction
You can see the glsl for each existing hydra function in [glsl-functions.js](https://github.com/hydra-synth/hydra-synth/blob/main/src/glsl/glsl-functions.js) of the hydra source code.

The Hydra API includes a function called `setFunction` which receives a specific type of JavaScript object. This object will have the properties `name`, `type`, `inputs` and `glsl`.
You can see the fragment shader code generated by a chain of functions in hydra, by replacing the `.out()` in a function chain with `.glsl()`, and then logging the results.

For example, `console.log(osc().glsl()[0])` will show the fragment shader generates by `osc()` in the browser console.


## setFunction

The hydra-synth API includes a function called `setFunction` which lets you dynamically add a function with custom GLSL and custom name, and use it elsewhere in the code.
* `name` is a String with the name for the function
* `type` is one of the available types of functions ('src', 'color', 'coord', 'combine', 'combineCoord')
* `inputs` is an Array of objects each with it's own `name`, `type` and `default` properties. They represent the arguments of the GLSL function.
* `type` is one of the available types of functions ('src', 'color', 'coord', 'combine', 'combineCoord', esplained below)
* `inputs` is an Array of objects each with it's own `name`, `type` and `default` properties. These become the arguments of the generated GLSL function.
* `glsl` is a String with the glsl code.

#### Example

### Example
For example, the following code:
```javascript
setFunction({
name: 'myOsc',
type: 'src',
inputs: [
{ name: 'freq', type: 'float', default: 20 }
],
glsl: `
return vec4(sin((_st.x+time)*freq*vec3(0.1)),1.0);
`
name: 'gradient2',
type: 'src',
inputs: [
{
type: 'float',
name: 'speed',
default: 0,
}
],
glsl:
` return vec4(sin(time*speed), _st, 1.0);`
})
```
will generate the glsl function:

```C
vec4 gradient2(vec2 _st, float speed){
return vec4(sin(time*speed), _st, 1.0);;
}
```
### Types of GLSL functions and their arguments
that is then usable in hydra using `gradient2().out()`
#### src
full example:
```hydra
setFunction({
name: 'gradient2',
type: 'src',
inputs: [
{
type: 'float',
name: 'speed',
default: 0,
}
],
glsl:
` return vec4(sin(time*speed), _st, 1.0);`
})
//
gradient2(1).out()
```

## Types of GLSL functions and their arguments
Types and default arguments for hydra functions.
The value in the 'type' field lets the parser know which type of function will be returned as well as default arguments.


```javascript
const types = {
'src': {
returnType: 'vec4',
args: ['vec2 _st']
},
'coord': { // geometry
returnType: 'vec2',
args: ['vec2 _st']
},
'color': {
returnType: 'vec4',
args: ['vec4 _c0']
},
'combine': { // blending
returnType: 'vec4',
args: ['vec4 _c0', 'vec4 _c1']
},
'combineCoord': { // modulation
returnType: 'vec2',
args: ['vec2 _st', 'vec4 _c0']
}
}

```

### src

A function with a specified type of `src` is one that generates visuals by its own. Just like `osc` or `noise`. They all have a `vec2` argument called `_st` for the coordinate. And you can add any custom inputs as shown above. You must return a `vec4`.

#### color
```hydra
setFunction({
name: 'myOsc',
type: 'src',
inputs: [
{
type: 'float',
name: 'frequency',
default: 60,
},
{
type: 'float',
name: 'sync',
default: 0.1,
},
{
type: 'float',
name: 'offset',
default: 0,
}
],
glsl:
` vec2 st = _st;
float r = sin((st.x-offset/frequency+time*sync)*frequency)*0.5 + 0.5;
float g = sin((-st.x+time*sync*2.)*frequency)*0.5 + 0.5;
float b = sin((st.x+offset/frequency+time*sync)*frequency)*0.5 + 0.5;
return vec4(r, g, b, 1.0);`
})
myOsc(10).out()
```


### color

A `color` function receives a `vec4` called `_c0` that represents the color being affected by the transform. As any function you may add any extra inputs. You must return another `vec4`.

Expand All @@ -56,7 +156,7 @@ osc(60,.1,5).switchColors()
.out()
```

#### coord
### coord

A `coord` function receives a `vec2` called `_st` that represents the coordinate plane. You must return another `vec2`.

Expand All @@ -76,7 +176,7 @@ osc(60,.1,5).tan(2)
.out()
```

#### combine
### combine

The functions of type `combine` receive 2 `vec4` arguments, `_c0` and `_c1`. The first one represents the texture being affected and the latter represents the texture being blended into the former. For example, when you use `osc().mult(noise())`, inside the definition of the function, `_c0` represents the `osc()` and `_c1` represents the `noise()` colors. You can think combine functions as blending modes. And as custom function you may add extra inputs as needed. You must return a `vec4`.

Expand All @@ -96,7 +196,7 @@ osc().negate(noise().brightness(.5))
.out()
```

#### combineCoord
### combineCoord

`combineCoord` functions change the position of colors in the texture being affected given the colors of another texture. Think about the many modulate functions for example, since they are precisely this type. They receive a `vec2 _st` and a `vec4 _c0`. You must return a `vec2`.

Expand Down

0 comments on commit b6cf243

Please sign in to comment.