Colors 寻找四元数,表示从一个向量到另一个向量的转换 简介。

Colors 寻找四元数,表示从一个向量到另一个向量的转换 简介。,colors,linear-algebra,transformation,quaternions,Colors,Linear Algebra,Transformation,Quaternions,之前,我讨论过如何将rgb三元组转换为四元数。在那个问题之后,我设法得到了单位四元数,但我怀疑它们的内部结构。没有简单的方法来操作它们,并分离亮度和色度,因为这是单位长度的四元数。根据我对它的感觉,亮度应该被编码在真实的部分,或者整个量级;颜色“色度”信息应编码在虚部 今天,我决定采取另一种不同于上面链接中第一种方法的方法来改进。我认为它可能会成功,因为四元数不仅可以存储旋转(单位四元数),还可以存储比例。首先,我将首先解释我的下一个想法。在下面的解释中,我将使用GLSL着色器语法 方法描述和

之前,我讨论过如何将rgb三元组转换为四元数。在那个问题之后,我设法得到了单位四元数,但我怀疑它们的内部结构。没有简单的方法来操作它们,并分离亮度和色度,因为这是单位长度的四元数。根据我对它的感觉,亮度应该被编码在真实的部分,或者整个量级;颜色“色度”信息应编码在虚部

今天,我决定采取另一种不同于上面链接中第一种方法的方法来改进。我认为它可能会成功,因为四元数不仅可以存储旋转(单位四元数),还可以存储比例。首先,我将首先解释我的下一个想法。在下面的解释中,我将使用GLSL着色器语法


方法描述和问题正文。 对于图像的某些像素,让我们在单位立方体中简化一个3D矢量
vec3 u
,其中正坐标位于闭合范围[0.0,1.0],表示完整的rgb颜色空间。因此,现在
u
的坐标、
u.x
u.y
u.z
将相应地表示该像素的红色、绿色和蓝色值。然后让我们取一个纯白色向量
constvec3v=vec3(1.0,1.0,1.0)。让我们定义一些四元数
q
,这样我们的向量
u
就是“
v
,用四元数
q
旋转和缩放”。简单地说,
q
必须回答“如何转换
v
,以获得最初构思的颜色
u
?”的问题。让我们介绍“旋转和缩放”操作的函数:
vec3q2c(在vec4q中,在vec3v中)
。我称之为“四元数到颜色”转换器

编写
q2c(q,v)
非常简单,:
q2c(q,v)=(q*vec4(v,0.0))*q'
。这里,“
*
”运算符表示:;让我们把它变成一个函数
vec4 qmul(在vec4 q1中,在vec4 q2中)
。而“
q'
”表示
q
,让我们将其设置为
vec4qconj(在vec4q中)
。省略它们的简单实现(您可以在完整的源代码中找到),我们将使用经典代码:

vec4 q2c(in vec4 q, in vec3 v) {
    return qmul(qmul(q, vec4(v, 0.0)), qconj(q));
}
现在我们有了
q2c(q,v)
函数,它通过旋转和缩放一些选定的三维向量
v
,将四元数
q
转换为颜色

问题是如何找到四元数
q

从程序员的角度来看,目标是编写反向函数vec4 c2q(在vec3 u中,在vec3 v中)
——一个相应的“颜色到四元数”转换器

请注意,如果没有很好的理由,您不应该触摸q2c()。例如,其逻辑中存在严重缺陷,导致“无法解决任务”,您可以证明这一点


如果你的答案是正确的,你怎么检查呢? 事实上,如果您能够前后转换,那么检查方法将产生于这样一个事实,即您将获得初始值。因此,对于任何非零长度
v
u
的检查条件为,必须始终等于
q2c(c2q(u,v),v)
v
必须具有非零长度,因为不能“缩放零”以获得“某物”

为了让事情变得简单,我已经准备好了,使用shadertoy.com服务

你需要一台像样的电脑,可以上网,还有一个支持webGL的网络浏览器(我用的是Chrome)。这个程序可以在任何GPU上运行,甚至可以嵌入英特尔的处理器。它甚至可以在我的低端智能手机上使用

为了测试您的答案,您应该将您建议的公式(用
GLSL
语法编写)放入
c2q()
函数中。然后按应用按钮,您的更改将生效:

左侧的图像表示一些未更改的源像素。右半部分将包含像素,通过
q2c(c2q())
前后变换。显然,两半在视觉上必须相等,您不应该注意到任何垂直线。可能会出现一些数学上的(不明显的)错误,但这仅仅是由于浮点的性质——它的有限精度和可能的舍入误差

请随意编辑和试验,更改将只在本地、在您的计算机上进行,您不能破坏任何东西。如果视频未在第一次打开时播放(shadertoy bug)-尝试暂停/取消暂停。享受吧


c2q()大厅
如果一切正常,则图像的右侧(已处理图像)应与左侧(原始图像)相等。在这里,我将回顾不同的结果,这些结果是通过在
c2q()
实现中放置某物而不是
xxxxx
获得的:

vec4 c2q(vec3 u, vec3 v) {
    return xxxxx;
}
让我们继续吧

  • 起初,我认为这一定行得通:
    vec4(十字(u,v),点(u,v))

  • 其中一项:
    vec4(交叉(u,v),sqrt(点(u,u)*点(v,v))+点(u,v))

  • 他暗示“别忘了规范化q”:
    标准化(vec4(交叉(u,v)、sqrt(点(u,u)*点(v,v))+点(u,v))

  • @minorlogic的评论似乎更进一步: 按
    sqrt(长度(v)/长度(u))
    缩放所有
    q
    的组件,
    vec4(十字(u,v)、点(u,v))*sqrt(长度(u)/长度(v))

  • 交换比率后:
    vec4(十字(u,v),点(u,v))*sqrt(长度(v)/长度(u))

我的尝试:

vec4 c2q(vec3 u, vec3 v) {
    float norm_q = sqrt(length(u) / length(v));
    vec4 u4 = vec4(normalize(u), 0.0);
    vec4 v4 = vec4(normalize(v), 0.0);
    return norm_q * (qmul(u4, v4 + u4) / length(v4 + u4));
}

与链接相比,
qmul
@rabbi76中存在(+/-)差异,这不是它,而是
q2c()
的乘法顺序:
q*v*q'
vs
q'*v*q
。交换它,您将得到反向旋转和RGB->CMY颜色偏移。大约一个小时后我终于找到了。此外,规则也改变了,问题变得更加有趣和互动;-)@minorlogic测试,