写的这个demo是想要实现Siggraph 17的一篇论文
原文地址如下
https://dl.acm.org/citation.cfm?doid=3072959.3073690
代码链接
https://github.com/Birdy-C/HCI_ColorMixer
demo
B站链接https://www.bilibili.com/video/av31583427/
关于论文
这个论文其实还是比较简单的啦(我不过我只看了和写的部分有关的内容)
主要部分一个是水滴融合,一个是提出了新的交互方式(的样子)。(为什么不是一篇HCI论文而是一篇图形学论文)
因为原文是在Pad上的一个软件,所以相对而言交互会方便很多。
所以交互方式就只能用鼠标点击了——
关于水滴融合,其实我的理解就是
看看这个等势面!多么完美的水滴融合模型啊!(它可能有一个更专业的名词叫做隐式曲面)
然后用的是据说是高斯的一个近似
剩下的就是对于在某个势能以上的点判断各部分的贡献比例了
步骤
事件和交互
落下不会写前端的眼泪……
js的数据处理都折腾了很久。经常小数转十六进制就炸了啊、转了十六进制没有补0啊……格式输出不对啊……还好比jsx debug方便很多(不太会用Adobe ExtendScript Toolkit)。
好像在js到jsx不能直接传数组。我后来是弄成字符串在split的。
然后在CEP JavaScript和ExtendScript 端之间传数据的时候,我还出现过事件监听循环的那种炸(……)网络环路那种。
在canvas上显示小球的时候,是遍历canvas上每一个点,根据位置判断应该输出什么颜色。
球的信息同步
然后基本的界面是
对就是那么傻。
一个球对应一个颜色。js中有一个数组记录球的数量,jsx中一个数组记录图层的信息。然后接收到颜色变化事件之后,更新mask的颜色。
新建颜色的jsx代码
function addNewColor(inColor) {
try {
// 新建两个图层并塞到数组里
var layerRef = app.activeDocument.artLayers.add();
layerRef.name = "ColorMixer";
var layerRefMask = app.activeDocument.artLayers.add();
layerRefMask.name = "CM mask";
myLayerSets[index] = layerRef;
index++;
myLayerSets[index] = layerRefMask;
index++;
// layerRefMask.blendMode = BlendMode.NORMAL; // auto
// 移到合适的位置 这里的worklayer就是之前那个workspace
worklayer.move(layerRef, ElementPlacement.PLACEBEFORE);
worklayer.move(layerRefMask, ElementPlacement.PLACEBEFORE);
layerRefMask.grouped = true;//设为剪切蒙版
app.activeDocument.selection.selectAll;//选择所有颜色
var colorRef = new SolidColor;
colorRef.rgb.hexValue = inColor;// 设置颜色
app.activeDocument.selection.fill(colorRef);
app.activeDocument.activeLayer = worklayer;// 把激活图层回到Workspcace 免得读完之后位置不对
} catch (e) {
alert("addNewColor" + e);
}
}
你敢信剪切蒙版是grouped……
绘制
每次更新颜色的时候,需要把画在workspace上的内容分块绘制到下面的分图层中。
这个还是比较麻烦的(抚额)
分几步
1. 选出在workspace上的绘制内容
2. 把下面图层中被覆盖的内容清空
3. 在下面的workspace按不同的颜色组成填充
第二步是为了防止在上面的颜色已经绘制的内容遮挡先绘制的内容。
但是这样的模型是有问题的。
主要是在透明度的问题上,由于这个没有办法读取具体的透明度,所以没有办法分情况处理(或许有,让我再想想有没有好的操作)。一旦有了透明度之后,将这个颜色合并到其他颜色里的操作会显得格外复杂。
举个例子、
比如图层是
0层 —50%—
1层 — 50%—
现在要把两个图层调换顺序,取得一样的效果的话,我需要
1层 —25%— // ==50%*50%
0层 —67%— // == 50%/75%
所以如果有透明度的话处理起来会有问题。所以对于软画笔啊啥的,会有问题。感觉要是真想要避免这种问题的话,可能需要重新确定结构了、
接下来分别介绍那三步
1. 选出在workspace上的绘制内容
我也想不到这一步会很麻烦……
如果在操作PS的话直接Ctrl加点击那个图层就行了。
然后翻遍了文档,artlayer没有返回选区的函数。
于是开始找有没有取artlayer的色彩范围的函数……
最后的解决方法又是迷之智障了——
这样,然后取channel返回选区。
这也是为什么每次我点一下那个插件PS的取色板会抖,而且处理还非常慢了(捂脸)。
2. 把下面图层中被覆盖的内容清空
这个就selection.clear()一个命令就行
3. 在下面的workspace按不同的颜色组成填充
理论上也就selection.fill()一个命令
由于之前讲过的透明度的问题,如果本来我想呈现的是两个图层各50%的颜色的话,下面那个图层实际的透明度是100%
0层 —50%—
1层 — 100%—
这样呈现的是0层50%,1层50%的效果
0层 —50%—
1层 — 50%—
这样由于混合的效果(普通混合),下面一层实际显示出来是25%
所以由于这个,需要进行一些预处理。
后面
第一个PS扩展,不枉我早年无知的时候玩过PS(???)
一开始想写插件的,然后发现插件限制还蛮多的(而且看不懂例程),就写了个扩展。
感觉最后效果一般吧——能交作业,但是远远没到愿意去用它的地步。很多地方还很粗糙。慢慢来吧。
哦然后最后引用我的傻儿子评价——
舍弃无用的取色功能,剩下有用的球。
这球真好玩.jpg
我觉得以上非常有道理可以考虑一下↑