[alg] kleur atlas shader

Pagina: 1
Acties:
  • 155 views sinds 30-01-2008
  • Reageer

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Ik ben op zoek naar de "formule" voor een atlas kleur verloop van hoogte. Het is niet gewoon lineair hue, want dan wordt bv. geel te klein. Heeft iemand een idee wat dit moet zijn, ik kan het nergens vinden...

Voorbeeld uit een ander programma:

Afbeeldingslocatie: http://www.cs.vu.nl/~fasmit/atlas_shader.png

Oh ik heb nu dit:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
    const static float colormap[][2] = {
        {0.0000f, 240.0f},
        {0.1042f, 163.0f},
        {0.2083f, 118.0f},
        {0.3125f,  95.0f},
        {0.4167f,  72.0f},
        {0.5208f,  54.0f},
        {0.6250f,  42.0f},
        {0.7292f,  30.0f},
        {0.8333f,  19.0f},
        {0.9375f,   7.0f},
        {1.0000f,   0.0f}
    };


uit die tabel gehaald met photoshop. Waar de eerste waarde het percentage van de balk is, en de tweede is de hue, in een HSL kleur systeem. (S=1.0, L hangt af van de belichting)

[ Voor 47% gewijzigd door Zoijar op 13-04-2004 12:24 ]


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 10-05 18:53

Bosmonster

*zucht*

Denk dat de buren hier meer verstand van hebben :)

Move W&G -> P&W

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Bosmonster schreef op 13 april 2004 @ 18:13:
Denk dat de buren hier meer verstand van hebben :)

Move W&G -> P&W
Ja ik twijfelde een beetje waar het meer thuis hoorde :) Bedankt.

Verwijderd

Het ziet eruit alsof het logaritmisch is gemaakt.

Nouja, het is iets van:
Hue = 256*(1-sqrt(percentage))

Vermoedelijke reden: mens is gevoeliger voor verlchillen in hue van groen/geel/rood dan blauw

