let properFrameCount = 0;
"precision mediump float;" +
"attribute vec3 aPosition;" +
" gl_Position = vec4(aPosition, 1.0);" +
"precision mediump float;" +
"uniform float uTexSize;" +
" vec2 p = gl_FragCoord.xy / uTexSize;" +
" vec2 pos = (p - 0.5) * 2.0;" +
" gl_FragColor = vec4(pos, 0.0, 0.0);" +
"precision mediump float;" +
"attribute vec3 aPosition;" +
" gl_Position = vec4(aPosition, 1.0);" +
"precision mediump float;" +
"uniform sampler2D uTex;" +
"uniform vec2 uResolution;" +
" vec2 p = gl_FragCoord.xy / uResolution.xy;" +
" gl_FragColor = texture2D(uTex, p);" +
"precision mediump float;" +
"attribute vec3 aPosition;" +
" gl_Position = vec4(aPosition, 1.0);" +
"precision mediump float;" +
"uniform sampler2D uTex;" +
"uniform float uTexSize;" +
"uniform bool uMouseFlag;" +
"uniform float uAccell;" +
"const float SPEED = 0.05;" +
" vec2 p = gl_FragCoord.xy / uTexSize;" +
" vec4 t = texture2D(uTex, p);" +
" vec2 velocity = t.zw;" +
" vec2 v = normalize(uMouse - pos) * 0.2;" +
" vec2 w = normalize(velocity + v);" +
" vec4 destColor = vec4(pos + w * SPEED * uAccell, w);" +
" if(!uMouseFlag){ destColor.zw = velocity; }" +
" gl_FragColor = destColor;" +
"precision mediump float;" +
"attribute float aIndex;" +
"uniform sampler2D uTex;" +
"uniform vec2 uResolution;" +
"uniform float uTexSize;" +
"uniform float uPointScale;" +
" float x = (mod(aIndex, uTexSize) + 0.5) / uTexSize;" +
" float y = (floor(aIndex / uTexSize) + 0.5) / uTexSize;" +
" vec4 t = texture2D(uTex, vec2(x, y));" +
" p *= vec2(min(uResolution.x, uResolution.y)) / uResolution;" +
" gl_Position = vec4(p, 0.0, 1.0);" +
" gl_PointSize = 0.1 + uPointScale;" +
"precision mediump float;" +
"uniform vec4 uAmbient;" +
" gl_FragColor = uAmbient;" +
createCanvas(windowWidth, windowHeight, WEBGL);
setAttributes("version", 1);
const _gl = this._renderer;
for(let i = 0; i < TEX_SIZE * TEX_SIZE; i++){
_node = new RenderNode();
const dataShader = createShader(dataVert, dataFrag);
_node.registRenderSystem('data', dataShader);
_node.use('data', 'plane');
_node.registAttribute('aPosition', positions, 3);
const bgShader = createShader(bgVert, bgFrag);
_node.registRenderSystem('bg', bgShader);
_node.use('bg', 'plane');
_node.registAttribute('aPosition', positions, 3);
_node.registUniformLocation('uTex');
const moveShader = createShader(moveVert, moveFrag);
_node.registRenderSystem('move', moveShader);
_node.use('move', 'plane');
_node.registAttribute('aPosition', positions, 3);
_node.registUniformLocation('uTex');
const _pointShader = createShader(pointVert, pointFrag);
_node.registRenderSystem('point', _pointShader);
_node.use('point', 'points');
_node.registAttribute('aIndex', indices, 1);
_node.registUniformLocation('uTex');
fb = create_framebuffer(TEX_SIZE, TEX_SIZE, gl.FLOAT);
fb2 = create_framebuffer(TEX_SIZE, TEX_SIZE, gl.FLOAT);
bgTex = new p5.Texture(_gl, bg);
const _size = min(width, height);
const mouse_x = (mouseX / width - 0.5) * 2.0 * width / _size;
const mouse_y = -(mouseY / height - 0.5) *2.0 * height / _size;
const mouse_flag = mouseIsPressed;
moveRendering(mouse_x, mouse_y, mouse_flag);
_node.use('bg', 'plane');
_node.setTexture('uTex', bgTex.glTex, 0);
_node.setUniform("uResolution", [width, height]);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.blendFunc(gl.ONE, gl.ONE);
_node.use('point', 'points');
_node.setTexture('uTex', fb2.t, 0);
const ambient = HSBA_to_RGBA((properFrameCount % 360)/3.6, 100, 80);
_node.setUniform("uTexSize", TEX_SIZE)
.setUniform("uPointScale", accell)
.setUniform("uAmbient", ambient)
.setUniform("uResolution", [width, height]);
gl.drawArrays(gl.POINTS, 0, TEX_SIZE * TEX_SIZE);
if(mouse_flag){ accell = 1.0; }else{ accell *= 0.95; }
bg.text(frameRate().toFixed(3), 20, 20);
function textureFloatCheck(){
const ext = gl.getExtension('OES_texture_float') || gl.getExtension('OES_texture_half_float');
alert('float texture not supported');
function defaultRendering(){
gl.bindFramebuffer(gl.FRAMEBUFFER, fb.f);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
_node.use('data', 'plane');
_node.setUniform('uTexSize', TEX_SIZE);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.viewport(0, 0, width, height);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
function moveRendering(mx, my, mFlag){
gl.bindFramebuffer(gl.FRAMEBUFFER, fb2.f);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
_node.use('move', 'plane');
_node.setTexture('uTex', fb.t, 0);
_node.setUniform("uTexSize", TEX_SIZE)
.setUniform("uAccell", accell)
.setUniform("uMouseFlag", mFlag)
.setUniform("uMouse", [mx, my]);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.viewport(0, 0, width, height);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
function prepareBackground(){
bg = createGraphics(width, height);
base = createGraphics(width, height);
base.textAlign(CENTER, CENTER);
base.textSize(min(width, height)*0.04);
base.text("This is GPGPU TEST.", width * 0.5, height * 0.45);
base.text("Press down the mouse to move", width * 0.5, height * 0.5);
base.text("Release the mouse to stop", width * 0.5, height * 0.55);
function create_framebuffer(w, h, format){
let textureFormat = null;
textureFormat = gl.UNSIGNED_BYTE;
let frameBuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
let depthRenderBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRenderBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRenderBuffer);
let fTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, fTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, textureFormat, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fTexture, 0);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
return {f : frameBuffer, d : depthRenderBuffer, t : fTexture};
function create_vbo(data){
let vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
function set_attribute(attributes){
for(let name of Object.keys(attributes)){
const attr = attributes[name];
gl.bindBuffer(gl.ARRAY_BUFFER, attr.vbo);
gl.enableVertexAttribArray(attr.location);
gl.vertexAttribPointer(attr.location, attr.stride, gl.FLOAT, false, 0, 0);
function HSBA_to_RGBA(h,s,b,a = 1, max_h = 100, max_s = 100, max_b = 100){
let sector = Math.floor(hue);
let tint1 = val * (1 - sat);
let tint2 = val * (1 - sat * (hue - sector));
let tint3 = val * (1 - sat * (1 + sector - hue));
RGB = [tint2, val, tint1]; break;
RGB = [tint1, val, tint3]; break;
RGB = [tint1, tint2, val]; break;
RGB = [tint3, tint1, val]; break;
RGB = [val, tint1, tint2]; break;
RGB = [val, tint3, tint1]; break;
constructor(name, _shader){
this.program = _shader._glProgram;
this.uniformLocations = {};
registTopology(topologyName){
if(this.topologies[topologyName] !== undefined){ return; }
this.topologies[topologyName] = new Topology(topologyName);
getTopology(topologyName){
return this.topologies[topologyName];
registUniformLocation(uniformName){
if(this.uniformLocations[uniformName] !== undefined){ return; }
this.uniformLocations[uniformName] = gl.getUniformLocation(this.program, uniformName);
setTexture(uniformName, _texture, locationID){
gl.activeTexture(gl.TEXTURE0 + locationID);
gl.bindTexture(gl.TEXTURE_2D, _texture);
gl.uniform1i(this.uniformLocations[uniformName], locationID);
this.currentRenderSystem = undefined;
this.currentShader = undefined;
this.currentTopology = undefined;
this.useTextureFlag = false;
registRenderSystem(renderSystemName, _shader){
if(this.renderSystems[renderSystemName] !== undefined){ return; }
this.renderSystems[renderSystemName] = new RenderSystem(renderSystemName, _shader);
use(renderSystemName, topologyName){
if(this.renderSystems[renderSystemName] == undefined){ return; }
this.useRenderSystem(renderSystemName);
this.registTopology(topologyName);
this.useTopology(topologyName);
useRenderSystem(renderSystemName){
this.currentRenderSystem = this.renderSystems[renderSystemName];
this.currentShader = this.currentRenderSystem.getShader();
this.currentShader.useProgram();
registTopology(topologyName){
this.currentRenderSystem.registTopology(topologyName);
useTopology(topologyName){
this.currentTopology = this.currentRenderSystem.getTopology(topologyName);
registAttribute(attributeName, data, stride){
this.currentTopology.registAttribute(this.currentRenderSystem.getProgram(), attributeName, data, stride);
this.currentTopology.setAttribute();
registUniformLocation(uniformName){
this.currentRenderSystem.registUniformLocation(uniformName);
setTexture(uniformName, _texture, locationID){
this.currentRenderSystem.setTexture(uniformName, _texture, locationID);
this.useTextureFlag = true;
setUniform(uniformName, data){
this.currentShader.setUniform(uniformName, data);
this.currentTopology.clear();
gl.bindTexture(gl.TEXTURE_2D, null);
this.useTextureFlag = false;
registAttribute(program, attributeName, data, stride){
attr.vbo = create_vbo(data);
attr.location = gl.getAttribLocation(program, attributeName);
this.attributes[attributeName] = attr;
set_attribute(this.attributes);
gl.bindBuffer(gl.ARRAY_BUFFER, null);