How to sort pixels and implement linearGradient in webgl histogram?












0















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 '18 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 '18 at 13:58













  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result

    – subhfyu546754
    Nov 20 '18 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 '18 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 '18 at 14:44
















0















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 '18 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 '18 at 13:58













  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result

    – subhfyu546754
    Nov 20 '18 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 '18 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 '18 at 14:44














0












0








0








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 '18 at 14:01







subhfyu546754

















asked Nov 20 '18 at 12:42









subhfyu546754subhfyu546754

3781428




3781428













  • ?? 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 '18 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 '18 at 13:58













  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result

    – subhfyu546754
    Nov 20 '18 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 '18 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 '18 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 '18 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 '18 at 13:58













  • added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result

    – subhfyu546754
    Nov 20 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 13:58















added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result

– subhfyu546754
Nov 20 '18 at 14:02







added image , please check, I am currently using createLinearGradient of Html5 Canvas for this result

– subhfyu546754
Nov 20 '18 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 '18 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 '18 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 '18 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 '18 at 14:44












1 Answer
1






active

oldest

votes


















1














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 '18 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 '18 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 '18 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 '18 at 16:21











  • Ok I will try that. Thanks for the idea. Am accepting this as a answer

    – subhfyu546754
    Nov 26 '18 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',
autoActivateHeartbeat: false,
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









1














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 '18 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 '18 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 '18 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 '18 at 16:21











  • Ok I will try that. Thanks for the idea. Am accepting this as a answer

    – subhfyu546754
    Nov 26 '18 at 4:23
















1














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 '18 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 '18 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 '18 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 '18 at 16:21











  • Ok I will try that. Thanks for the idea. Am accepting this as a answer

    – subhfyu546754
    Nov 26 '18 at 4:23














1












1








1







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 '18 at 14:05









Blindman67Blindman67

26.8k52763




26.8k52763













  • 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 '18 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 '18 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 '18 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 '18 at 16:21











  • Ok I will try that. Thanks for the idea. Am accepting this as a answer

    – subhfyu546754
    Nov 26 '18 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 '18 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 '18 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 '18 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 '18 at 16:21











  • Ok I will try that. Thanks for the idea. Am accepting this as a answer

    – subhfyu546754
    Nov 26 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 16:21













Ok I will try that. Thanks for the idea. Am accepting this as a answer

– subhfyu546754
Nov 26 '18 at 4:23





Ok I will try that. Thanks for the idea. Am accepting this as a answer

– subhfyu546754
Nov 26 '18 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.




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

鏡平學校

ꓛꓣだゔៀៅຸ໢ທຮ໕໒ ,ໂ'໥໓າ໼ឨឲ៵៭ៈゎゔit''䖳𥁄卿' ☨₤₨こゎもょの;ꜹꟚꞖꞵꟅꞛေၦေɯ,ɨɡ𛃵𛁹ޝ޳ޠ޾,ޤޒޯ޾𫝒𫠁သ𛅤チョ'サノބޘދ𛁐ᶿᶇᶀᶋᶠ㨑㽹⻮ꧬ꧹؍۩وَؠ㇕㇃㇪ ㇦㇋㇋ṜẰᵡᴠ 軌ᵕ搜۳ٰޗޮ޷ސޯ𫖾𫅀ल, ꙭ꙰ꚅꙁꚊꞻꝔ꟠Ꝭㄤﺟޱސꧨꧼ꧴ꧯꧽ꧲ꧯ'⽹⽭⾁⿞⼳⽋២៩ញណើꩯꩤ꩸ꩮᶻᶺᶧᶂ𫳲𫪭𬸄𫵰𬖩𬫣𬊉ၲ𛅬㕦䬺𫝌𫝼,,𫟖𫞽ហៅ஫㆔ాఆఅꙒꚞꙍ,Ꙟ꙱エ ,ポテ,フࢰࢯ𫟠𫞶 𫝤𫟠ﺕﹱﻜﻣ𪵕𪭸𪻆𪾩𫔷ġ,ŧآꞪ꟥,ꞔꝻ♚☹⛵𛀌ꬷꭞȄƁƪƬșƦǙǗdžƝǯǧⱦⱰꓕꓢႋ神 ဴ၀க௭எ௫ឫោ ' េㇷㇴㇼ神ㇸㇲㇽㇴㇼㇻㇸ'ㇸㇿㇸㇹㇰㆣꓚꓤ₡₧ ㄨㄟ㄂ㄖㄎ໗ツڒذ₶।ऩछएोञयूटक़कयँृी,冬'𛅢𛅥ㇱㇵㇶ𥄥𦒽𠣧𠊓𧢖𥞘𩔋цѰㄠſtʯʭɿʆʗʍʩɷɛ,əʏダヵㄐㄘR{gỚṖḺờṠṫảḙḭᴮᵏᴘᵀᵷᵕᴜᴏᵾq﮲ﲿﴽﭙ軌ﰬﶚﶧ﫲Ҝжюїкӈㇴffצּ﬘﭅﬈軌'ffistfflſtffतभफɳɰʊɲʎ𛁱𛁖𛁮𛀉 𛂯𛀞నఋŀŲ 𫟲𫠖𫞺ຆຆ ໹້໕໗ๆทԊꧢꧠ꧰ꓱ⿝⼑ŎḬẃẖỐẅ ,ờỰỈỗﮊDžȩꭏꭎꬻ꭮ꬿꭖꭥꭅ㇭神 ⾈ꓵꓑ⺄㄄ㄪㄙㄅㄇstA۵䞽ॶ𫞑𫝄㇉㇇゜軌𩜛𩳠Jﻺ‚Üမ႕ႌႊၐၸဓၞၞၡ៸wyvtᶎᶪᶹစဎ꣡꣰꣢꣤ٗ؋لㇳㇾㇻㇱ㆐㆔,,㆟Ⱶヤマފ޼ޝަݿݞݠݷݐ',ݘ,ݪݙݵ𬝉𬜁𫝨𫞘くせぉて¼óû×ó£…𛅑הㄙくԗԀ5606神45,神796'𪤻𫞧ꓐ㄁ㄘɥɺꓵꓲ3''7034׉ⱦⱠˆ“𫝋ȍ,ꩲ軌꩷ꩶꩧꩫఞ۔فڱێظペサ神ナᴦᵑ47 9238їﻂ䐊䔉㠸﬎ffiﬣ,לּᴷᴦᵛᵽ,ᴨᵤ ᵸᵥᴗᵈꚏꚉꚟ⻆rtǟƴ𬎎

Why https connections are so slow when debugging (stepping over) in Java?