Skip to content

Commit d4b8dba

Browse files
author
B Wu
committed
style: move glsl code to their own files
1 parent 9371aca commit d4b8dba

19 files changed

+623
-404
lines changed

index.d.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
declare module '*.glsl' {
2+
const value: string;
3+
export default value;
4+
}
5+
6+
declare module '*.template' {
7+
const value: string;
8+
export default value;
9+
}
10+

src/components/common/utils.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Escape all regex characters in a string
3+
* https://stackoverflow.com/a/6318742
4+
* @param str the string to escape the characters in
5+
* @returns a string with all regex characters escaped
6+
*/
7+
export const quotemeta = (str: string) => {
8+
// these escapes are fully necessary
9+
// eslint-disable-next-line no-useless-escape
10+
return str.replace(/([\.\\\+\*\?\[\^\]\$\(\)])/g, '\\$1');
11+
};
12+
13+
/**
14+
* Replace {{ template strings }} in a string with values in a mapping
15+
* @param stringTemplate the string whose substrings in {{ this_form }} are getting replaced
16+
* @param expressions a map (or string indexed object) whose keys are {{ substrings }} getting replaced by values
17+
* @returns the interpolated stringTemplate
18+
*/
19+
export const interpolateStringTemplate = (stringTemplate: string, expressions: Record<string, string> | Map<string, string>): string => {
20+
const expressionsArray: Array<[string, string]> = typeof expressions.entries === 'function'
21+
? Array.from (expressions.entries())
22+
: Object.entries(expressions);
23+
24+
return expressionsArray.reduce((stringTemplateAccumulator, [ key, replacement ]) => {
25+
const regexp = new RegExp(String.raw`{{ ${quotemeta(key)} }}`, 'g');
26+
const replacedString = stringTemplateAccumulator.replace(regexp, replacement);
27+
return replacedString;
28+
}, stringTemplate);
29+
};
30+

