How to sort pixels and implement linearGradient in webgl histogram?











up vote
0
down vote

favorite












I was trying to implement a histogram for a image using webgl.
I am able to do it in javascript HTML5 Canvas by taking a array of 255 length and increasing pixel values of each index through out 0-255 and using createLinearGradient to create a histogram.



for(var c = 0; c < 256; c++){
histogram[c] = 0;
}
var ctx = document.getElementById('canvas').getContext('2d');
var pixels= ctx.getImageData(0, 0, width, height).data;
for (var i = 0, j = 0; i < u8a.length; i++, j = j + 4) {
histogram[pixels[j]]++; //increasing pixel index for histogram
}


And for implementing the same in WebGL, I am referring this jsfiddle but what I see is the histogram is not smooth and not sorted.



So, I am stuck with 2 things here with WebGL:



-How can we sort the pixel values from 0.0(0) to 1.0(255) in the above mentioned fiddle?



-How to make the histogram smooth in webgl with/without linear gradient?



Code :



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 = texture2D(u_histTexture, uv);
// scale by maxColor so scaled goes from 0 to 1 with 1 = maxColor
vec4 scaled = hist / maxColor;
// 1 > maxColor, 0 otherwise
vec4 color = step(uv.yyyy, scaled);
float rr = 0.2989 * color.r + 0.5870 * color.g + 0.1140 * color.b;
gl_FragColor = vec4(rr, rr, rr, 1);
}


Histogram ranging from 0 to 255 or 0 to 65536 if image is 16 bit










share|improve this question
























  • ?? Sort a histogram!, not really a histogram if it is sorted. Anyway your question is very unclear, what do you mean by smooth and sort? can you provide an image of what you want, including unsorted and sorted histograms as it is hard to guess what you mean?
    – Blindman67
    Nov 20 at 13:46










  • from sorting what I mean is it should render from 0.0 to 1.0 from darkest to lightest (black to white) in grayscale format. I will shortly add the expected image
    – subhfyu546754
    Nov 20 at 13:58












  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result
    – subhfyu546754
    Nov 20 at 14:02












  • To create gradient change last line to gl_FragColor = vec4(rr, rr, rr, 1.0) * vec4(uv.xxx,1.0); it will multiply the color by the x position (0-1) As for sort, that is still unclear as to what you mean.
    – Blindman67
    Nov 20 at 14:37












  • ok I tried your change and it looks good .Thanks . For the sorting thing, please check the image I added, it starts from darker shades and goes to lighter shades . Hope that's clear.
    – subhfyu546754
    Nov 20 at 14:44















up vote
0
down vote

favorite












I was trying to implement a histogram for a image using webgl.
I am able to do it in javascript HTML5 Canvas by taking a array of 255 length and increasing pixel values of each index through out 0-255 and using createLinearGradient to create a histogram.



for(var c = 0; c < 256; c++){
histogram[c] = 0;
}
var ctx = document.getElementById('canvas').getContext('2d');
var pixels= ctx.getImageData(0, 0, width, height).data;
for (var i = 0, j = 0; i < u8a.length; i++, j = j + 4) {
histogram[pixels[j]]++; //increasing pixel index for histogram
}


And for implementing the same in WebGL, I am referring this jsfiddle but what I see is the histogram is not smooth and not sorted.



So, I am stuck with 2 things here with WebGL:



-How can we sort the pixel values from 0.0(0) to 1.0(255) in the above mentioned fiddle?



-How to make the histogram smooth in webgl with/without linear gradient?



Code :



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 = texture2D(u_histTexture, uv);
// scale by maxColor so scaled goes from 0 to 1 with 1 = maxColor
vec4 scaled = hist / maxColor;
// 1 > maxColor, 0 otherwise
vec4 color = step(uv.yyyy, scaled);
float rr = 0.2989 * color.r + 0.5870 * color.g + 0.1140 * color.b;
gl_FragColor = vec4(rr, rr, rr, 1);
}


Histogram ranging from 0 to 255 or 0 to 65536 if image is 16 bit










