写点什么

HSV - RGB 来点实际的

作者:Miracle
  • 2025-09-25
    四川
  • 本文字数:2135 字

    阅读完需:约 7 分钟

HSV - RGB 来点实际的

现在开始 做点有用的东西了,图形学中最常见的 转换是 HSV <-> RGB

一个高效的算法长这样的

vec3 hsv2rgb(vec3 c) {    vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);}
复制代码

我们用 Zeta 来实现

K 是个常数,我们首先需要 常数定义的指令 Zeta 是动态类型语言 所以可以 写成这样

我们没必要单独引入 Vec<4> 对于 常量数组 [] 语法足够了


const K = [1.0, 2.0/3.0, 1.0/3.0, 3.0];


让我们增加 const 的解析


let const_stmt = just("const").padded_by(rust_ws()).ignore_then( super::ident_parser().padded().then(just(':').padded_by(rust_ws()) .ignore_then(type_parser()).padded().or_not() ).then_ignore(just('=').padded_by(rust_ws())).then(expr_parser.clone()).then_ignore(just(';').padded_by(rust_ws())) ).map(|((name, opt_ty), val)| { let ty = opt_ty.unwrap_or(Type::Void); // 或者进行类型推断 Stmt::Const(name, ty, val) }).boxed();
复制代码


然后增加 Vec 的加法

       if let Self::VecF32(_) = self {            let len = self.len();            let mut ret = Vec::new();            for idx in 0..len {                ret.push(self.get_f32(idx).unwrap() + other.as_f32().unwrap());            }            return Dynamic::from(&ret[..]);        }        if let Self::List(list) = self {            let mut ret = Vec::new();            for item in list {                ret.push(item + other.clone());            }            return Dynamic::List(ret);        }        if let Self::List(list) = other {            let mut ret = Vec::new();            for item in list {                ret.push(self.clone() +item);            }            return Dynamic::List(ret);        }        if let Self::VecF32(_) = other {            let len = other.len();            let mut ret = Vec::new();            for idx in 0..len {                ret.push(other.get_f32(idx).unwrap() + self.as_f32().unwrap());            }            return Dynamic::from(&ret[..]);        }
复制代码


Zeta 写成这样

    const K = [1.0f32, 2.0f32/3.0f32, 1.0f32/3.0f32];    fn hsv2rgb(hsv: [f32; 3]) {        let x = (hsv[0] + K).fract();        return x;    }"#;
复制代码

我们要为 Dynamic 实现 fract 先只实现需要的

impl Dynamic {    pub fn fract(&self) -> Dynamic {        match self {            Self::F32(v) => Dynamic::F32(v.fract()),            Self::List(list) => {                let mut new_list = Vec::with_capacity(list.len());                for item in list {                    new_list.push(item.fract());                }                Dynamic::List(new_list)            },            _ => panic!("Unsupported type for fract"),        }    }}
复制代码

native.rs 加上

            "fract"=> {                let val = self.get(&obj);                *self.get_mut(ret_addr).unwrap() = val.fract();            }
复制代码

完美

加上乘法 减法 和绝对值

    fn mul(self, other: Self) -> Self::Output {        if let Self::List(list) = self {            let mut ret = Vec::new();            for item in list {                ret.push(item * other.clone());            }            return Dynamic::List(ret);        }
复制代码


然后是 clamp 以及 mix 函数

            "clamp"=> {                let val = self.get(&obj);                let min = var_list[0].as_f32().unwrap();                let max = var_list[1].as_f32().unwrap();                return Some(val.my_clamp(min, max));            }            "mix"=> {                if let Dynamic::List(list) = var_list[1].clone() {                    let mut v = Vec::new();                    for elem in list {                        let x = var_list[0].clone() * (Dynamic::F32(1.0) - var_list[2].clone());                        let x = x + (elem.clone() * var_list[2].clone());                        v.push(x);                    }                    return Some(Dynamic::List(v));                }            }
复制代码


我们的 Zeta 代码现在长这样


    const K = [1.0, 2.0/3.0, 1.0/3.0];    fn hsv2rgb(hsv: [f32; 3]) {        let rgb = (((hsv[0] + K).fract() * 6.0f32 - 3.0f32).abs() - 1.0).clamp(0.0, 1.0);        return mix(1.0f32, rgb, hsv[1]) * hsv[2];    }
复制代码

注意 我们现在明确需要类型了

现在我们的虚拟机上验证执行


测试这几个 HSV 的值

结果是这样的


完美 下一步就是 放在显卡上执行了

用户头像

Miracle

关注

三十年资深码农 2019-10-25 加入

还未添加个人简介

评论

发布
暂无评论
HSV - RGB 来点实际的_Miracle_InfoQ写作社区