颜色的类层次结构

时间:2011-12-31 19:22:25

标签: c++ class colors hierarchy

我无法确定用于存储RGB / RGBA颜色信息的类结构。

我正在制作一个非常简单的3D游戏引擎,以获得乐趣并磨练我的OO编程能力。

我希望我的引擎支持RGB和RGBA颜色。最重要的是,我想拥有它,因此可以将RGB和RGBA值指定为浮点数钳位到[0,1]或无符号字符。我认为出于存储目的,最好使用无符号字符,因为它们使用的内存数量与浮点数相差第四。

所以现在,我已经设计了以下类用于此:Color,Color3,Color3f,Color3c,Color4,Color4f和Color4c。 Color是Color3和Color4的超类,而Color3是Color3f和Color3c的超类,而Color4是Color4f和Color4c。

这似乎是一种比需要更复杂的方法。我还想了一下使用泛型,所以不使用Color3f和Color3c,就可以使用Color3< float>和Color3< unsigned char>。然而,这种方法似乎也不正确。

理想情况下,我希望能够编写如下代码:     

Color3 red1(255, 0, 0);
Color3 red2(1.0f, 0.0f, 0.0f);
Color* someColor = new Color3(1.0f, 0.0f, 0.5f);
Color4 anotherColor = *someColor;
Color4 thisColor = anotherColor.toChar();
//thisColor.r = 255, thisColor.g = 0, thisColor.b = 127
thisColor = thisColor.toFloat();
//thisColor.r = 1.0f, thisColor.g = 0.0f, thisColor.b = 0.5f

现在这在C ++中无法实现(至少据我所知),但是如何在不创建7个单独的类的情况下集中相同的功能呢?而且不存储浪费的信息?例如,在内存中拍摄1024x1024图像。这将是一个包含超过一百万种这些颜色的数组,那么如何创建一个灵活且可重用的Color类层次结构呢?即,通过无符号字符将RGB和RGBA值存储在不同的结构中,但是提供了检索浮点值的功能吗?

对不起,如果这不够具体或什么,这是我的第一个问题!让我知道还有什么有用的。如果你们愿意,我可以发布我迄今为止尝试过的代码,但希望你能理解我想要实现的目标。

4 个答案:

答案 0 :(得分:3)

您只需要一种颜色(或颜色可能)

在内部,您可以存储您喜欢的值,32位无符号整数RGBA(或BGRA)是常见的,然后只使用掩码和位移来提取每个组件。

您可以拥有采用Color(unsigned char red,unsigned char green,unsigned char blue, unsigned char alpha=0xff)或浮点数

的构造函数

每种形式的每个组件都有类似的getter / setter。

编辑:但是如果你正在计划任何类型的高性能,那么每个像素的一组颜色对象组成的图像可能不是可行的方法。您可能希望查看一组静态函数来设置/获取每个组件以及一个以图像格式的格式获取像素的构造函数(即BGRA或RGB unsigned int)

答案 1 :(得分:2)

你想为所有的可能性做一个课程。这是错的。一个班级可以处理所有这些问题。

首先,您的GPU预计会有4x [0,1]个浮点数用于颜色数据,而两个浮动[0,1]比[0,255] RGB颜色更精确。这意味着从浮点0,1到char 0,255是有损的。这两个事实意味着你实际上别无选择,只能使用4x [0,1]作为实现。是否为[0,255]提供访问器和构造函数取决于您。

其次,你可以通过简单地将A默认为1来支持同一类中的RGB和RGBA,任何不想处理A的人都不需要。

答案 2 :(得分:1)

Xeo关于过度工程的观点很好,您可能希望阅读我关于避免over-engineering的答案。但OO的重点是隐瞒复杂性,而不是鼓励它。

从具有一些有效内部表示的Color类开始,并为您想要作为参数的数据类型重载ctors。除非你有一些需要来公开实现,否则不要打扰所有的子类。采取可能有效的最简单方法。

答案 3 :(得分:1)

这只是编码其他人所说的内容,因为它看起来很有趣。这不是答案。

class color {
    unsigned char red_, green_, blue_, alpha_;
public:
    color() 
    :red_(0), green_(0), blue_(0), alpha_(0xFF) {}
    color(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=0xFF)
    :red_(red), green_(green), blue_(blue), alpha_(alpha) {}
    color(float red, float green, float blue, float alpha=1.0)
    :red_(red*255.0+.5), green_(green*255.0+.5), blue_(blue*255.0+.5), alpha_(alpha*255.0+.5) {}
    color(const color& rhs)
    :red_(rhs.red_), green_(rhs.green_), blue_(rhs.blue_), alpha_(rhs.alpha_) {}
    //operator= and dtor automatically generated
    unsigned char& c_red() {return red_;}
    unsigned char& c_green() {return green_;}
    unsigned char& c_blue() {return blue_;}
    unsigned char& c_alpha() {return alpha_;}
    const unsigned char& c_red() const {return red_;}
    const unsigned char& c_green() const {return green_;}
    const unsigned char& c_blue() const {return blue_;}
    const unsigned char& c_alpha() const {return alpha_;}
    void set_f_red(float val) {red_=val*255.0+.5;}
    void set_f_green(float val) {green_=val*255.0+.5;}
    void set_f_blue(float val) {blue_=val*255.0+.5;}
    void set_f_alpha(float val) {alpha_=val*255.0+.5;}
    float get_f_red() const {return red_/255.0;}
    float get_f_green() const {return green_/255.0;}
    float get_f_blue() const {return blue_/255.0;}
    float get_f_alpha() const {return alpha_/255.0;}

    unsigned int rgba() {return (red_<<24)|(green_<<16)|(blue_<<8)|(alpha_<<0);}
};