Skip to content

Commit

Permalink
Merge pull request #138 from Absulit/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Absulit authored Aug 23, 2024
2 parents 52a7f55 + 22808bb commit 0619c2c
Show file tree
Hide file tree
Showing 11 changed files with 371 additions and 2 deletions.
41 changes: 41 additions & 0 deletions examples/droste_effect_1/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import vert0 from './renderpass0/vert.js';
import compute0 from './renderpass0/compute.js';
import frag0 from './renderpass0/frag.js';

import vert1 from './renderpass1/vert.js';
import compute1 from './renderpass1/compute.js';
import frag1 from './renderpass1/frag.js';

import Points from 'points';
import ShaderType from 'shadertype';
import RenderPasses from 'renderpasses';
import RenderPass from 'renderpass';


/**
* Genuary 3: Droste Effect
* http://roy.red/posts/droste/
* https://github.com/ruby-processing/picrate-examples/blob/master/library/video/capture/data/droste.glsl
*/

const base = {

renderPasses: [
new RenderPass(vert0, frag0, compute0),
new RenderPass(vert1, frag1, compute1)
],
/**
*
* @param {Points} points
*/
init: async (points, folder) => {
points.setSampler('imageSampler', null, ShaderType.FRAGMENT);
points.setTexture2d('feedbackTexture', true);
points.setStorage('variables', 'Variables');
points.setStorage('colors', 'array<vec3f, 6>');
},
update: points => {
}
}

export default base;
30 changes: 30 additions & 0 deletions examples/droste_effect_1/renderpass0/compute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { structs } from '../structs.js';

const compute = /*wgsl*/`
${structs}
@compute @workgroup_size(8,8,1)
fn main(
@builtin(global_invocation_id) GlobalId: vec3<u32>,
@builtin(workgroup_id) WorkGroupID: vec3<u32>,
@builtin(local_invocation_id) LocalInvocationID: vec3<u32>
) {
if(variables.init == 0){
var index = 0;
colors[index] = vec3f(248, 208, 146) / 255; index++;
colors[index] = vec3f(21, 144, 151) / 255; index++;
colors[index] = vec3f(56, 164, 140) / 255; index++;
colors[index] = vec3f(26, 86, 120) / 255; index++;
colors[index] = vec3f(37, 36, 93) / 255; index++;
colors[index] = vec3f(87, 28, 86) / 255; index++;
variables.init = 1;
}
}
`;

