A continuación se muestra la imagen original y los 3 filtros implementados como resultado de una imagen.
A continuación se muestran los resultados obtenidos aplicando las funciones que se explicarán a continuación. Arriba izquierda se muestra la imagen original, arriba derecha se muestra la imagen en negativo, abajo izquierda se muestra aplicando luma, abajo derecha se muestra aplicando el promedio RGB
1linklet img;
2link
3linklet shaderPred;
4linklet shaderNegative;
5linklet shaderLuma;
6linklet shaderRGB;
7link
8linklet imgPred;
9linklet imgNegative;
10linklet imgLuma;
11linklet imgRGB;
12link
13linklet pred = 1;
14linklet negative = 2;
15linklet luma = 3;
16linklet rgb = 4;
17link
18linkfunction preload() {
19link shaderPred = loadShader("/vc/docs/sketches/workshops/imaging/hardware/grayScale/shader.vert", "/vc/docs/sketches/workshops/imaging/hardware/grayScale/grayScale.frag");
20link shaderNegative = loadShader("/vc/docs/sketches/workshops/imaging/hardware/grayScale/shader.vert", "/vc/docs/sketches/workshops/imaging/hardware/grayScale/grayScale.frag");
21link shaderLuma = loadShader("/vc/docs/sketches/workshops/imaging/hardware/grayScale/shader.vert", "/vc/docs/sketches/workshops/imaging/hardware/grayScale/grayScale.frag");
22link shaderRGB = loadShader("/vc/docs/sketches/workshops/imaging/hardware/grayScale/shader.vert", "/vc/docs/sketches/workshops/imaging/hardware/grayScale/grayScale.frag");
23link img = loadImage("/vc/docs/sketches/workshops/imaging/BabyYoda2.jpg", () => img.resize(windowWidth / 2, windowHeight / 2));
24link}
25link
26linkfunction setup() {
27link createCanvas(windowWidth - 15, windowHeight - 21);
28link noLoop();
29link
30link button = createButton('FullScreen');
31link button.attribute('style', 'box-shadow:inset 0px 1px 0px 0px #000000;\n' +
32link '\tborder-radius:6px;\n' +
33link '\tborder:1px solid #000000;\n' +
34link '\tdisplay:inline-block;\n' +
35link '\tcursor:pointer;\n' +
36link '\tcolor:#000000;\n' +
37link '\tfont-family:Arial;\n' +
38link '\tfont-size:15px;\n' +
39link '\tfont-weight:bold;\n' +
40link '\tpadding:6px 24px;\n' +
41link '\ttext-decoration:none;\n');
42link button.position(3, 3);
43link button.mousePressed(fullScreen);
44link
45link imgPred = shaderImage(shaderPred, pred);
46link imgNegative = shaderImage(shaderNegative, negative);
47link imgLuma = shaderImage(shaderLuma, luma);
48link imgRGB = shaderImage(shaderRGB, rgb);
49link}
50link
51linkfunction draw() {
52link
53link image(imgPred, 0, 0, windowWidth / 2, windowHeight / 2);
54link image(imgNegative, windowWidth / 2, 0, windowWidth / 2, windowHeight / 2);
55link image(imgLuma, 0, windowHeight / 2, windowWidth / 2, windowHeight / 2);
56link image(imgRGB, windowWidth / 2, windowHeight / 2, windowWidth / 2, windowHeight / 2);
57link
58link fill(255, 255, 255);
59link textSize(32);
60link text('Emboss', 0, 0);
61link text('Outline', windowWidth / 2, 0);
62link text('Blur', 0, windowHeight / 2);
63link text('Sharpen', windowWidth / 2, windowHeight / 2);
64link
65link console.timeEnd("kernels");
66link}
67link
68linkfunction shaderImage(shader, grayType) {
69link graphic = createGraphics(windowWidth - 15, windowHeight - 21, WEBGL);
70link graphic.textureMode(NORMAL);
71link graphic.shader(shader);
72link shader.setUniform('texture', img);
73link shader.setUniform('verticalOffset', 1 / img.height);
74link shader.setUniform('horizontalOffset', 1 / img.width);
75link shader.setUniform("grayType", grayType);
76link
77link graphic.beginShape();
78link graphic.vertex(-width / 2, -height / 2, 0, 0);
79link graphic.vertex(width / 2, -height / 2, 1, 0);
80link graphic.vertex(width / 2, height / 2, 1, 1);
81link graphic.vertex(-width / 2, height / 2, 0, 1);
82link graphic.endShape(CLOSE);
83link return graphic;
84link}
85link
86linkfunction fullScreen() {
87link let fs = fullscreen();
88link fullscreen(!fs);
89link}
90link
91linkfunction windowResized() {
92link resizeCanvas(windowWidth - 15, windowHeight - 21);
93link}
1linkprecision mediump float;
2linkuniform sampler2D texture;
3linkuniform int grayType;
4link
5linkvarying vec4 vVertexColor;
6link
7linkvec4 textureColor;
8link
9linkfloat luma;
10linkfloat average;
11link
12linkvarying vec2 vTexCoord;
13link
14linkfloat sRGBtoLin(in float colorChannel) {
15link if ( colorChannel <= 0.04045 ) {
16link return colorChannel / 12.92;
17link } else {
18link return pow((( colorChannel + 0.055)/1.055),2.2);
19link }
20link}
21link
22linkfloat gam_sRGB(in float v) {
23link if(v <= 0.0031308){
24link v *= 12.92;
25link } else {
26link v = (1.055 * (pow(v,1.0/2.4))) - 0.055;
27link }
28link return v*255.0;
29link}
30link
31linkfloat lumaFunc(in float r, in float g, in float b) {
32link float rY = 0.212655;
33link float gY = 0.715158;
34link float bY = 0.072187;
35link //Convert all sRGB 8 bit integer values to decimal 0.0-1.0
36link float vR = r / 255.0;
37link float vG = g / 255.0;
38link float vB = b / 255.0;
39link //Convert a gamma encoded RGB to a linear value.
40link float rLin = sRGBtoLin(vR);
41link float gLin = sRGBtoLin(vG);
42link float bLin = sRGBtoLin(vB);
43link //Find Luminance (Y)
44link float Y = ((rY * rLin) + (gY * gLin) + (bY * bLin));
45link //float Y = ((rY) + (gY) + (bY)) * 255.0;
46link return gam_sRGB(Y) ;
47link}
48link
49linkvoid main() {
50link textureColor = texture2D(texture, vTexCoord);
51link if(grayType == 1){}
52link if(grayType == 2){
53link textureColor.r = 1.0-textureColor.r;
54link textureColor.g = 1.0-textureColor.g;
55link textureColor.b = 1.0-textureColor.b;
56link textureColor.a = 1.0;
57link }
58link if(grayType == 3){
59link luma = lumaFunc(textureColor.r, textureColor.g, textureColor.b);
60link textureColor.r = luma;
61link textureColor.g = luma;
62link textureColor.b = luma;
63link textureColor.a = 1.0;
64link }
65link if(grayType == 4){
66link average = (textureColor.r + textureColor.g + textureColor.b) / 3.0;
67link textureColor.r = average;
68link textureColor.g = average;
69link textureColor.b = average;
70link textureColor.a = 1.0;
71link }
72link gl_FragColor = textureColor * vVertexColor;
73link}
Adicionalmente se realizó el mismo procedimiento para video, se muestra a continuación:
Adicionalmente se realizó el mismo procedimiento para video, se muestra a continuación:
1linklet video;
2linklet shaderVideo;
3linklet interfaz;
4link
5linklet pred = 1;
6linklet negative = 2;
7linklet luma = 3;
8linklet rgb = 4;
9link
10linkfunction preload() {
11link shaderVideo = loadShader("/vc/docs/sketches/workshops/imaging/hardware/grayScale/shader.vert", "/vc/docs/sketches/workshops/imaging/hardware/grayScale/grayScale.frag");
12link video = createVideo("/vc/docs/sketches/fingers.webm");
13link}
14link
15linkfunction mousePressed() {
16link video.loop();
17link}
18link
19linkfunction setup() {
20link createCanvas(640, 480, WEBGL);
21link noStroke();
22link video.hide();
23link video.volume(0);
24link
25link cam = createCamera();
26link cam.setPosition(320, 240, (height / 2) / tan(PI / 6));
27link
28link interfaz = createGraphics(640, 480);
29link interfaz.fill(255);
30link interfaz.textSize(25);
31link interfaz.text('Original', 220, 35);
32link interfaz.text('Negative', 230, 275);
33link interfaz.text('Luma', 520, 35);
34link interfaz.text('RGB', 535, 275);
35link
36link stroke(255, 255, 255);
37link strokeWeight(11);
38link line(0, 246, 640, 246);
39link strokeWeight(5);
40link line(320, 0, 320, 480);
41link
42link shader(shaderVideo);
43link shaderVideo.setUniform('texture', video);
44link shaderVideo.setUniform('verticalOffset', 1 / video.height);
45link shaderVideo.setUniform('horizontalOffset', 1 / video.width);
46link}
47link
48linkfunction draw() {
49link filterVideo(pred, 1);
50link filterVideo(negative, 2);
51link filterVideo(luma, 3);
52link filterVideo(rgb, 4);
53link
54link image(interfaz, 0, 0);
55link}
56link
57linkfunction filterVideo(grayType, nVideo) {
58link shaderVideo.setUniform('grayType', grayType);
59link
60link var x0 = (width / 2) * (1 - (nVideo % 2));
61link var x1 = (width / 2) * (2 - (nVideo % 2));
62link var y0 = (height / 2) * (Math.ceil(nVideo / 2) - 1);
63link var y1 = (height / 2) * Math.ceil(nVideo / 2);
64link
65link beginShape();
66link vertex(x0, y0, 0, 0);
67link vertex(x1, y0, 1, 0);
68link vertex(x1, y1, 1, 1);
69link vertex(x0, y1, 0, 1);
70link endShape(CLOSE);
71link}
Nota: Para imagen y para video es usado el mismo fragment shader.
Explicación más detallada en: https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color