├── README.md └── skydome.c /README.md: -------------------------------------------------------------------------------- 1 | Skydome 2 | ======= 3 | 4 | An Analytic Model for Full Spectral Sky-Dome Radiance(http://cgg.mff.cuni.cz/projects/SkylightModelling/) 5 | にあったソースコードを使ってHDR形式で出力するプログラム。上のソースコードと一緒にコンパイル、リンクすると使える。 6 | C99対応コンパイラが必要。 7 | 8 | ・使い方 9 | 10 | skydome ファイル名 幅 高さ 濁度 地面のアルベド値 太陽と地面の角度 11 | 12 | などとする。 -------------------------------------------------------------------------------- /skydome.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "ArHosekSkyModel.h" 7 | 8 | typedef struct RawImage_ { 9 | double r, g, b; 10 | } RawImage; 11 | 12 | void conv(RawImage* pixel, unsigned char* out) { 13 | float d; 14 | int e; 15 | d = pixel->r > pixel->g ? pixel->r : pixel->g; 16 | if (pixel->b > d) d = pixel->b; 17 | 18 | if (d <= 1e-32) { 19 | out[0] = out[1] = out[2] = 0; 20 | out[3] = 0; 21 | return; 22 | } 23 | 24 | float m = frexp(d, &e); // d = m * 2^e 25 | d = m * 256.0 / d; 26 | 27 | out[0] = pixel->r * d; 28 | out[1] = pixel->g * d; 29 | out[2] = pixel->b * d; 30 | out[3] = (e + 128); 31 | } 32 | 33 | 34 | void saveHDRfile(char *filename, RawImage *imgdata, int width, int height) { 35 | FILE *fp = fopen(filename, "wb"); 36 | if (fp == NULL) { 37 | printf("Error: %s", filename); 38 | return; 39 | } 40 | 41 | unsigned char ret = 0x0a; 42 | // Header 43 | fprintf(fp, "#?RADIANCE%c", (unsigned char)ret); 44 | fprintf(fp, "# Made with 100%% pure HDR Shop%c", ret); 45 | fprintf(fp, "FORMAT=32-bit_rle_rgbe%c", ret); 46 | fprintf(fp, "EXPOSURE= 1.0000000000000%c%c", ret, ret); 47 | 48 | // Data 49 | fprintf(fp, "-Y %d +X %d%c", height, width, ret); 50 | for (int i = height - 1; i >= 0; i --) { 51 | 52 | unsigned char buf[width * 4]; 53 | for (int j = 0; j < width; j ++) { 54 | conv(&imgdata[i * width + j], &buf[j * 4]); 55 | } 56 | 57 | fprintf(fp, "%c%c", 0x02, 0x02); 58 | fprintf(fp, "%c%c", (width >> 8) & 0xFF, width & 0xFF); 59 | 60 | for (int j = 0; j < 4; j ++) { 61 | int cursor = 0; 62 | for (;;) { 63 | int w = width - cursor; 64 | if (w >= 128) 65 | w = 127; 66 | fprintf(fp, "%c", w); 67 | for (int idx = cursor; idx < cursor + w; idx ++) 68 | fprintf(fp, "%c", buf[idx * 4 + j]); 69 | cursor += w; 70 | if (cursor >= width) 71 | break; 72 | } 73 | } 74 | } 75 | 76 | fclose(fp); 77 | } 78 | 79 | // tekito converter 80 | void xyz2rgb(double* xyz, double* rgb) { 81 | double X = xyz[0]; 82 | double Y = xyz[1]; 83 | double Z = xyz[2]; 84 | rgb[0] = 3.2410*X - 1.5374*Y - 0.4986*Z; 85 | rgb[1] = -0.9692*X + 1.8760*Y + 0.0416*Z; 86 | rgb[2] = 0.0556*X - 0.2040*Y + 1.5070*Z; 87 | } 88 | 89 | // 90 | // skydome filename width height turbidity albedo solarElevation 91 | // 92 | int main(int argc, char **argv) { 93 | ArHosekXYZSkyModelState *skymodel_state; 94 | if (argc < 7) 95 | return 0; 96 | 97 | int width = atof(argv[2]); 98 | int height = atof(argv[3]); 99 | double turbidity = atof(argv[4]); 100 | double albedo = atof(argv[5]); 101 | double solarElevation = atof(argv[6]); 102 | RawImage *img = (RawImage*)malloc(sizeof(RawImage) * width * height); 103 | skymodel_state = arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, solarElevation); 104 | 105 | 106 | for (int y = 0; y < height; y ++) { 107 | for (int x = 0; x < width; x ++) { 108 | double PI = 3.14159265359; 109 | 110 | int cx = width / 2; 111 | int cy = height / 2; 112 | int rx = (x - cx); 113 | int ry = (y - cy); 114 | 115 | double nr = sqrt(rx*rx + ry*ry) / (width / 2.0); 116 | double th = nr * 0.5 * PI; 117 | double ph = atan2(rx, ry); 118 | 119 | double gamma = acos(cos(solarElevation) * sin(th) * sin(ph) + sin(solarElevation) * cos(th)); 120 | double theta = th; 121 | 122 | if (nr < width / 2.0) { 123 | double xyz[3]; 124 | double rgb[3]; 125 | 126 | for (int i = 0; i < 3; i ++) { 127 | xyz[i] = arhosek_xyz_skymodel_radiance(skymodel_state, theta, gamma, i); 128 | } 129 | xyz2rgb(xyz, rgb); 130 | 131 | img[y * width + x].r = rgb[0]; 132 | img[y * width + x].g = rgb[1]; 133 | img[y * width + x].b = rgb[2]; 134 | } else { 135 | img[y * width + x].r = 0; 136 | img[y * width + x].g = 0; 137 | img[y * width + x].b = 0; 138 | } 139 | } 140 | } 141 | 142 | arhosek_xyz_skymodelstate_free(skymodel_state); 143 | 144 | 145 | // save 146 | saveHDRfile(argv[1], img, width, height); 147 | free(img); 148 | 149 | return 0; 150 | } 151 | --------------------------------------------------------------------------------