export default compute;
127 changes: 127 additions & 0 deletions examples/droste_effect_1/renderpass0/frag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { fnusin } from 'animation';
import { structs } from '../structs.js';
const frag = /*wgsl*/`
${fnusin}
${structs}
fn opSmoothSubtraction(d1: f32, d2: f32, k: f32) -> f32{
let h = clamp(.5 - .5 * (d2 + d1) / k, 0., 1.);
return mix(d2, -d1, h) + k * h * (1. - h);
}
fn smin(d1: f32, d2: f32, k: f32) -> f32{
let h = max(k-abs(d1-d2), 0.)/k;
return min(d1, d2) - h*h*h*k*(1./6.);
}
fn sdBox(p:vec3f, b: vec3f) -> f32 {
let q = abs(p) - b;
return length(max(q, vec3f(0.) )) + min(max(q.x, max(q.y, q.z)), 0.);
}
fn rot2d(angle: f32) -> mat2x2<f32> {
let s = sin(angle);
let c = cos(angle);
return mat2x2(c, -s, s, c);
}
fn paletteLerp(a:array<vec3f,6>, value:f32) -> vec3f {
let numElements = 6.;
let elementPercent = 1 / numElements;
let index = value / elementPercent;
let minIndex = i32(floor(index));
let maxIndex = i32(ceil(index));
let a0 = a[minIndex];
let a1 = a[maxIndex];
return mix(a0, a1, fract(index));
}
fn map(p: vec3f, step:f32) -> f32 {
// input copy to rotate
var q = p;
var qRotated = q.xy * rot2d(params.time * .53);
q = vec3(qRotated, q.z);
qRotated = q.xz * rot2d(params.time * .633);
q = vec3(qRotated, q.y);
// scale down by 4 with p*4 and correcting distotrion dividing by 4
let scale = .5;
// for repetition
let boxBase = sdBox(q * scale, vec3(.5)) / scale; // cube sdf
let boxHollow1 = sdBox(q * scale, vec3(.4,.4, 1.)) / scale; // cube sdf
let boxHollow2 = sdBox(q * scale, vec3(1.,.4, .4)) / scale; // cube sdf
let boxHollow3 = sdBox(q * scale, vec3(.4,1., .4)) / scale; // cube sdf
var box = opSmoothSubtraction(boxHollow1, boxBase, .1);
box = opSmoothSubtraction(boxHollow2, box, .1);
box = opSmoothSubtraction(boxHollow3, box, .1);
let ground = p.y + .75;
// closest distance to the scene
return smin(ground, box, 1.);
}
@fragment
fn main(
@location(0) color: vec4<f32>,
@location(1) uv: vec2<f32>,
@location(2) ratio: vec2<f32>, // relation between params.screen.x and params.screen.y
@location(3) uvr: vec2<f32>, // uv with aspect ratio corrected
@location(4) mouse: vec2<f32>,
@builtin(position) position: vec4<f32>
) -> @location(0) vec4<f32> {
let sliderA = 1.;
let sliderB = .1116;
let uv2 = uvr * 4 - (vec2(2) * ratio); // clip space
// let m = mouse * 4 - (vec2(2) * ratio);
let m = vec2f(.5, .5) * 4 - (vec2(2) * ratio);
// initialization
var ro = vec3f(0, 0, -3); // ray origin
var rd = normalize(vec3(uv2 * sliderB * 5, 1)); // ray direction one ray per uv position
var t = 0.; // total distance traveled // travel distance
var col = vec3f();
// Vertical camera rotation
let mouseRotY = rot2d(-m.y);
// ro.xz *= rot2d(-m.x);
ro = vec3(ro.x, ro.yz * mouseRotY);
// rd.xz *= rot2d(-m.x);
rd = vec3(rd.x, rd.yz * mouseRotY);
// Horizontal camera rotation
let mouseRotX = rot2d(-m.x);
// ro.xz *= rot2d(-m.x);
ro = vec3(ro.xz * mouseRotX, ro.y).xzy;
// rd.xz *= rot2d(-m.x);
rd = vec3(rd.xz * mouseRotX, rd.y).xzy;
// Raymarching
var i = 0;
for (; i < 80; i++) {
let p = ro + rd * t; // position along the ray
let d = map(p, f32(i)); // current distance to the scene
t += d; // "march" the ray
// early stop if close enough, test this .001 value with others to test
// early stop if too far
if(d < .001 || d > 100.){
break;
}
}
let value = (t * sliderA * f32(i) * .005);
col = paletteLerp(colors, value);
return vec4(col, 1);
}
`;

export default frag;
17 changes: 17 additions & 0 deletions examples/droste_effect_1/renderpass0/vert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { structs } from '../structs.js';

const vert = /*wgsl*/`
${structs}
@vertex
fn main(
@location(0) position: vec4<f32>,
@location(1) color: vec4<f32>,
@location(2) uv: vec2<f32>,
@builtin(vertex_index) vertexIndex: u32
) -> Fragment {
return defaultVertexBody(position, color, uv);
}
`;

export default vert;
15 changes: 15 additions & 0 deletions examples/droste_effect_1/renderpass1/compute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { structs } from '../structs.js';

const compute = /*wgsl*/`
${structs}
@compute @workgroup_size(8,8,1)
fn main(
@builtin(global_invocation_id) GlobalId: vec3<u32>,
@builtin(workgroup_id) WorkGroupID: vec3<u32>,
@builtin(local_invocation_id) LocalInvocationID: vec3<u32>
) {
// let time = params.time;
}
`;

