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);
}
opengl-es html5-canvas webgl linear-gradients
|
show 4 more comments
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);
}
opengl-es html5-canvas webgl linear-gradients
?? 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 togl_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
|
show 4 more comments
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);
}
opengl-es html5-canvas webgl linear-gradients
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);
}
opengl-es html5-canvas webgl linear-gradients
opengl-es html5-canvas webgl linear-gradients
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 togl_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
|
show 4 more comments
?? 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 togl_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
|
show 4 more comments
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);
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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);
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
add a comment |
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);
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
add a comment |
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);
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);
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
add a comment |
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 API
globalCompositeOperation
(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 API
globalCompositeOperation
(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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
?? 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