src/components/projects/palette-posterization/PalettePosterization.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const PaletePosterization: React.FC = () => {
2424

2525
const handleImageLoad = (image: HTMLImageElement) => {
2626
setImage(image);
27-
setImageColors([{ red: 0, green: 0, blue: 0 }])
27+
setImageColors([{ red: 0, green: 0, blue: 0 }]);
2828
// const canvas = canvasRef.current ?? undefined;
2929
// const context = canvas?.getContext('2d') ?? undefined;
3030

@@ -100,7 +100,7 @@ const PaletePosterization: React.FC = () => {
100100

101101
return (
102102
<div className='flex flex-col space-y-2'>
103-
<WebGlCanvas image={image} palette={palette} colorMetric={colorMetric} colorReducer={renderedColorReducer} />
103+
<WebGlCanvas image={ image } palette={ palette } colorMetric={ colorMetric } colorReducer={ renderedColorReducer } />
104104
{ imageColors.length > 0 && (
105105
<PalettePosterizationOptions
106106
onColorMetricSelect={ setColorMetric }

src/components/projects/palette-posterization/WebGlCanvas.tsx

+11-28
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,9 @@ import React, { useEffect, useRef } from 'react';
22
import { RgbColor } from '../../common/colorUtils';
33
import { initArrayBuffer, initProgram, initTexture, setAttributeToArrayBuffer, setTexture } from '../../common/webglUtils';
44
import { ColorMetricType, getFragmentShader, RenderedColorReducerType } from './utils';
5+
import vertexShaderSource from './shaders/vertex-shader.glsl';
56
import mixbox from 'mixbox';
67

7-
const VERTEX_SHADER = `
8-
attribute vec2 a_position;
9-
attribute vec2 a_texCoord;
10-
11-
uniform vec2 u_resolution;
12-
13-
varying vec2 v_texCoord;
14-
15-
void main() {
16-
// remap positions to be in the [-1, 1] range
17-
vec2 clipSpace = ((a_position / u_resolution) * 2.0) - 1.0;
18-
19-
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
20-
21-
v_texCoord = a_texCoord;
22-
}
23-
`
24-
258
interface WebGlCanvasProps {
269
image: HTMLImageElement | undefined;
2710
palette: RgbColor[];
@@ -45,7 +28,7 @@ const WebGlCanvas: React.FC<WebGlCanvasProps> = ({
4528
return;
4629
}
4730

48-
const program = initProgram(gl, VERTEX_SHADER, getFragmentShader(colorMetric, colorReducer));
31+
const program = initProgram(gl, vertexShaderSource, getFragmentShader(colorMetric, colorReducer));
4932
if (program === undefined) {
5033
console.error('Program could not be initialized.');
5134
return;
@@ -86,11 +69,11 @@ const WebGlCanvas: React.FC<WebGlCanvasProps> = ({
8669

8770
const texture = initTexture(gl);
8871
if (texture === undefined) {
89-
console.error('Texture could not be initialized.')
72+
console.error('Texture could not be initialized.');
9073
return;
9174
}
9275

93-
setTexture(gl, texture, image)
76+
setTexture(gl, texture, image);
9477

9578
gl.viewport(0, 0, canvas.width, canvas.height);
9679
gl.useProgram(program);
@@ -99,14 +82,14 @@ const WebGlCanvas: React.FC<WebGlCanvasProps> = ({
9982
gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);
10083

10184
const paletteBufferData = palette.flatMap(
102-
(color) => [ color.red / 255, color.green / 255, color.blue / 255, 1 ]
85+
(color) => [ color.red / 255, color.green / 255, color.blue / 255, 1 ],
10386
);
104-
paletteBufferData.push(...((new Array((64 - palette.length) * 4)).fill(0))) // pad with 0s
87+
paletteBufferData.push(...((new Array((64 - palette.length) * 4)).fill(0))); // pad with 0s
10588
const paletteLocation = gl.getUniformLocation(program, 'u_palette');
10689
gl.uniform4fv(paletteLocation, paletteBufferData);
10790

10891
const paletteSizeLocation = gl.getUniformLocation(program, 'u_paletteSize');
109-
gl.uniform1i(paletteSizeLocation, palette.length)
92+
gl.uniform1i(paletteSizeLocation, palette.length);
11093

11194
const positionLocation = gl.getAttribLocation(program, 'a_position');
11295
setAttributeToArrayBuffer(gl, positionBuffer, positionLocation);
@@ -121,17 +104,17 @@ const WebGlCanvas: React.FC<WebGlCanvasProps> = ({
121104
}
122105

123106
gl.drawArrays(gl.TRIANGLES, 0, 6);
124-
}, [ image, palette, colorMetric, colorReducer ])
107+
}, [ image, palette, colorMetric, colorReducer ]);
125108

126109
if (image === undefined) {
127110
return (
128111
<></>
129-
)
112+
);
130113
}
131114

132115
return (
133116
<canvas ref={ canvasRef } />
134-
)
135-
}
117+
);
118+
};
136119

137120
export default WebGlCanvas;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
vec3 rgb2xyz( vec3 c ) {
2+
vec3 tmp;
3+
tmp.x = ( c.r > 0.04045 ) ? pow( ( c.r + 0.055 ) / 1.055, 2.4 ) : c.r / 12.92;
4+
tmp.y = ( c.g > 0.04045 ) ? pow( ( c.g + 0.055 ) / 1.055, 2.4 ) : c.g / 12.92,
5+
tmp.z = ( c.b > 0.04045 ) ? pow( ( c.b + 0.055 ) / 1.055, 2.4 ) : c.b / 12.92;
6+
return 100.0 * tmp *
7+
mat3( 0.4124, 0.3576, 0.1805,
8+
0.2126, 0.7152, 0.0722,
9+
0.0193, 0.1192, 0.9505 );
10+
}
11+
12+
vec3 xyz2lab( vec3 c ) {
13+
vec3 n = c / vec3( 95.047, 100, 108.883 );
14+
vec3 v;
15+
v.x = ( n.x > 0.008856 ) ? pow( n.x, 1.0 / 3.0 ) : ( 7.787 * n.x ) + ( 16.0 / 116.0 );
16+
v.y = ( n.y > 0.008856 ) ? pow( n.y, 1.0 / 3.0 ) : ( 7.787 * n.y ) + ( 16.0 / 116.0 );
17+
v.z = ( n.z > 0.008856 ) ? pow( n.z, 1.0 / 3.0 ) : ( 7.787 * n.z ) + ( 16.0 / 116.0 );
18+
return vec3(( 116.0 * v.y ) - 16.0, 500.0 * ( v.x - v.y ), 200.0 * ( v.y - v.z ));
19+
}
20+
21+
vec3 rgb2lab(in vec3 c) {
22+
vec3 lab = xyz2lab( rgb2xyz( c ) );
23+
return vec3( lab.x / 100.0, 0.5 + 0.5 * ( lab.y / 127.0 ), 0.5 + 0.5 * ( lab.z / 127.0 ));
24+
}
25+
26+
float metric(in vec4 color1, in vec4 color2)
27+
{
28+
vec3 lab1 = rgb2lab(vec3(color1.rgb));
29+
vec3 lab2 = rgb2lab(vec3(color2.rgb));
30+
vec3 diff = lab1 - lab2;
31+
return diff.r * diff.r + diff.g * diff.g + diff.b * diff.b;
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
float metric(in vec4 color1, in vec4 color2)
2+
{
3+
vec4 diff = color1 - color2;
4+
return diff.r * diff.r + diff.g * diff.g + diff.b * diff.b;
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
vec3 rgb2hsl(vec3 color) {
2+
vec3 hsl = vec3(0.0, 0.0, 0.0);
3+
4+
float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB
5+
float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB
6+
float delta = fmax - fmin; //Delta RGB value
7+
8+
hsl.z = (fmax + fmin) / 2.0; // Luminance
9+
10+
if (delta == 0.0) //This is a gray, no chroma...
11+
{
12+
hsl.x = 0.0; // Hue
13+
hsl.y = 0.0; // Saturation
14+
} else //Chromatic data...
15+
{
16+
if (hsl.z < 0.5)
17+
hsl.y = delta / (fmax + fmin); // Saturation
18+
else
19+
hsl.y = delta / (2.0 - fmax - fmin); // Saturation
20+
21+
float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;
22+
float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;
23+
float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;
24+
25+
if (color.r == fmax)
26+
hsl.x = deltaB - deltaG; // Hue
27+
else if (color.g == fmax)
28+
hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue
29+
else if (color.b == fmax)
30+
hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue
31+
32+
if (hsl.x < 0.0)
33+
hsl.x += 1.0; // Hue
34+
else if (hsl.x > 1.0)
35+
hsl.x -= 1.0; // Hue
36+
}
37+
38+
return hsl;
39+
}
40+
41+
float metric(in vec4 color1, in vec4 color2)
42+
{
43+
vec3 hsl1 = rgb2hsl(color1.rgb);
44+
vec3 hsl2 = rgb2hsl(color2.rgb);
45+
return abs(hsl1.x - hsl2.x);
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
vec3 rgb2hsl(vec3 color) {
2+
vec3 hsl = vec3(0.0, 0.0, 0.0);
3+
4+
float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB
5+
float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB
6+
float delta = fmax - fmin; //Delta RGB value
7+
8+
hsl.z = (fmax + fmin) / 2.0; // Luminance
9+
10+
if (delta == 0.0) //This is a gray, no chroma...
11+
{
12+
hsl.x = 0.0; // Hue
13+
hsl.y = 0.0; // Saturation
14+
} else //Chromatic data...
15+
{
16+
if (hsl.z < 0.5)
17+
hsl.y = delta / (fmax + fmin); // Saturation
18+
else
19+
hsl.y = delta / (2.0 - fmax - fmin); // Saturation
20+
21+
float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;
22+
float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;
23+
float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;
24+
25+
if (color.r == fmax)
26+
hsl.x = deltaB - deltaG; // Hue
27+
else if (color.g == fmax)
28+
hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue
29+
else if (color.b == fmax)
30+
hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue
31+
32+
if (hsl.x < 0.0)
33+
hsl.x += 1.0; // Hue
34+
else if (hsl.x > 1.0)
35+
hsl.x -= 1.0; // Hue
36+
}
37+
38+
return hsl;
39+
}
40+
41+
float metric(in vec4 color1, in vec4 color2)
42+
{
43+
vec3 hsl1 = rgb2hsl(color1.rgb);
44+
vec3 hsl2 = rgb2hsl(color2.rgb);
45+
return abs(hsl1.z - hsl2.z);
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
vec3 rgb2hsl(vec3 color) {
2+
vec3 hsl = vec3(0.0, 0.0, 0.0);
3+
4+
float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB
5+
float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB
6+
float delta = fmax - fmin; //Delta RGB value
7+
8+
hsl.z = (fmax + fmin) / 2.0; // Luminance
9+
10+
if (delta == 0.0) //This is a gray, no chroma...
11+
{
12+
hsl.x = 0.0; // Hue
13+
hsl.y = 0.0; // Saturation
14+
} else //Chromatic data...
15+
{
16+
if (hsl.z < 0.5)
17+
hsl.y = delta / (fmax + fmin); // Saturation
18+
else
19+
hsl.y = delta / (2.0 - fmax - fmin); // Saturation
20+
21+
float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;
22+
float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;
23+
float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;
24+
25+
if (color.r == fmax)
26+
hsl.x = deltaB - deltaG; // Hue
27+
else if (color.g == fmax)
28+
hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue
29+
else if (color.b == fmax)
30+
hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue
31+
32+
if (hsl.x < 0.0)
33+
hsl.x += 1.0; // Hue
34+
else if (hsl.x > 1.0)
35+
hsl.x -= 1.0; // Hue
36+
}
37+
38+
return hsl;
39+
}
40+
41+
float metric(in vec4 color1, in vec4 color2)
42+
{
43+
vec3 hsl1 = rgb2hsl(color1.rgb);
44+
vec3 hsl2 = rgb2hsl(color2.rgb);
45+
return abs(hsl1.y - hsl2.y);
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
float metric(in vec4 color1, in vec4 color2)
2+
{
3+
float redMean = (color1.r + color2.r) / 2.0;
4+
vec4 diff = color1 - color2;
5+
vec3 squaredDiff = vec3(diff.r * diff.r, diff.g * diff.g, diff.b * diff.b);
6+
vec3 weightedDiff = vec3((2.0 + redMean / 256.0) * squaredDiff.r, 4.0 * squaredDiff.g, (2.0 + (255.0 - redMean) / 256.0) * squaredDiff.b);
7+
return weightedDiff.r + weightedDiff.g + weightedDiff.b;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
vec4 reducer(in vec4 textureColor, in vec4 paletteColor)
2+
{
3+
return vec4((textureColor + paletteColor) / 2.0);
4+
}

0 commit comments

Comments
 (0)