share|improve this question
























  • ?? Sort a histogram!, not really a histogram if it is sorted. Anyway your question is very unclear, what do you mean by smooth and sort? can you provide an image of what you want, including unsorted and sorted histograms as it is hard to guess what you mean?
    – Blindman67
    Nov 20 at 13:46










  • from sorting what I mean is it should render from 0.0 to 1.0 from darkest to lightest (black to white) in grayscale format. I will shortly add the expected image
    – subhfyu546754
    Nov 20 at 13:58












  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result
    – subhfyu546754
    Nov 20 at 14:02












  • To create gradient change last line to gl_FragColor = vec4(rr, rr, rr, 1.0) * vec4(uv.xxx,1.0); it will multiply the color by the x position (0-1) As for sort, that is still unclear as to what you mean.
    – Blindman67
    Nov 20 at 14:37












  • ok I tried your change and it looks good .Thanks . For the sorting thing, please check the image I added, it starts from darker shades and goes to lighter shades . Hope that's clear.
    – subhfyu546754
    Nov 20 at 14:44













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I was trying to implement a histogram for a image using webgl.
I am able to do it in javascript HTML5 Canvas by taking a array of 255 length and increasing pixel values of each index through out 0-255 and using createLinearGradient to create a histogram.



for(var c = 0; c < 256; c++){
histogram[c] = 0;
}
var ctx = document.getElementById('canvas').getContext('2d');
var pixels= ctx.getImageData(0, 0, width, height).data;
for (var i = 0, j = 0; i < u8a.length; i++, j = j + 4) {
histogram[pixels[j]]++; //increasing pixel index for histogram
}


And for implementing the same in WebGL, I am referring this jsfiddle but what I see is the histogram is not smooth and not sorted.



So, I am stuck with 2 things here with WebGL:



-How can we sort the pixel values from 0.0(0) to 1.0(255) in the above mentioned fiddle?



-How to make the histogram smooth in webgl with/without linear gradient?



Code :



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 = texture2D(u_histTexture, uv);
// scale by maxColor so scaled goes from 0 to 1 with 1 = maxColor
vec4 scaled = hist / maxColor;
// 1 > maxColor, 0 otherwise
vec4 color = step(uv.yyyy, scaled);
float rr = 0.2989 * color.r + 0.5870 * color.g + 0.1140 * color.b;
gl_FragColor = vec4(rr, rr, rr, 1);
}


Histogram ranging from 0 to 255 or 0 to 65536 if image is 16 bit










share|improve this question















I was trying to implement a histogram for a image using webgl.
I am able to do it in javascript HTML5 Canvas by taking a array of 255 length and increasing pixel values of each index through out 0-255 and using createLinearGradient to create a histogram.



for(var c = 0; c < 256; c++){
histogram[c] = 0;
}
var ctx = document.getElementById('canvas').getContext('2d');
var pixels= ctx.getImageData(0, 0, width, height).data;
for (var i = 0, j = 0; i < u8a.length; i++, j = j + 4) {
histogram[pixels[j]]++; //increasing pixel index for histogram
}


And for implementing the same in WebGL, I am referring this jsfiddle but what I see is the histogram is not smooth and not sorted.



So, I am stuck with 2 things here with WebGL:



-How can we sort the pixel values from 0.0(0) to 1.0(255) in the above mentioned fiddle?



-How to make the histogram smooth in webgl with/without linear gradient?



Code :



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 = texture2D(u_histTexture, uv);
// scale by maxColor so scaled goes from 0 to 1 with 1 = maxColor
vec4 scaled = hist / maxColor;
// 1 > maxColor, 0 otherwise
vec4 color = step(uv.yyyy, scaled);
float rr = 0.2989 * color.r + 0.5870 * color.g + 0.1140 * color.b;
gl_FragColor = vec4(rr, rr, rr, 1);
}


Histogram ranging from 0 to 255 or 0 to 65536 if image is 16 bit







opengl-es html5-canvas webgl linear-gradients






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 14:01

























asked Nov 20 at 12:42









subhfyu546754

3551427