export default compute;
106 changes: 106 additions & 0 deletions examples/droste_effect_1/renderpass1/frag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { sdfLine2, sdfSegment } from 'sdf';
import { fnusin } from 'animation';
import { snoise } from 'noise2d';
import { PI, E, rotateVector } from 'math';
import { texturePosition } from 'image';
import { RGBAFromHSV, layer } from 'color';
import { structs } from '../structs.js';
const frag = /*wgsl*/`
${structs}
${fnusin}
${snoise}
${sdfSegment}
${sdfLine2}
${PI}
${E}
${texturePosition}
${rotateVector}
${layer}
${RGBAFromHSV}
const RADIAN = 0.0174533;
fn sdfRing(position:vec2f, radius1:f32, uv:vec2f) -> f32 {
let d = distance(uv, position);
let st0 = 1. - smoothstep(radius1, radius1, d);
let st1 = smoothstep(radius1 - .004, radius1 - .004, d);
return st0 * st1;
}
fn annulus(position:vec2f, radius1:f32, radius2:f32, uv:vec2f) -> f32 {
let ring1 = sdfRing(position, radius1, uv);
let ring0 = sdfRing(position, radius2, uv);
const w = .004;
var vertical = sdfLine2(position + vec2(0, radius1), position + vec2(0, radius2), w, uv);
vertical += sdfLine2(position + vec2(0, -radius1), position + vec2(0, -radius2), w, uv);
var horizontal = sdfLine2(position + vec2(radius1, 0), position + vec2(radius2, 0), w, uv);
horizontal += sdfLine2(position + vec2(-radius1, 0), position + vec2(-radius2, 0), w, uv);
return ring0 + ring1 + vertical + horizontal;
}
fn complexExp(z: vec2f) -> vec2f {
return vec2(exp(z.x)*cos(z.y),exp(z.x)*sin(z.y));
}
fn complexLog(z: vec2f) -> vec2f {
return vec2(log(length(z)), atan2(z.y, z.x));
}
fn complexMult(a:vec2f, b:vec2f) -> vec2f {
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}
fn complexMag(z:vec2f) -> f32 {
return pow(length(z), 2.0);
}
fn complexReciprocal(z:vec2f) -> vec2f {
return vec2(z.x / complexMag(z), -z.y / complexMag(z));
}
fn complexDiv(a:vec2f, b:vec2f) -> vec2f {
return complexMult(a, complexReciprocal(b));
}
@fragment
fn main(
@location(0) color: vec4<f32>,
@location(1) uv: vec2<f32>,
@location(2) ratio: vec2<f32>, // relation between params.screen.x and params.screen.y
@location(3) uvr: vec2<f32>, // uv with aspect ratio corrected
@location(4) mouse: vec2<f32>,
@builtin(position) position: vec4<f32>
) -> @location(0) vec4<f32> {
let sliderA = .192;
let sliderB = 1 + 40 * fnusin(1);
let r1 = 0.3;
let r2 = 0.7;
let pos = vec2f(0);
var z = (uvr * 2) - (vec2(1) * ratio);
z = z * sliderB * 10;
// 4. Take the tiled strips back to ordinary space.
z = complexLog(z);
// 3. Scale and rotate the strips
let scale = log(r2/r1);
// Negate the angle to twist the other way
let angle = atan(scale/(2.0*PI));
z = complexDiv(z, complexExp(vec2(0,angle))*cos(angle));
// 2. Tile the strips
z.x = z.x % log(r2/r1);
// 1. Take the annulus to a strip
z = complexExp(z) * r1;
let c = RGBAFromHSV( atan2(z.y,z.x)/PI*2,1.,1.);
let imageColor = texturePosition(feedbackTexture, imageSampler, vec2(-.5) * ratio, z / sliderA / 10 , false);
var a = annulus(pos, r1, r2, z);
let board = sin(z*20.0)*10.;
return imageColor;
}
`;

export default frag;
17 changes: 17 additions & 0 deletions examples/droste_effect_1/renderpass1/vert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { structs } from '../structs.js';

const vert = /*wgsl*/`
${structs}
@vertex
fn main(
@location(0) position: vec4<f32>,
@location(1) color: vec4<f32>,
@location(2) uv: vec2<f32>,
@builtin(vertex_index) vertexIndex: u32
) -> Fragment {
return defaultVertexBody(position, color, uv);
}
`;

export default vert;
7 changes: 7 additions & 0 deletions examples/droste_effect_1/structs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const structs = /*wgsl*/`
struct Variables {
init: i32,
}
`;
1 change: 1 addition & 0 deletions examples/index_files/shader_projects.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion examples/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ const authorLinkEl = infoEl.querySelector('#author-link');

async function loadShaderByIndex(index) {
console.clear();
if (index > shaderProjects.length) {
index = 0;
}

localStorage.setItem('selected-shader', index);
const shaderProject = shaderProjects[index];
sourceBtn.href = `https://github.com/Absulit/points/tree/master/examples/${shaderProject.uri}`;
Expand Down Expand Up @@ -137,7 +141,7 @@ async function loadShaderByURI() {
}

lastSelected = Array.from(document.querySelectorAll('#nav a')).filter(a => a.index == index)[0];
lastSelected.classList.add('selected');
lastSelected?.classList.add('selected');
}

//---
Expand Down
Loading

0 comments on commit 0619c2c

Please sign in to comment.