Skip to content

Commit

Permalink
Shader for color mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
Николаев Андрей committed Aug 17, 2023
1 parent a455ff5 commit 87405d7
Show file tree
Hide file tree
Showing 5 changed files with 652 additions and 15 deletions.
586 changes: 582 additions & 4 deletions dist/ui/index.html

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"dependencies": {
"@preact/signals": "^1.2.1",
"culori": "^3.2.0",
"preact": "^10.17.0"
"preact": "^10.17.0",
"twgl.js": "^5.5.1",
"vite-plugin-virtual-plain-text": "^1.4.3"
},
"devDependencies": {
"@figma/plugin-typings": "^1.74.0",
Expand Down
58 changes: 51 additions & 7 deletions ui/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@ import { useRef, useEffect } from "preact/hooks";
import CssColorCodes from "./components/CssColorCodes";

import { formatHex, formatHex8, converter, inGamut, clampChromaInGamut } from "./helpers/culori.mjs";
import * as twgl from 'twgl.js';

import { colorConversion } from "./helpers/colorConversion";
import { PICKER_SIZE, SLIDER_SIZE, LOW_RES_PICKER_SIZE, LOW_RES_PICKER_SIZE_OKLCH, lOW_RES_FACTOR, lOW_RES_FACTOR_OKLCH, OKLCH_CHROMA_SCALE, debugMode } from "./constants";

import { UiMessageTexts } from "./ui-messages";
import { renderImageData } from "./helpers/renderImageData";

// import { renderImageData } from "./helpers/renderImageData";

import { clampNumber, limitMouseHandlerValue, is2DMovementMoreVerticalOrHorizontal, roundWithDecimal, isColorCodeInGoodFormat } from "./helpers/others";

import utilsGlsl from '@virtual:shaders/ui/shaders/utils.glsl';
import libraryGlsl from '@virtual:shaders/ui/shaders/library.glsl';
import fShader from '@virtual:shaders/ui/shaders/f_shader.glsl';
import vShader from '@virtual:shaders/ui/shaders/v_shader.glsl';


const inGamutSrgb = inGamut("rgb");
const inGamutP3 = inGamut("p3");
Expand Down Expand Up @@ -57,7 +65,9 @@ let shapeInfos: ShapeInfos = {
}
}

let colorPickerCanvas2dContext: CanvasRenderingContext2D | null = null;
let colorPickerGLContext: WebGL2RenderingContext | null = null;
let bufferInfo: twgl.BufferInfo;
let programInfo: twgl.ProgramInfo;

let UIMessageOn = false;

Expand All @@ -72,9 +82,16 @@ let colorCodesInputValues = {
hex: ""
}

enum ColorModels {
'oklchCss',
'oklch',
'okhsl',
'okhsv'
}

// Default choice unless selected shape on launch has no fill.
let currentFillOrStroke = "fill";
let currentColorModel: "oklchCss" | "oklch" | "okhsl" | "okhsv";
let currentColorModel: keyof typeof ColorModels;
let activeMouseHandler: Function | undefined;

// This var is to let user move the manipulators outside of their zone, if not the event of the others manipulator will trigger if keep the mousedown and go to other zones.
Expand All @@ -95,7 +112,20 @@ export const App = function() {
if (debugMode) { console.log("UI: render App"); }

useEffect(() => {
colorPickerCanvas2dContext = colorPickerCanvas.current!.getContext("2d");
colorPickerGLContext = colorPickerCanvas.current!.getContext("webgl2");
const gl = colorPickerGLContext!;
const arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0]
}

bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
programInfo = twgl.createProgramInfo(gl, [
vShader,
libraryGlsl + utilsGlsl + fShader
]);

gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);

// We launch the init procedure from the plugin (send some values and the color shape if any is selected) when the UI is ready.
parent.postMessage({ pluginMessage: { type: "init"} }, "*");
Expand Down Expand Up @@ -360,7 +390,23 @@ export const App = function() {
colorPickerCanvas() {
if (debugMode) { console.log("UI: render.colorPickerCanvas()"); }

colorPickerCanvas2dContext!.putImageData(renderImageData(okhxyValues.hue.value, currentColorModel, fileColorProfile), 0, 0);
let dark = document.documentElement.classList.contains("figma-dark");

const gl = colorPickerGLContext!;
const isLch = ['oklch', 'oklchCss'].includes(currentColorModel);
const size = isLch ? LOW_RES_PICKER_SIZE_OKLCH : LOW_RES_PICKER_SIZE;
gl.viewport(0, 0, size, size);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
twgl.setUniforms(programInfo, {
resolution: [size, size],
dark,
chroma_scale: OKLCH_CHROMA_SCALE,
showP3: fileColorProfile === 'p3',
mode: ColorModels[currentColorModel],
hue_rad: okhxyValues.hue.value * Math.PI / 180,
})
twgl.drawBufferInfo(gl, bufferInfo);
},
fillOrStrokeSelector() {
if (debugMode) { console.log("UI: render.fillOrStrokeSelector()"); }
Expand Down Expand Up @@ -464,8 +510,6 @@ export const App = function() {
updateManipulatorPositions.all();
render.opacitySliderCanvas();
render.fillOrStrokeSelector();

colorPickerCanvas2dContext!.clearRect(0, 0, colorPickerCanvas.current!.width, colorPickerCanvas.current!.height);
};


Expand Down
4 changes: 2 additions & 2 deletions ui/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ export const PICKER_SIZE = 240;
// We use a different value for the slider as they take less room.
export const SLIDER_SIZE = 148;

export const lOW_RES_FACTOR = 2.5;
export const lOW_RES_FACTOR_OKLCH = 1;
export const lOW_RES_FACTOR = 0.5;
export const lOW_RES_FACTOR_OKLCH = 0.2;

export const LOW_RES_PICKER_SIZE = PICKER_SIZE / lOW_RES_FACTOR;
export const LOW_RES_PICKER_SIZE_OKLCH = PICKER_SIZE / lOW_RES_FACTOR_OKLCH;
Expand Down
15 changes: 14 additions & 1 deletion viteUI.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@ import { resolve } from "path";
import { defineConfig } from "vite";
import preact from "@preact/preset-vite";
import { viteSingleFile } from "vite-plugin-singlefile";
import plainText from 'vite-plugin-virtual-plain-text';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [preact(), viteSingleFile()],
plugins: [
preact(),
plainText({ virtualNamespace: '@virtual:shaders/', dtsAutoGen: 'virtual-shaders-declaration' }),
{
name: 'watch-external', // https://stackoverflow.com/questions/63373804/rollup-watch-include-directory/63548394#63548394
async buildStart(){
this.addWatchFile('ui/shaders/utils.glsl');
this.addWatchFile('ui/shaders/library.glsl');
this.addWatchFile('ui/shaders/v_shader.glsl');
this.addWatchFile('ui/shaders/f_shader.glsl');
}
},
viteSingleFile()],
build: {
rollupOptions: {
input: {
Expand Down

0 comments on commit 87405d7

Please sign in to comment.