Webgl2 Multipass-Rendering using custom shaders and my lightweight WebGl1+2 wrapper (dwgl.js).
https://github.com/diwi/p5.EasyCam
The Reaction Diffusion sketch is a port of the PixelFlow library for Processing.
Requires a browser that supports Webgl1 or Webgl2 and some extensions.
Oh, that naughty sketch! Please let us know what the issue is below.
Apply Template
Applying this template will reset your sketch and remove all your changes. Are you sure you would like to continue?
Report Sketch
Report Comment
Please confirm that you would like to report the comment below.
We will review your submission and take any actions necessary per our Community Guidelines. In addition to reporting this comment, you can also block the user to prevent any future interactions.
Please report comments only when necessary. Unnecessary or abusive use of this tool may result in your own account being suspended.
Are you sure you want to delete your sketch?
Any files uploaded will be deleted as well.
Delete Comment?
This will also delete all the replies to this comment.
Delete this tab? Any code in it will be deleted as well.
Select a collection to submit your sketch
We Need Your Support
Since 2008, OpenProcessing has provided tools for creative coders to learn, create, and share over a million open source projects in a friendly environment.
Niche websites like ours need your continued support for future development and maintenance, while keeping it an ad-free platform that respects your data and privacy!
Please consider subscribing below to show your support with a "Plus" badge on your profile and get access to many other features!
Mouse, [c] random colors
A fork of Reaction Diffusion Mirror by truestonee
CC Attribution ShareAlike
Reaction Diffusion Mirror
Sherman
xxxxxxxxxx
/**
* dwgl.js - a very lightweight webgl wrapper.
*
* Copyright 2018 by Thomas Diewald (https://www.thomasdiewald.com)
*
* MIT License: https://opensource.org/licenses/MIT
* ource: https://github.com/diwi/p5.EasyCam (will be moved)
*
* versions: webgl1, webgl2
*
*/
/**
* Note:
* This is just a draft and for experimental purposes only.
* To work with it you need a browser that supports webgl2.
*
* http://webglreport.com/?v=2
* https://caniuse.com/#feat=webgl2
* https://webglstats.com/
*
*/
/**
* This Reaction-Diffusion Demo is a port from the PixelFlow-Library.
* https://github.com/diwi/PixelFlow/tree/master/examples/Miscellaneous/ReactionDiffusion
*/
'use strict';
// framebuffer
var fbo;
let reference, refImg;
function preload(){
reference = loadImage("skull.jpeg");
}
// tex-struct (ping-pong)
var tex =
{
src : null,
dst : null,
swap : function(){
var tmp = this.src;
this.src = this.dst;
this.dst = tmp;
}
};
// shader
var shaderfiles = {};
var shader_grayscott;
var shader_display;
// offscreen resolution scale factor.
var SCREEN_SCALE = 1.0;
// reaction diffusion settings and presets
var rdDef = {
name : 'ReactionDiffusion',
da : 1.0,
db : 0.5,
feed : 0.022,
kill : 0.059,
dt : 1.0,
iter : 10,
reset : initRD,
preset0 : function() { this.feed = 0.040; this.kill = 0.060; this.da = 1.00; this.db = 0.60; },
preset1 : function() { this.feed = 0.034; this.kill = 0.059; this.da = 1.00; this.db = 0.60; },
preset2 : function() { this.feed = 0.080; this.kill = 0.060; this.da = 1.00; this.db = 0.40; },
preset3 : function() { this.feed = 0.015; this.kill = 0.050; this.da = 1.00; this.db = 0.60; },
preset4 : function() { this.feed = 0.072; this.kill = 0.062; this.da = 0.50; this.db = 0.25; },
preset5 : function() { this.feed = 0.071; this.kill = 0.063; this.da = 0.40; this.db = 0.20; },
preset6 : function() { this.feed = 0.023; this.kill = 0.052; this.da = 0.50; this.db = 0.50; },
preset7 : function() { this.feed = 0.029; this.kill = 0.056; this.da = 0.60; this.db = 0.46; },
};
function setup() {
pixelDensity(1);
// webgl canvas
createCanvas(windowWidth, windowHeight, WEBGL);
refImg = createGraphics(windowWidth, windowHeight);
refImg.loadPixels();
for (let i = 0; i < width * height; i ++) {
if ((i / width) % 200 < 100) {
refImg.pixels[i * 4] = 255;
refImg.pixels[i * 4 + 1] = 255;
refImg.pixels[i * 4 + 2] = 255;
} else {
refImg.pixels[i * 4] = 0;
refImg.pixels[i * 4 + 1] = 0;
refImg.pixels[i * 4 + 2] = 0;
}
refImg.pixels[i * 4 + 3] = 255;
}
refImg.updatePixels();
// create gui (dat.gui)
var gui = new dat.GUI();
gui.add(rdDef, 'name');
gui.add(rdDef, 'da' , 0, 1 ).listen();
gui.add(rdDef, 'db' , 0, 1 ).listen();
gui.add(rdDef, 'feed' , 0.01, 0.09).listen();
gui.add(rdDef, 'kill' , 0.01, 0.09).listen();
gui.add(rdDef, 'dt' , 0, 1);
gui.add(rdDef, 'iter' , 1, 50);
gui.add(rdDef, 'preset0');
gui.add(rdDef, 'preset1');
gui.add(rdDef, 'preset2');
gui.add(rdDef, 'preset3');
gui.add(rdDef, 'preset4');
gui.add(rdDef, 'preset5');
gui.add(rdDef, 'preset6');
gui.add(rdDef, 'preset7');
gui.add(rdDef, 'reset' );
// webgl context
var gl = this._renderer.GL;
// webgl version (1=webgl1, 2=webgl2)
var VERSION = gl.getVersion();
console.log("WebGL Version: "+VERSION);
// get some webgl extensions
// if(VERSION === 1){
// var ext = gl.newExt(['OES_texture_float', 'OES_texture_float_linear'], true);
// }
// if(VERSION === 2){
// var ext = gl.newExt(['EXT_color_buffer_float'], true);
// }
// beeing lazy ... load all available extensions.
gl.newExt(gl.getSupportedExtensions(), true);
// create FrameBuffer for offscreen rendering
fbo = gl.newFramebuffer();
// create Textures for multipass rendering
var def = {
target : gl.TEXTURE_2D
,iformat : gl.RGBA32F
,format : gl.RGBA
,type : gl.FLOAT
,wrap : gl.CLAMP_TO_EDGE
,filter : [gl.NEAREST, gl.LINEAR]
}
var tex_w = ceil(width * SCREEN_SCALE);
var tex_h = ceil(height * SCREEN_SCALE);
tex.src = gl.newTexture(tex_w, tex_h, def);
tex.dst = gl.newTexture(tex_w, tex_h, def);
// Shader source, depending on available webgl version
// var fs_grayscott = document.getElementById("webgl"+VERSION+".fs_grayscott").textContent;
// var fs_display = document.getElementById("webgl"+VERSION+".fs_display" ).textContent;
var fs_grayscott = shaderfiles["webgl"+VERSION+".fs_grayscott"];
var fs_display = shaderfiles["webgl"+VERSION+".fs_display"];
// crreate Shader
shader_grayscott = new Shader(gl, {fs:fs_grayscott});
shader_display = new Shader(gl, {fs:fs_display });
// place initial samples
initRD();
}
function windowResized() {
if(!fbo) return;
var w = windowWidth;
var h = windowHeight;
resizeCanvas(w, h);
var tex_w = ceil(w * SCREEN_SCALE);
var tex_h = ceil(h * SCREEN_SCALE);
tex.src.resize(tex_w, tex_h);
tex.dst.resize(tex_w, tex_h);
initRD();
}
// shading colors
// var pallette = [
// 1.00, 1.00, 1.00,
// 0.00, 0.40, 0.80,
// 0.20, 0.00, 0.20,
// 1.00, 0.80, 0.40,
// 0.50, 0.25, 0.12,
// 0.50, 0.50, 0.50,
// 0.00, 0.00, 0.00
// ];
var pallette = [
1.00, 1.00, 1.00,
1.00, 1.00, 1.00,
0.70, 0.70, 0.70,
0.50, 0.50, 0.50,
0.20, 0.20, 0.20,
0.10, 0.10, 0.10,
0.00, 0.00, 0.00
];
function randomizeColors(){
var num = pallette.length /3;
for(var i = 1; i < num-1; i++){
var id = i * 3;
var r = random(1);
var g = random(1);
var b = random(1);
pallette[id + 0] = r;
pallette[id + 1] = g;
pallette[id + 2] = b;
}
}
function keyReleased(){
if(key === 'C'){
randomizeColors();
}
}
function draw(){
if(!fbo) return;
// ortho(0, width, -height, 0, 0, 20000);
push();
ortho();
translate(-width/2, -height/2, 0);
updateRD();
pop();
var w = tex.dst.w / SCREEN_SCALE;
var h = tex.dst.h / SCREEN_SCALE;
// display result
shader_display.viewport(0, 0, w, h);
shader_display.begin();
shader_display.uniformF('PALLETTE', pallette, 7);
shader_display.uniformT('tex', tex.src);
shader_display.uniformF('wh_rcp', [1.0/w, 1.0/h]);
shader_display.quad();
shader_display.end();
}
function initRD(){
ortho();
// translate(-width/2, -height/2, 0);
var gl = fbo.gl;
// bind framebuffer and texture for offscreenrendering
fbo.begin(tex.dst);
var w = tex.dst.w;
var h = tex.dst.h;
gl.viewport(0, 0, w, h);
gl.clearColor(1.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.disable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
// < native p5 here
noStroke();
fill(0,255,0);
ellipse(-100, 0, 100, 100);
ellipse(+100, 0, 100, 100);
ellipse(0, -100, 100, 100);
ellipse(0, +100, 100, 100);
// >
tex.swap();
fbo.end();
}
function updateRD(){
var gl = fbo.gl;
// multipass rendering (ping-pong)
for(var i = 0; i < rdDef.iter; i++){
// set texture as rendertarget
fbo.begin(tex.dst);
var w = tex.dst.w;
var h = tex.dst.h;
// clear texture
gl.viewport(0, 0, w, h);
gl.clearColor(1.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.disable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
// apply shader
let mx = map(mouseX, 0, width, 0, 1);
let my = map(mouseY, 0, height, 0, 1);
shader_grayscott.begin();
shader_grayscott.uniformF("dA" , [rdDef.da]);
shader_grayscott.uniformF("dB" , [rdDef.db]);
// shader_grayscott.uniformF("feed" , [rdDef.feed]);
// shader_grayscott.uniformF("kill" , [rdDef.kill]);
shader_grayscott.uniformF("dt" , [rdDef.dt]);
shader_grayscott.uniformF("wh_rcp", [1.0/w, 1.0/h]);
shader_grayscott.uniformT("tex" , tex.src);
shader_grayscott.uniformT("img" , refImg);
shader_grayscott.uniformT("mouse" , [mx,my]);
shader_grayscott.quad();
shader_grayscott.end();
// < native p5 here
if(mouseIsPressed){
noStroke();
fill(0,255,0);
ellipse(mouseX, mouseY, 20, 20);
}
// >
// ping-pong
tex.swap();
}
// end fbo, so p5 can take over again.
fbo.end();
}
(function () {
var loadJS = function(filename){
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.setAttribute("src", filename);
document.getElementsByTagName("head")[0].appendChild(script);
}
loadJS("https://rawgit.com/diwi/p5.EasyCam/master/dwgl.js");
loadJS("https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.5/dat.gui.min.js");
document.oncontextmenu = function() { return false; }
document.onmousedown = function() { return false; }
})();
See More Shortcuts
Please verify your email to comment
Verify Email