<script id="hist-vs" type="not-js">
attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
uniform vec4 u_colorMult;
void main() {
// based on an id (0, 1, 2, 3 ...) compute the pixel x, y for the source image
vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
// compute corresponding uv center of that pixel
vec2 uv = (pixel + 0.5) / u_resolution;
// get the pixels but 0 out channels we don't want
vec4 color = texture2D(u_texture, uv) * u_colorMult;
// add up all the channels. Since 3 are zeroed out we'll get just one channel
float colorSum = color.r + color.g + color.b + color.a;
// set the position to be over a single pixel in the 256x1 destination texture
gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
gl_PointSize = 1.0;
}
</script>
<script id="hist-fs" type="not-js">
precision mediump float;
void main() {
gl_FragColor = vec4(1);
}
</script>
<script id="max-fs" type="not-js">
precision mediump float;
uniform sampler2D u_texture;
void main() {
vec4 maxColor = vec4(0);
// we know the texture is 256x1 so just go over the whole thing
for (int i = 0; i < 256; ++i) {
// compute centers of pixels
vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
// get max value of pixel
maxColor = max(maxColor, texture2D(u_texture, uv));
}
gl_FragColor = maxColor;
}
</script>
<script id="show-vs" type="not-js">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="show-fs" type="not-js">
precision mediump float;
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;
void main() {
// get the max color constants
vec4 maxColor = texture2D(u_maxTexture, vec2(0));
// compute our current UV position
vec2 uv = gl_FragCoord.xy / u_resolution;
// Get the history for this color
// (note: since u_histTexture is 256x1 uv.y is irrelevant
vec4 hist =...
"use strict";
var canvas = document.createElement("canvas");
canvas.width = 256;
canvas.height = 120;
var m4 = twgl.m4;
var gl = canvas.getContext("webgl");
var ext = gl.getExtension("OES_texture_float");
if (!ext) {
alert("requires OES_texture_float");
}
twgl.createTexture(gl, {
//src: "https://i.imgur.com/9Y3sd8S.png",
src: "https://farm1.staticflickr.com/293/18414763798_cb8ebded43_m_d.jpg",
// required link: https://www.flickr.com/photos/greggman/18414763798/in/album-72157653822314919/
min: gl.NEAREST,
mag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
crossOrigin: "",
}, function(err, tex, img) {
log("img");
document.body.appendChild(img);
log("histogram");
document.body.appendChild(canvas);
var quadBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl);
var histProgramInfo = twgl.createProgramInfo(gl, ["hist-vs", "hist-fs"]);
var pixelIds = [];
var numIds = img.width * img.height;
// Just fill a buffer with an incrementing count. If we wanted to make this
// generic we'd re-use this buffer and just make it bigger if we were
// processing a bigger image
for (var i = 0; i < numIds; ++i) {
pixelIds.push(i);
}
var pixelIdBufferInfo = twgl.createBufferInfoFromArrays(gl, {
pixelId: { size: 1, data: new Float32Array(pixelIds), },
});
// make a 256x1 RGBA floating point texture and attach to a framebuffer
var sumFbi = twgl.createFramebufferInfo(gl, [
{ type: gl.FLOAT,
min: gl.NEAREST,
mag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
},
], 256, 1);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
alert("can't render to floating point texture");
}
// Render sum of each color
// we're going to render a gl.POINT for each pixel in the source image
// That point will be positioned based on the color of the source image
// we're just going to render vec4(1,1,1,1). This blend function will
// mean each time we render to a specific point that point will...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.