3551427












  • ?? Sort a histogram!, not really a histogram if it is sorted. Anyway your question is very unclear, what do you mean by smooth and sort? can you provide an image of what you want, including unsorted and sorted histograms as it is hard to guess what you mean?
    – Blindman67
    Nov 20 at 13:46










  • from sorting what I mean is it should render from 0.0 to 1.0 from darkest to lightest (black to white) in grayscale format. I will shortly add the expected image
    – subhfyu546754
    Nov 20 at 13:58












  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result
    – subhfyu546754
    Nov 20 at 14:02












  • To create gradient change last line to gl_FragColor = vec4(rr, rr, rr, 1.0) * vec4(uv.xxx,1.0); it will multiply the color by the x position (0-1) As for sort, that is still unclear as to what you mean.
    – Blindman67
    Nov 20 at 14:37












  • ok I tried your change and it looks good .Thanks . For the sorting thing, please check the image I added, it starts from darker shades and goes to lighter shades . Hope that's clear.
    – subhfyu546754
    Nov 20 at 14:44


















  • ?? Sort a histogram!, not really a histogram if it is sorted. Anyway your question is very unclear, what do you mean by smooth and sort? can you provide an image of what you want, including unsorted and sorted histograms as it is hard to guess what you mean?
    – Blindman67
    Nov 20 at 13:46










  • from sorting what I mean is it should render from 0.0 to 1.0 from darkest to lightest (black to white) in grayscale format. I will shortly add the expected image
    – subhfyu546754
    Nov 20 at 13:58












  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result
    – subhfyu546754
    Nov 20 at 14:02












  • To create gradient change last line to gl_FragColor = vec4(rr, rr, rr, 1.0) * vec4(uv.xxx,1.0); it will multiply the color by the x position (0-1) As for sort, that is still unclear as to what you mean.
    – Blindman67
    Nov 20 at 14:37












  • ok I tried your change and it looks good .Thanks . For the sorting thing, please check the image I added, it starts from darker shades and goes to lighter shades . Hope that's clear.
    – subhfyu546754
    Nov 20 at 14:44
















?? Sort a histogram!, not really a histogram if it is sorted. Anyway your question is very unclear, what do you mean by smooth and sort? can you provide an image of what you want, including unsorted and sorted histograms as it is hard to guess what you mean?
– Blindman67
Nov 20 at 13:46




?? Sort a histogram!, not really a histogram if it is sorted. Anyway your question is very unclear, what do you mean by smooth and sort? can you provide an image of what you want, including unsorted and sorted histograms as it is hard to guess what you mean?
– Blindman67
Nov 20 at 13:46












from sorting what I mean is it should render from 0.0 to 1.0 from darkest to lightest (black to white) in grayscale format. I will shortly add the expected image
– subhfyu546754
Nov 20 at 13:58






from sorting what I mean is it should render from 0.0 to 1.0 from darkest to lightest (black to white) in grayscale format. I will shortly add the expected image
– subhfyu546754
Nov 20 at 13:58














added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result
– subhfyu546754
Nov 20 at 14:02






added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result
– subhfyu546754
Nov 20 at 14:02














To create gradient change last line to gl_FragColor = vec4(rr, rr, rr, 1.0) * vec4(uv.xxx,1.0); it will multiply the color by the x position (0-1) As for sort, that is still unclear as to what you mean.
– Blindman67
Nov 20 at 14:37






To create gradient change last line to gl_FragColor = vec4(rr, rr, rr, 1.0) * vec4(uv.xxx,1.0); it will multiply the color by the x position (0-1) As for sort, that is still unclear as to what you mean.
– Blindman67
Nov 20 at 14:37














ok I tried your change and it looks good .Thanks . For the sorting thing, please check the image I added, it starts from darker shades and goes to lighter shades . Hope that's clear.
– subhfyu546754
Nov 20 at 14:44




ok I tried your change and it looks good .Thanks . For the sorting thing, please check the image I added, it starts from darker shades and goes to lighter shades . Hope that's clear.
– subhfyu546754
Nov 20 at 14:44












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










Best i can work out is that you dont want to sort, but rather you want to do a black and white histogram (all channels r,g,b combined).



To do that you need just one pass that sums all channels rather than 4 passes as it currently does.



You need to make changes to the following shaders and replace a some render calls in javascript.



Change "hist-vs" to



attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
void main() {
vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
vec2 uv = (pixel + 0.5) / u_resolution;
vec4 color = texture2D(u_texture, uv);
float colorSum = (color.r + color.g + color.b) / 3.0 ;
gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
gl_PointSize = 1.0;
}


Change "max-vs" to



precision mediump float;
uniform sampler2D u_texture;
void main() {
vec4 maxColor = vec4(0);
for (int i = 0; i < 256; i++) {
vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
maxColor = max(maxColor, vec4(texture2D(u_texture, uv).rgb, 1));
}
gl_FragColor = maxColor;
}


