Skip to content
Newer
Older
100644 339 lines (278 sloc) 8.76 KB
1829c80 @rygorous ktg Initial checkin
rygorous authored Apr 10, 2012
1 /****************************************************************************/
2 /*** ***/
b04d9b5 @rygorous ktg: Licensed as PD
rygorous authored Apr 10, 2012
3 /*** Written by Fabian Giesen. ***/
4 /*** I hereby place this code in the public domain. ***/
1829c80 @rygorous ktg Initial checkin
rygorous authored Apr 11, 2012
5 /*** ***/
6 /****************************************************************************/
7
8 #include <stdio.h>
9 #include "gentexture.hpp"
10
5d4f081 @fdb Add support for compiling KTG on Mac OS X.
fdb authored Apr 16, 2012
11 #ifdef _WIN32
12 #pragma comment(lib,"winmm.lib")
13 #include <windows.h>
14 #else
15 #include <sys/time.h>
16 static long timeGetTime()
17 {
18 timeval tim;
19 gettimeofday(&tim, NULL);
20 return tim.tv_sec * 1000000 + tim.tv_usec / 10;
21 }
22 static int timeBeginPeriod(unsigned int period)
23 {
24 return 0;
25 }
26 static int timeEndPeriod(unsigned int period)
27 {
28 return 0;
29 }
30 #endif
1829c80 @rygorous ktg Initial checkin
rygorous authored Apr 11, 2012
31
32 // 4x4 matrix multiply
33 static void MatMult(Matrix44 &dest,const Matrix44 &a,const Matrix44 &b)
34 {
35 for(sInt i=0;i<4;i++)
36 for(sInt j=0;j<4;j++)
37 dest[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]*b[3][j];
38 }
39
40 // Create a scaling matrix
41 static void MatScale(Matrix44 &dest,sF32 sx,sF32 sy,sF32 sz)
42 {
43 sSetMem(dest,0,sizeof(dest));
44 dest[0][0] = sx;
45 dest[1][1] = sy;
46 dest[2][2] = sz;
47 dest[3][3] = 1.0f;
48 }
49
50 // Create a translation matrix
51 static void MatTranslate(Matrix44 &dest,sF32 tx,sF32 ty,sF32 tz)
52 {
53 MatScale(dest,1.0f,1.0f,1.0f);
54 dest[3][0] = tx;
55 dest[3][1] = ty;
56 dest[3][2] = tz;
57 }
58
59 // Create a z-axis rotation matrix
60 static void MatRotateZ(Matrix44 &dest,sF32 angle)
61 {
62 sF32 s = sFSin(angle);
63 sF32 c = sFCos(angle);
64
65 MatScale(dest,1.0f,1.0f,1.0f);
66 dest[0][0] = c;
67 dest[0][1] = s;
68 dest[1][0] = -s;
69 dest[1][1] = c;
70 }
71
72 // Create a simple linear gradient texture
73 // Input colors are 0xaarrggbb (not premultiplied!)
74 static GenTexture LinearGradient(sU32 startCol,sU32 endCol)
75 {
76 GenTexture tex;
77
78 tex.Init(2,1);
79 tex.Data[0].Init(startCol);
80 tex.Data[1].Init(endCol);
81
82 return tex;
83 }
84
85 // Create a pattern of randomly colored voronoi cells
86 static void RandomVoronoi(GenTexture &dest,const GenTexture &grad,sInt intensity,sInt maxCount,sF32 minDist)
87 {
88 sVERIFY(maxCount <= 256);
89 CellCenter centers[256];
90
91 // generate random center points
92 for(sInt i=0;i<maxCount;i++)
93 {
94 int intens = (rand() * intensity) / RAND_MAX;
95
96 centers[i].x = 1.0f * rand() / RAND_MAX;
97 centers[i].y = 1.0f * rand() / RAND_MAX;
98 centers[i].color.Init(intens,intens,intens,255);
99 }
100
101 // remove points too close together
102 sF32 minDistSq = minDist*minDist;
103 for(sInt i=1;i<maxCount;)
104 {
105 sF32 x = centers[i].x;
106 sF32 y = centers[i].y;
107
108 // try to find a point closer than minDist
109 sInt j;
110 for(j=0;j<i;j++)
111 {
112 sF32 dx = centers[j].x - x;
113 sF32 dy = centers[j].y - y;
114
115 if(dx < 0.0f) dx += 1.0f;
116 if(dy < 0.0f) dy += 1.0f;
117
118 dx = sMin(dx,1.0f-dx);
119 dy = sMin(dy,1.0f-dy);
120
121 if(dx*dx + dy*dy < minDistSq) // point is too close, stop
122 break;
123 }
124
125 if(j<i) // we found such a point
126 centers[i] = centers[--maxCount]; // remove this one
127 else // accept this one
128 i++;
129 }
130
131 // generate the image
132 dest.Cells(grad,centers,maxCount,0.0f,GenTexture::CellInner);
133 }
134
135 // Transforms a grayscale image to a colored one with a matrix transform
136 static void Colorize(GenTexture &img,sU32 startCol,sU32 endCol)
137 {
138 Matrix44 m;
139 Pixel s,e;
140
141 s.Init(startCol);
142 e.Init(endCol);
143
144 // calculate matrix
145 sSetMem(m,0,sizeof(m));
146 m[0][0] = (e.r - s.r) / 65535.0f;
147 m[1][1] = (e.g - s.g) / 65535.0f;
148 m[2][2] = (e.b - s.b) / 65535.0f;
149 m[3][3] = 1.0f;
150 m[0][3] = s.r / 65535.0f;
151 m[1][3] = s.g / 65535.0f;
152 m[2][3] = s.b / 65535.0f;
153
154 // transform
155 img.ColorMatrixTransform(img,m,sTRUE);
156 }
157
158 // Save an image as .TGA file
159 static bool SaveImage(GenTexture &img,const char *filename)
160 {
161 FILE *f = fopen(filename,"wb");
162 if(!f)
163 return false;
164
165 // prepare header
166 sU8 buffer[18];
167 sSetMem(buffer,0,sizeof(buffer));
168
169 buffer[ 2] = 2; // image type code 2 (RGB, uncompressed)
170 buffer[12] = img.XRes & 0xff; // width (low byte)
171 buffer[13] = img.XRes >> 8; // width (high byte)
172 buffer[14] = img.YRes & 0xff; // height (low byte)
173 buffer[15] = img.YRes >> 8; // height (high byte)
174 buffer[16] = 32; // pixel size (bits)
175
176 // write header
177 if(!fwrite(buffer,sizeof(buffer),1,f))
178 {
179 fclose(f);
180 return false;
181 }
182
183 // write image data
184 sU8 *lineBuf = new sU8[img.XRes*4];
185 for(sInt y=0;y<img.YRes;y++)
186 {
187 const Pixel *in = &img.Data[y*img.XRes];
188
189 // convert a line of pixels (as simple as possible - no gamma correction etc.)
190 for(sInt x=0;x<img.XRes;x++)
191 {
192 lineBuf[x*4+0] = in->b >> 8;
193 lineBuf[x*4+1] = in->g >> 8;
194 lineBuf[x*4+2] = in->r >> 8;
195 lineBuf[x*4+3] = in->a >> 8;
196
197 in++;
198 }
199
200 // write to file
201 if(!fwrite(lineBuf,img.XRes*4,1,f))
202 {
203 fclose(f);
204 return false;
205 }
206 }
207
208 fclose(f);
209 return true;
210 }
211
212 int main(int argc,char **argv)
213 {
214 // initialize generator
215 InitTexgen();
216
217 // colors
218 Pixel black,white;
219 black.Init(0,0,0,255);
220 white.Init(255,255,255,255);
221
222 timeBeginPeriod(1);
223 sInt startTime = timeGetTime();
224
225 for(sInt i=0;i<100;i++)
226 {
227 // create gradients
228 GenTexture gradBW = LinearGradient(0xff000000,0xffffffff);
229 GenTexture gradWB = LinearGradient(0xffffffff,0xff000000);
230 GenTexture gradWhite = LinearGradient(0xffffffff,0xffffffff);
231
232 // simple noise test texture
233 GenTexture noise;
234 noise.Init(256,256);
235 noise.Noise(gradBW,2,2,6,0.5f,123,GenTexture::NoiseDirect|GenTexture::NoiseBandlimit|GenTexture::NoiseNormalize);
236
237 /*// save test image
238 if(!SaveImage(noise,"noise.tga"))
239 {
240 printf("Couldn't write 'noise.tga'!\n");
241 return 1;
242 }*/
243
244 // 4 "random voronoi" textures with different minimum distances
245 GenTexture voro[4];
246 static sInt voroIntens[4] = { 37, 42, 37, 37 };
247 static sInt voroCount[4] = { 90, 132, 240, 255 };
248 static sF32 voroDist[4] = { 0.125f, 0.063f, 0.063f, 0.063f };
249
250 for(sInt i=0;i<4;i++)
251 {
252 voro[i].Init(256,256);
253 RandomVoronoi(voro[i],gradWhite,voroIntens[i],voroCount[i],voroDist[i]);
254 }
255
256 // linear combination of them
257 LinearInput inputs[4];
258 for(sInt i=0;i<4;i++)
259 {
260 inputs[i].Tex = &voro[i];
261 inputs[i].Weight = 1.5f;
262 inputs[i].UShift = 0.0f;
263 inputs[i].VShift = 0.0f;
264 inputs[i].FilterMode = GenTexture::WrapU|GenTexture::WrapV|GenTexture::FilterNearest;
265 }
266
267 GenTexture baseTex;
268 baseTex.Init(256,256);
269 baseTex.LinearCombine(black,0.0f,inputs,4);
270
271 // blur it
272 baseTex.Blur(baseTex,0.0074f,0.0074f,1,GenTexture::WrapU|GenTexture::WrapV);
273
274 // add a noise layer
275 GenTexture noiseLayer;
276 noiseLayer.Init(256,256);
277 noiseLayer.Noise(LinearGradient(0xff000000,0xff646464),4,4,5,0.995f,3,GenTexture::NoiseDirect|GenTexture::NoiseNormalize|GenTexture::NoiseBandlimit);
278
279 baseTex.Paste(baseTex,noiseLayer,0.0f,0.0f,1.0f,0.0f,0.0f,1.0f,GenTexture::CombineAdd,0);
280
281 // colorize it
282 Colorize(baseTex,0xff747d8e,0xfff1feff);
283
284 // Create transform matrix for grid pattern
285 Matrix44 m1,m2,m3;
286 MatTranslate(m1,-0.5f,-0.5f,0.0f);
287 MatScale(m2,3.0f * sSQRT2F,3.0f * sSQRT2F,1.0f);
288 MatMult(m3,m2,m1);
289 MatRotateZ(m1,0.125f * sPI2F);
290 MatMult(m2,m1,m3);
291 MatTranslate(m1,0.5f,0.5f,0.0f);
292 MatMult(m3,m1,m2);
293
294 // Grid pattern GlowRect
295 GenTexture rect1,rect1x,rect1n;
296 rect1.Init(256,256);
297 rect1.LinearCombine(black,1.0f,0,0); // black background
298 rect1.GlowRect(rect1,gradWB,0.5f,0.5f,0.41f,0.0f,0.0f,0.25f,0.7805f,0.64f);
299
300 rect1x.Init(256,256);
301 rect1x.CoordMatrixTransform(rect1,m3,GenTexture::WrapU|GenTexture::WrapV|GenTexture::FilterBilinear);
302
303 // Make a normalmap from it
304 rect1n.Init(256,256);
305 rect1n.Derive(rect1x,GenTexture::DeriveNormals,2.5f);
306
307 // Apply as bump map
308 GenTexture finalTex;
309 Pixel amb,diff;
310
311 finalTex.Init(256,256);
312 amb.Init(0xff101010);
313 diff.Init(0xffffffff);
314 finalTex.Bump(baseTex,rect1n,0,0,0.0f,0.0f,0.0f,-2.518f,0.719f,-3.10f,amb,diff,sTRUE);
315
316 // Second grid pattern GlowRect
317 GenTexture rect2,rect2x;
318 rect2.Init(256,256);
319 rect2.LinearCombine(white,1.0f,0,0); // white background
320 rect2.GlowRect(rect2,gradBW,0.5f,0.5f,0.36f,0.0f,0.0f,0.20f,0.8805f,0.74f);
321
322 rect2x.Init(256,256);
323 rect2x.CoordMatrixTransform(rect2,m3,GenTexture::WrapU|GenTexture::WrapV|GenTexture::FilterBilinear);
324
325 // Multiply it over
326 finalTex.Paste(finalTex,rect2x,0.0f,0.0f,1.0f,0.0f,0.0f,1.0f,GenTexture::CombineMultiply,0);
327 }
328
329 sInt totalTime = timeGetTime() - startTime;
330 timeEndPeriod(1);
331
332 printf("%d ms/tex\n",totalTime / 100);
333
334 /*SaveImage(baseTex,"baseTex.tga");
335 SaveImage(finalTex,"final.tga");*/
336
337 return 0;
b04d9b5 @rygorous ktg: Licensed as PD
rygorous authored Apr 11, 2012
338 }
Something went wrong with that request. Please try again.