[ Voor 73% gewijzigd door Verwijderd op 13-04-2004 19:58 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Verwijderd schreef op 13 april 2004 @ 19:53:
Het ziet eruit alsof het logaritmisch is gemaakt.

Nouja, het is iets van:
Hue = 256*(1-sqrt(percentage))

Vermoedelijke reden: mens is gevoeliger voor verlchillen in hue van groen/geel/rood dan blauw
Ok, daar zit wel wat in ja...ik heb ook dit nog gevonden:
C-39 I WANT TO VISUALIZE A SCALAR FUNCTION OF TWO VARIABLES. SHOULD I USE RGB
VALUES CORRESPONDING TO THE COLORS OF THE RAINBOW?

When you look at a rainbow you do not see a smooth gradation of colors.
Instead, some bands appear quite narrow, and others are quite broad.
Perceptibility of hue variation near 540 nm is half that of either 500 nm
or 600 nm. If you use the rainbow's colors to represent data, the
visibility of differences among your data values will depend on where they
lie in the spectrum.

If you are using color to aid in the visual detection of patterns, you
should use colors chosen according to the principles of perceptual
uniformity. This an open research problem, but basing your system on CIE
L*a*b* or L*u*v*, or on nonlinear video-like RGB, would be a good start.
Misschien dan toch maar afstappen van HSL...hmmm.. (bold regel in quote geeft me niet veel hoop... :| )

[ Voor 3% gewijzigd door Zoijar op 13-04-2004 21:06 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Heb nog even CGPP erop nageslagen, hoofdstuk 13, en daar staat:

"A perceptually uniform color space is needed, in qhich two colors that are equally distant are perceived as equally distant by viewers. The 1976 CIE LUV uniform color space was developed in reponse to this need."

Het is dus niet zo simpel als ik dacht :) Ik lees nog even verder, evengoed bedankt voor het meedenken.

Verwijderd

Zoijar schreef op 13 april 2004 @ 21:21:
Heb nog even CGPP erop nageslagen, hoofdstuk 13, en daar staat:
CGPP = Computer Graphics ... .. ??

(kon niet snel iets relevants vinden op google)

Ohja: is het voor scherm visualisatie? voor prof.. monitoren of voor elke web-browsende bak? Moet je wel een "regenboog" gebruiken? (http://www.research.ibm.com/people/l/lloydt/) etc :)

Verwijderd

die knopjes lijken ook teveel op elkaar. bedtijd dus :)

[ Voor 89% gewijzigd door Verwijderd op 13-04-2004 22:49 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Verwijderd schreef op 13 april 2004 @ 22:46:
CGPP = Computer Graphics ... .. ??
Computer Graphics - Principles and Practice. Foley, van Dam, Feiner, Hughes.

Tijden lang de "bijbel" voor cg geweest; nu een beetje gedateerd maar nog steeds staat er veel in.
Ohja: is het voor scherm visualisatie? voor prof.. monitoren of voor elke web-browsende bak? Moet je wel een "regenboog" gebruiken? (http://www.research.ibm.com/people/l/lloydt/) etc :)
Ja, daar is het voor. Voor beamers...zou dan ook waarschijnlijk het juiste whitepoint moeten hebben etc. Best wel een gedoe. Die link ziet er wel interessant uit, ik zal die papers eens lezen. Misschien dat zij een veel makkelijkere goede oplossing hebben. Thnx :)

[ Voor 3% gewijzigd door Zoijar op 13-04-2004 23:07 ]


Verwijderd

Interessant onderwerp, ik kan de formule wel gebruiken in een mouse visualization tooltje waar ik mee bezig ben :)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Voor degene die geinteresseerd waren... eindelijk heb ik iets dat redelijk goed werkt. Moet nog even het zee niveau iets omlaag halen, maar verder ziet het er VEEL beter uit dan "regenboog". Zelfs als ik regenboog zou gebruiken nu, ziet het er beter uit. Geel is veel breder, maw het is nu perceptually uniform.

Afbeeldingslocatie: http://www.cs.vu.nl/~fasmit/ter_test.jpg

De code/theorie viel nog vies tegen. Het gaat er voornamelijk om om in CIE L*H*C* te werken. Dat is een soort HSL, met het verschil dat afstanden in kleuren overeen komen met de gevoels afstand. Dat converteren naar CIE Lab, hetzelfde als LHC maar niet in pool coordinaten. Dan naar CIE XYZ, de standaard met D65 whitepoint...en dan dat nog naar sRGB met standaard waarden...

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
void TextureGenerator::putColor(Grid::Index pos, const Vector& lightDirection, char* rgb) {
    float lab[3];
    float xyz[3];
    float hue = heightToHue(grid_.getElevation(pos));
    float light = positionToLightness(pos, lightDirection);

    LCHtoLAB(light*100.0f, 50.0f, hue, lab);
    LABtoXYZ(lab[0], lab[1], lab[2], xyz);
    XYZtoSRGB(xyz[0], xyz[1], xyz[2], rgb);
}

float TextureGenerator::positionToLightness(const Grid::Index& pos, const Vector& light) {
    // The vertex to shade
    Vector v(grid_.getVertex(pos));
    
    // We can not determine dx/dy on a global edge, so check for that
    if (pos.x > 0 && pos.y > 0 &&
        pos.x < (grid_.edge()-1) && pos.y < (grid_.edge()-1))
    {
        // The x/y slopes, their cross product will be the unnormalized normal.
        Vector dx = (grid_.getVertex(Grid::Index(pos.x+1, pos.y)) - grid_.getVertex(Grid::Index(pos.x-1, pos.y)));
        Vector dy = (grid_.getVertex(Grid::Index(pos.x, pos.y+1)) - grid_.getVertex(Grid::Index(pos.x, pos.y-1)));
        
        // Dot product with normal gives cos of angle between light and normal
        float shade = light % normalize(dy * dx);
        
        // Light on the back of a polygon is not visible
        if (shade < 0.0f) shade = 0.0f;

        // Add some ambient light, and shade the remaining range
        //float ambient = 0.05f;
        //float maxlightness = 0.7f;
        float ambient = 0.00f;
        float maxlightness = 1.0f;

        return ambient + (shade * (maxlightness - ambient));
    } else {
        // Neutral light on the edges
        return 0.5f;
    }
}

float TextureGenerator::heightToHue(float height) const {
    // Hue is given as angle between 0-360 degrees.
    const static float colormap[][2] = {
        {0.0000f, 240.0f},
    //  {0.1042f, 163.0f},
        {0.1042f, 130.0f},
        {0.2083f, 118.0f},
        {0.3125f,  95.0f},
        {0.4167f,  72.0f},
        {0.5208f,  54.0f},
        {0.6250f,  42.0f},
        {0.7292f,  30.0f},
        {0.8333f,  19.0f},
        {0.9375f,   7.0f},
        {1.0000f,   0.0f}
    };

    // Scale height to the [0,1] range
    float scaledHeight = height / (256.0f*16.0f);
    if (scaledHeight > 1.0f) scaledHeight = 1.0f;
    if (scaledHeight < 0.0f) scaledHeight = 0.0f;

    float hue = 0.0f;
    for (int i=0; i<sizeof(colormap)-1; i++) {
        if (scaledHeight >= colormap[i][0] &&
            scaledHeight <= colormap[i+1][0])
        {
            // perc is in [0,1]
            float perc = (scaledHeight - colormap[i][0]) / (colormap[i+1][0] - colormap[i][0]);
            hue = colormap[i][1] + perc*(colormap[i+1][1] - colormap[i][1]);
            break;
        }
    }

    return hue;
}

// Convert CIE LCH to CIE LAB (no loss of color)
// H (hue) is given in degrees, not radians
void TextureGenerator::LCHtoLAB(float L, float C, float H, float* lab) const {
    lab[0] = L;     // L = L

    // a = +-C / sqrt(tan(H)^2 + 1)
    float tan = std::tan(static_cast<float>(RAD(H)));
    float tmp = 1 / std::sqrt(tan*tan+1);

    if (H <= 90.0f || H >= 270.0f) {
        lab[1] = C * tmp;
    } else {
        lab[1] = -C * tmp;
    }

    // b = +- sqrt(C^2 - a^2)
    lab[2] = std::sqrt((C*C) - (lab[1]*lab[1]));
    if (H > 180.0f) lab[2] = -lab[2];
}

// Convert CIE LAB to CIE XYZ (uses sRGB reference white D65, no loss of color)
void TextureGenerator::LABtoXYZ(float L, float A, float B, float* xyz) const {
    const static Vector D65(0.9505f, 1.0f, 1.0891f);
    const static float e = 216.0f/24389;
    const static float k = 24389/27.0f;

    // Calculate Y
    float y;
    if (L > k*e) {
        float tmp = (L+16)/116.0f;
        y = tmp * tmp * tmp;
    } else {
        y = L / k;
    }

    // Now we can calc Fy
    float fy;
    if (y > e) {
        fy = (L+16)/116.0f;
    } else {
        fy = (k*y+16)/116.0f;
    }

    // Now we can calc fx and fz
    float fx = (A/500.0f) + fy;
    float fz = fy - (B/200.0f);

    // and finally x and z
    float x, z;
    float fx3 = fx * fx * fx;
    float fz3 = fz * fz * fz;

    if (fx3 > e) {
        x = fx3;
    } else {
        x = (116.0f*fx - 16) / k;
    }

    if (fz3 > e) {
        z = fz3;
    } else {
        z = (116.0f*fz - 16) / k;
    }

    // Now scale to the reference white point (D65 for sRGB)
    xyz[0] = x * D65.x;
    xyz[1] = y * D65.y;
    xyz[2] = z * D65.z;
}

// Convert CIE XYZ (with sRGB ref.white D65) to sRGB (losses some color information)
void TextureGenerator::XYZtoSRGB(float X, float Y, float Z, char* rgb) const {
    const static PTRS::matx44<float> XYZtoSRGBMatrix(
          3.24071f, -0.969258f,  0.0556352f, 0.0f,
         -1.53726f,   1.87599f,  -0.203996f, 0.0f,
        -0.498571f, 0.0415557f,    1.05707f, 0.0f,
              0.0f,       0.0f,        0.0f, 1.0f);

    Vector srgbVec = Vector(X, Y, Z) * XYZtoSRGBMatrix;

    rgb[0] = sRGBValue(srgbVec.x);
    rgb[1] = sRGBValue(srgbVec.y);
    rgb[2] = sRGBValue(srgbVec.z);
}

// Gamma correct linear srgb values to non-linear rgb
unsigned char TextureGenerator::sRGBValue(float linear) const {
    const static float treshhold = 0.0031308f;
    const static float exponent = 1.0f/2.4f;
    float result;

    // Compute non-linear sRGB
    if (linear <= treshhold) {
        result = 12.92f * linear;
    } else {
        result = 1.055f * std::pow(linear, exponent) - 0.055f;
    }

    // Clamp RGB to [0,1] range
    if (result < 0.0f) result = 0.0f;
    if (result > 1.0f) result = 1.0f;
    
    // Scale to discrete byte range [0,255]
    return static_cast<unsigned char>(255 * result);
}
Pagina: 1