Change "show-fs" to



precision mediump float;    
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;
void main() {
vec3 maxColor = texture2D(u_maxTexture, vec2(0)).rgb;
vec2 uv = gl_FragCoord.xy / u_resolution;
vec3 hist = texture2D(u_histTexture, uv).rgb;
gl_FragColor = vec4(step(uv.yyy, hist / maxColor) * uv.x, 1);
}


Changes to javascript



Then in Javascript rather than call the first shader 4 times you need only call it once. Also as the mask uniform is not needed you dont need to pass that to the shader.



The for loop that originally looked like



  for (var channel = 0; channel < 4; ++channel) {
gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
twgl.setUniforms(histProgramInfo, {
u_texture: tex,
u_colorMult: [
channel === 0 ? 1 : 0,
channel === 1 ? 1 : 0,
channel === 2 ? 1 : 0,
channel === 3 ? 1 : 0,
],
u_resolution: [img.width, img.height],
});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
}


replace all those lines with



gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, { u_texture: tex, u_resolution: [img.width, img.height]});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);





share|improve this answer





















  • This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
    – subhfyu546754
    Nov 22 at 4:38










  • @subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
    – Blindman67
    Nov 22 at 15:05










  • yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
    – subhfyu546754
    Nov 22 at 15:24






  • 1




    @subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
    – Blindman67
    Nov 22 at 16:21










  • Ok I will try that. Thanks for the idea. Am accepting this as a answer
    – subhfyu546754
    Nov 26 at 4:23











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53393244%2fhow-to-sort-pixels-and-implement-lineargradient-in-webgl-histogram%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










Best i can work out is that you dont want to sort, but rather you want to do a black and white histogram (all channels r,g,b combined).



To do that you need just one pass that sums all channels rather than 4 passes as it currently does.



You need to make changes to the following shaders and replace a some render calls in javascript.



Change "hist-vs" to



attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
void main() {
vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
vec2 uv = (pixel + 0.5) / u_resolution;
vec4 color = texture2D(u_texture, uv);
float colorSum = (color.r + color.g + color.b) / 3.0 ;
gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
gl_PointSize = 1.0;
}


Change "max-vs" to



precision mediump float;
uniform sampler2D u_texture;
void main() {
vec4 maxColor = vec4(0);
for (int i = 0; i < 256; i++) {
vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
maxColor = max(maxColor, vec4(texture2D(u_texture, uv).rgb, 1));
}
gl_FragColor = maxColor;
}


Change "show-fs" to



precision mediump float;    
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;
void main() {
vec3 maxColor = texture2D(u_maxTexture, vec2(0)).rgb;
vec2 uv = gl_FragCoord.xy / u_resolution;
vec3 hist = texture2D(u_histTexture, uv).rgb;
gl_FragColor = vec4(step(uv.yyy, hist / maxColor) * uv.x, 1);
}


Changes to javascript



Then in Javascript rather than call the first shader 4 times you need only call it once. Also as the mask uniform is not needed you dont need to pass that to the shader.



The for loop that originally looked like



  for (var channel = 0; channel < 4; ++channel) {
gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
twgl.setUniforms(histProgramInfo, {
u_texture: tex,
u_colorMult: [
channel === 0 ? 1 : 0,
channel === 1 ? 1 : 0,
channel === 2 ? 1 : 0,
channel === 3 ? 1 : 0,
],
u_resolution: [img.width, img.height],
});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
}


replace all those lines with



gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, { u_texture: tex, u_resolution: [img.width, img.height]});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);





share|improve this answer





















  • This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
    – subhfyu546754
    Nov 22 at 4:38










  • @subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
    – Blindman67
    Nov 22 at 15:05










  • yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
    – subhfyu546754
    Nov 22 at 15:24






  • 1




    @subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
    – Blindman67
    Nov 22 at 16:21










  • Ok I will try that. Thanks for the idea. Am accepting this as a answer
    – subhfyu546754
    Nov 26 at 4:23















up vote
1
down vote



accepted










Best i can work out is that you dont want to sort, but rather you want to do a black and white histogram (all channels r,g,b combined).



To do that you need just one pass that sums all channels rather than 4 passes as it currently does.



You need to make changes to the following shaders and replace a some render calls in javascript.



Change "hist-vs" to



attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
void main() {
vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
vec2 uv = (pixel + 0.5) / u_resolution;
vec4 color = texture2D(u_texture, uv);
float colorSum = (color.r + color.g + color.b) / 3.0 ;
gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
gl_PointSize = 1.0;
}


Change "max-vs" to



precision mediump float;
uniform sampler2D u_texture;
void main() {
vec4 maxColor = vec4(0);
for (int i = 0; i < 256; i++) {
vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
maxColor = max(maxColor, vec4(texture2D(u_texture, uv).rgb, 1));
}
gl_FragColor = maxColor;
}


Change "show-fs" to



precision mediump float;    
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;
void main() {
vec3 maxColor = texture2D(u_maxTexture, vec2(0)).rgb;
vec2 uv = gl_FragCoord.xy / u_resolution;
vec3 hist = texture2D(u_histTexture, uv).rgb;
gl_FragColor = vec4(step(uv.yyy, hist / maxColor) * uv.x, 1);
}


Changes to javascript



Then in Javascript rather than call the first shader 4 times you need only call it once. Also as the mask uniform is not needed you dont need to pass that to the shader.



The for loop that originally looked like



  for (var channel = 0; channel < 4; ++channel) {
gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
twgl.setUniforms(histProgramInfo, {
u_texture: tex,
u_colorMult: [
channel === 0 ? 1 : 0,
channel === 1 ? 1 : 0,
channel === 2 ? 1 : 0,
channel === 3 ? 1 : 0,
],
u_resolution: [img.width, img.height],
});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
}


replace all those lines with



gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, { u_texture: tex, u_resolution: [img.width, img.height]});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);





share|improve this answer





















  • This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
    – subhfyu546754
    Nov 22 at 4:38










  • @subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
    – Blindman67
    Nov 22 at 15:05










  • yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
    – subhfyu546754
    Nov 22 at 15:24






  • 1




    @subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
    – Blindman67
    Nov 22 at 16:21










  • Ok I will try that. Thanks for the idea. Am accepting this as a answer
    – subhfyu546754
    Nov 26 at 4:23













up vote
1
down vote



accepted







up vote
1
down vote



accepted






Best i can work out is that you dont want to sort, but rather you want to do a black and white histogram (all channels r,g,b combined).



To do that you need just one pass that sums all channels rather than 4 passes as it currently does.



You need to make changes to the following shaders and replace a some render calls in javascript.



Change "hist-vs" to



attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
void main() {
vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
vec2 uv = (pixel + 0.5) / u_resolution;
vec4 color = texture2D(u_texture, uv);
float colorSum = (color.r + color.g + color.b) / 3.0 ;
gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
gl_PointSize = 1.0;
}


Change "max-vs" to



precision mediump float;
uniform sampler2D u_texture;
void main() {
vec4 maxColor = vec4(0);
for (int i = 0; i < 256; i++) {
vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
maxColor = max(maxColor, vec4(texture2D(u_texture, uv).rgb, 1));
}
gl_FragColor = maxColor;
}


Change "show-fs" to



precision mediump float;    
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;
void main() {
vec3 maxColor = texture2D(u_maxTexture, vec2(0)).rgb;
vec2 uv = gl_FragCoord.xy / u_resolution;
vec3 hist = texture2D(u_histTexture, uv).rgb;
gl_FragColor = vec4(step(uv.yyy, hist / maxColor) * uv.x, 1);
}


Changes to javascript



Then in Javascript rather than call the first shader 4 times you need only call it once. Also as the mask uniform is not needed you dont need to pass that to the shader.



The for loop that originally looked like



  for (var channel = 0; channel < 4; ++channel) {
gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
twgl.setUniforms(histProgramInfo, {
u_texture: tex,
u_colorMult: [
channel === 0 ? 1 : 0,
channel === 1 ? 1 : 0,
channel === 2 ? 1 : 0,
channel === 3 ? 1 : 0,
],
u_resolution: [img.width, img.height],
});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
}


replace all those lines with



gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, { u_texture: tex, u_resolution: [img.width, img.height]});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);





share|improve this answer












Best i can work out is that you dont want to sort, but rather you want to do a black and white histogram (all channels r,g,b combined).



To do that you need just one pass that sums all channels rather than 4 passes as it currently does.



You need to make changes to the following shaders and replace a some render calls in javascript.



Change "hist-vs" to



attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
void main() {
vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
vec2 uv = (pixel + 0.5) / u_resolution;
vec4 color = texture2D(u_texture, uv);
float colorSum = (color.r + color.g + color.b) / 3.0 ;
gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
gl_PointSize = 1.0;
}


Change "max-vs" to



precision mediump float;
uniform sampler2D u_texture;
void main() {
vec4 maxColor = vec4(0);
for (int i = 0; i < 256; i++) {
vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
maxColor = max(maxColor, vec4(texture2D(u_texture, uv).rgb, 1));
}
gl_FragColor = maxColor;
}


Change "show-fs" to



precision mediump float;    
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;
void main() {
vec3 maxColor = texture2D(u_maxTexture, vec2(0)).rgb;
vec2 uv = gl_FragCoord.xy / u_resolution;
vec3 hist = texture2D(u_histTexture, uv).rgb;
gl_FragColor = vec4(step(uv.yyy, hist / maxColor) * uv.x, 1);
}


Changes to javascript



Then in Javascript rather than call the first shader 4 times you need only call it once. Also as the mask uniform is not needed you dont need to pass that to the shader.



The for loop that originally looked like



  for (var channel = 0; channel < 4; ++channel) {
gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
twgl.setUniforms(histProgramInfo, {
u_texture: tex,
u_colorMult: [
channel === 0 ? 1 : 0,
channel === 1 ? 1 : 0,
channel === 2 ? 1 : 0,
channel === 3 ? 1 : 0,
],
u_resolution: [img.width, img.height],
});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
}


replace all those lines with



gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, { u_texture: tex, u_resolution: [img.width, img.height]});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 14:05









Blindman67

26.2k52659




26.2k52659












  • This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
    – subhfyu546754
    Nov 22 at 4:38










  • @subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
    – Blindman67
    Nov 22 at 15:05










  • yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
    – subhfyu546754
    Nov 22 at 15:24






  • 1




    @subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
    – Blindman67
    Nov 22 at 16:21










  • Ok I will try that. Thanks for the idea. Am accepting this as a answer
    – subhfyu546754
    Nov 26 at 4:23


















  • This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
    – subhfyu546754
    Nov 22 at 4:38










  • @subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
    – Blindman67
    Nov 22 at 15:05










  • yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
    – subhfyu546754
    Nov 22 at 15:24






  • 1




    @subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
    – Blindman67
    Nov 22 at 16:21










  • Ok I will try that. Thanks for the idea. Am accepting this as a answer
    – subhfyu546754
    Nov 26 at 4:23
















This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
– subhfyu546754
Nov 22 at 4:38




This solution works as expected but it does not create a linear gradient as per the image I attached(see the black line covering the histogram from top). So, does that mean that OpenGL cannot render a linearGradient like what we achieve from a HTML5 Canvas createLinearGradient?
– subhfyu546754
Nov 22 at 4:38












@subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
– Blindman67
Nov 22 at 15:05




@subhfyu546754 You need to use the correct terminology. The black line is a stroke, and has nothing to do with a gradient.
– Blindman67
Nov 22 at 15:05












yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
– subhfyu546754
Nov 22 at 15:24




yes it's a stroke I didn't notice. But how do we achieve it in webgl in this scenario . I can see many examples online , but can you give some idea on how to implement stroke in this case
– subhfyu546754
Nov 22 at 15:24




1




1




@subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
– Blindman67
Nov 22 at 16:21




@subhfyu546754 The fiddle provided is not conducive to adding an outline and the stroke you show extends outside the webGl canvas. You can easily use 2D APIglobalCompositeOperation (gCO) and the webGL rendered image as a mask to draw an outline but you will need to modify the WebGL output to include transparent pixels. Then create a new canvas that is one pixel bigger on all sides, draw the mask 1 pixel up,down,left and right, set gCO to "source-atop", draw a black rect over the canvas, set gCO to "source-over" and draw the mask at the center.
– Blindman67
Nov 22 at 16:21












Ok I will try that. Thanks for the idea. Am accepting this as a answer
– subhfyu546754
Nov 26 at 4:23




Ok I will try that. Thanks for the idea. Am accepting this as a answer
– subhfyu546754
Nov 26 at 4:23


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53393244%2fhow-to-sort-pixels-and-implement-lineargradient-in-webgl-histogram%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen