Changeset 1092
- Timestamp:
- Nov 28, 2011, 2:58:55 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/test/tutorial/tut03.cpp
r1090 r1092 57 57 m_size.x = (m_size.x + 15) & ~15; 58 58 m_size.y = (m_size.y + 15) & ~15; 59 m_texel_settings = vec4( vec2(1.0, 1.0) / (vec2)m_size,60 vec2(0.5, 0.5) * (vec2)m_size);59 m_texel_settings = vec4(1.0, 1.0, 2.0, 2.0) / (vec4)m_size.xyxy(); 60 m_screen_settings = vec4(1.0, 1.0, 0.5, 0.5) * (vec4)m_size.xyxy(); 61 61 62 62 /* Window size decides the world aspect ratio. For instance, 640×480 … … 79 79 m_tmppixels = new u8vec4[m_size.x / 2 * m_size.y / 2]; 80 80 m_frame = -1; 81 m_slices = 4; 81 82 for (int i = 0; i < 4; i++) 82 83 { … … 97 98 m_radius = 5.0; 98 99 m_ready = false; 100 m_drag = false; 99 101 100 102 m_palette = new u8vec4[(MAX_ITERATIONS + 1) * PALETTE_STEP]; … … 158 160 } 159 161 160 inline f64cmplx TexelToWorldOffset( ivec2 texel)162 inline f64cmplx TexelToWorldOffset(vec2 texel) 161 163 { 162 164 double dx = (0.5 + texel.x - m_size.x / 2) * m_texel2world.x; … … 165 167 } 166 168 167 inline f64cmplx ScreenToWorldOffset( ivec2 pixel)169 inline f64cmplx ScreenToWorldOffset(vec2 pixel) 168 170 { 169 171 /* No 0.5 offset here, because we want to be able to position the … … 187 189 if (buttons[1]) 188 190 { 189 if (clicked[1]) 191 if (!m_drag) 192 { 190 193 m_oldmouse = mousepos; 194 m_drag = true; 195 } 191 196 m_translate = ScreenToWorldOffset(m_oldmouse) 192 197 - ScreenToWorldOffset(mousepos); 198 /* XXX: the purpose of this hack is to avoid translating by 199 * an exact number of pixels. If this were to happen, the step() 200 * optimisation for i915 cards in our shader would behave 201 * incorrectly because a quarter of the pixels in the image 202 * would have tie rankings in the distance calculation. */ 203 m_translate *= 1023.0 / 1024.0; 193 204 m_oldmouse = mousepos; 194 205 } 195 else if (m_translate != 0.0) 196 { 197 m_translate *= pow(2.0, -deltams * 0.005); 198 if (m_translate.norm() / m_radius < 1e-4) 199 m_translate = 0.0; 206 else 207 { 208 m_drag = false; 209 if (m_translate != 0.0) 210 { 211 m_translate *= pow(2.0, -deltams * 0.005); 212 if (m_translate.norm() / m_radius < 1e-4) 213 m_translate = 0.0; 214 } 200 215 } 201 216 … … 210 225 { 211 226 m_zoom_speed *= pow(2.0, -deltams * 0.005); 212 if (abs(m_zoom_speed) < 1e-5 )227 if (abs(m_zoom_speed) < 1e-5 || m_drag) 213 228 m_zoom_speed = 0.0; 214 229 } … … 287 302 #endif 288 303 289 u8vec4 *m_pixelstart = m_pixels + m_size.x * m_size.y / 4 * m_frame;290 291 304 if (m_dirty[m_frame]) 292 305 { 293 double const maxsqlen = 1024;294 double const k1 = 1.0 / (1 << 10) / log2(maxsqlen);295 296 306 m_dirty[m_frame]--; 297 307 298 for (int j = ((m_frame + 1) % 4) / 2; j < m_size.y; j += 2) 299 for (int i = m_frame % 2; i < m_size.x; i += 2) 300 { 301 302 f64cmplx z0 = m_center + TexelToWorldOffset(ivec2(i, j)); 303 f64cmplx r0 = z0; 304 //f64cmplx r0(0.28693186889504513, 0.014286693904085048); 305 //f64cmplx r0(0.001643721971153, 0.822467633298876); 306 //f64cmplx r0(-1.207205434596, 0.315432814901); 307 //f64cmplx r0(-0.79192956889854, -0.14632423080102); 308 //f64cmplx r0(0.3245046418497685, 0.04855101129280834); 309 f64cmplx z; 310 int iter = MAX_ITERATIONS; 311 for (z = z0; iter && z.sqlen() < maxsqlen; z = z * z + r0) 312 --iter; 313 314 if (iter) 315 { 316 double f = iter; 317 double n = z.sqlen(); 318 if (n > maxsqlen * maxsqlen) 319 n = maxsqlen * maxsqlen; 320 321 /* Approximate log(sqrt(n))/log(sqrt(maxsqlen)) */ 322 union { double n; uint64_t x; } u = { n }; 323 double k = (u.x >> 42) - (((1 << 10) - 1) << 10); 324 k *= k1; 325 326 /* Approximate log2(k) in [1,2]. */ 327 f += (- 0.344847817623168308695977510213252644185 * k 328 + 2.024664188044341212602376988171727038739) * k 329 - 1.674876738008591047163498125918330313237; 330 331 *m_pixelstart++ = m_palette[(int)(f * PALETTE_STEP)]; 332 } 333 else 334 { 335 *m_pixelstart++ = u8vec4(0, 0, 0, 255); 336 } 308 /* FIXME: this is the ugliest, most pathetic excuse for a 309 * threading system that I have seen in a while. */ 310 DoWorkHelper helpers[m_slices]; 311 for (int slice = 0; slice < m_slices; slice++) 312 { 313 helpers[slice].fractal = this; 314 helpers[slice].slice = slice; 315 helpers[slice].thread = new Thread(DoWorkHelper::Help, 316 &helpers[slice]); 317 } 318 for (int slice = 0; slice < m_slices; slice++) 319 { 320 delete helpers[slice].thread; 321 } 322 } 323 } 324 325 struct DoWorkHelper 326 { 327 Fractal *fractal; 328 Thread *thread; 329 int slice; 330 331 static void *Help(void *data) 332 { 333 DoWorkHelper *helper = (DoWorkHelper *)data; 334 helper->fractal->DoWork(helper->slice); 335 return NULL; 336 } 337 }; 338 339 void DoWork(int slice) 340 { 341 double const maxsqlen = 1024; 342 double const k1 = 1.0 / (1 << 10) / log2(maxsqlen); 343 344 int jmin = m_size.y * slice / m_slices; 345 int jmax = m_size.y * (slice + 1) / m_slices; 346 u8vec4 *m_pixelstart = m_pixels 347 + m_size.x * (m_size.y / 4 * m_frame + jmin / 4); 348 349 for (int j = ((m_frame + 1) % 4) / 2 + jmin; j < jmax; j += 2) 350 for (int i = m_frame % 2; i < m_size.x; i += 2) 351 { 352 f64cmplx z0 = m_center + TexelToWorldOffset(ivec2(i, j)); 353 f64cmplx r0 = z0; 354 //f64cmplx r0(0.28693186889504513, 0.014286693904085048); 355 //f64cmplx r0(0.001643721971153, 0.822467633298876); 356 //f64cmplx r0(-1.207205434596, 0.315432814901); 357 //f64cmplx r0(-0.79192956889854, -0.14632423080102); 358 //f64cmplx r0(0.3245046418497685, 0.04855101129280834); 359 f64cmplx z; 360 int iter = MAX_ITERATIONS; 361 for (z = z0; iter && z.sqlen() < maxsqlen; z = z * z + r0) 362 --iter; 363 364 if (iter) 365 { 366 double f = iter; 367 double n = z.sqlen(); 368 if (n > maxsqlen * maxsqlen) 369 n = maxsqlen * maxsqlen; 370 371 /* Approximate log(sqrt(n))/log(sqrt(maxsqlen)) */ 372 union { double n; uint64_t x; } u = { n }; 373 double k = (u.x >> 42) - (((1 << 10) - 1) << 10); 374 k *= k1; 375 376 /* Approximate log2(k) in [1,2]. */ 377 f += (- 0.344847817623168308695977510213252644185 * k 378 + 2.024664188044341212602376988171727038739) * k 379 - 1.674876738008591047163498125918330313237; 380 381 *m_pixelstart++ = m_palette[(int)(f * PALETTE_STEP)]; 382 } 383 else 384 { 385 *m_pixelstart++ = u8vec4(0, 0, 0, 255); 337 386 } 338 387 } … … 391 440 "uniform mat4 u_ZoomSettings;" 392 441 "uniform vec4 u_TexelSize;" 442 "uniform vec4 u_ScreenSize;" 393 443 "" 394 444 "attribute vec2 a_TexCoord;" … … 419 469 " u_ZoomSettings[2][1]," 420 470 " u_ZoomSettings[3][1]);" 421 /* Pass all this to the fragment shader */422 471 " v_CenterX = zoomscale * a_TexCoord.x + zoomtx" 423 472 " + offsets.xyxy * u_TexelSize.x;" … … 428 477 * this value. We add or remove a slight offset to avoid 429 478 * rounding issues at the image's edges. */ 430 " v_IndexX = v_CenterX * u_ TexelSize.z - offsets.zwzw;"431 " v_IndexY = v_CenterY * u_ TexelSize.w - offsets.zwwz;"479 " v_IndexX = v_CenterX * u_ScreenSize.z - (offsets.zwzw + vec4(0.001, 0.002, 0.003, 0.004));" 480 " v_IndexY = v_CenterY * u_ScreenSize.w - (offsets.zwwz + vec4(0.0015, 0.0025, 0.0035, 0.0045));" 432 481 "}", 433 482 … … 445 494 "void main(void)" 446 495 "{" 496 " vec4 v05 = vec4(0.5, 0.5, 0.5, 0.5);" 497 " vec4 rx, ry, t0, dx, dy, dd;" 447 498 /* Get a pixel coordinate from each slice into rx & ry */ 448 " vec4 rx = u_TexelSize.x * (1.0 + 2.0 * floor(v_IndexX));" 449 " vec4 ry = u_TexelSize.y * (1.0 + 2.0 * floor(v_IndexY));" 450 /* Compute distance to expected pixel in dd */ 451 " vec4 v05 = vec4(0.5, 0.5, 0.5, 0.5);" 452 " vec4 t0 = step(abs(rx - v05), v05)" 453 " * step(abs(ry - v05), v05);" 454 " vec4 dx = rx - v_CenterX;" 455 " vec4 dy = ry - v_CenterY;" 499 " rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX);" 500 " ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY);" 501 /* Compute inverse distance to expected pixel in dd, 502 * and put zero if we fall outside the texture. */ 503 " t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05);" 504 " dx = rx - v_CenterX;" 505 " dy = ry - v_CenterY;" 456 506 //" vec4 dd = t0 * (abs(dx) + abs(dy));" 457 507 //" vec4 dd = t0 / (0.001 + sqrt((dx * dx) + (dy * dy)));" 458 " vec4dd = t0 / (0.000001 + (dx * dx) + (dy * dy));"508 " dd = t0 / (0.000001 + (dx * dx) + (dy * dy));" 459 509 /* Modify Y coordinate to select proper quarter. */ 460 510 " ry = ry * 0.25 + vec4(0.0, 0.25, 0.5, 0.75);" 461 511 "" 462 512 #if 1 463 /* Put min(.x,.y) in .x and min(.z,.w) in .z */ 464 " vec4 t1 = step(dd, dd.yyww);" 465 " rx = mix(rx, rx.yyww, t1);" 466 " ry = mix(ry, ry.yyww, t1);" 467 " dd = mix(dd, dd.yyww, t1);" 468 /* Put min(x,z) in x */ 469 " vec4 t2 = step(dd, dd.zzzz);" 470 " rx = mix(rx, rx.zzzz, t2);" 471 " ry = mix(ry, ry.zzzz, t2);" 513 "\n#if 0\n" /* XXX: disabled until we can autodetect i915 */ 514 /* t1.x <-- dd.x > dd.y */ 515 /* t1.y <-- dd.z > dd.w */ 516 " vec2 t1 = step(dd.xz, dd.yw);" 517 /* ret.x <-- max(rx.x, rx.y) wrt. t1.x */ 518 /* ret.y <-- max(rx.z, rx.w) wrt. t1.y */ 519 /* ret.z <-- max(ry.x, ry.y) wrt. t1.x */ 520 /* ret.w <-- max(ry.z, ry.w) wrt. t1.y */ 521 " vec4 ret = mix(vec4(rx.xz, ry.xz)," 522 " vec4(rx.yw, ry.yw), t1.xyxy);" 523 /* dd.x <-- max(dd.x, dd.y) */ 524 /* dd.z <-- max(dd.z, dd.w) */ 525 " dd.xy = mix(dd.xz, dd.yw, t1);" 526 /* t2 <-- dd.x > dd.z */ 527 " float t2 = step(dd.x, dd.y);" 528 /* ret.x <-- max(ret.x, ret.y); */ 529 /* ret.y <-- max(ret.z, ret.yw; */ 530 " ret.xy = mix(ret.xz, ret.yw, t2);" 531 "\n#else\n" 532 /* Fallback for i915 cards -- the trick to reduce the 533 * number of operations is to compute both step(a,b) 534 * and step(b,a) and hope that their sum is 1. This is 535 * almost always the case, and when it isn't we can 536 * afford to have a few wrong pixels. However, a real 537 * problem is when panning the image, because half the 538 * screen is likely to flicker. To avoid this problem, 539 * we cheat a little (see m_translate comment above). */ 540 " vec4 t1 = step(dd.xzyw, dd.ywxz);" 541 " vec4 ret = vec4(rx.xz, ry.xz) * t1.zwzw" 542 " + vec4(rx.yw, ry.yw) * t1.xyxy;" 543 " dd.xy = dd.xz * t1.zw + dd.yw * t1.xy;" 544 " vec2 t2 = step(dd.xy, dd.yx);" 545 " ret.xy = ret.xz * t2.yy + ret.yw * t2.xx;" 546 "\n#endif\n" 472 547 /* Nearest neighbour */ 473 " gl_FragColor = texture2D(in_Texture, vec2(rx.x, ry.x));"548 " gl_FragColor = texture2D(in_Texture, ret.xy);" 474 549 #else 475 550 /* Alternate version: some kind of linear interpolation */ … … 546 621 m_texattrib = m_shader->GetAttribLocation("a_TexCoord"); 547 622 m_texeluni = m_shader->GetUniformLocation("u_TexelSize"); 623 m_screenuni = m_shader->GetUniformLocation("u_ScreenSize"); 548 624 m_zoomuni = m_shader->GetUniformLocation("u_ZoomSettings"); 549 625 m_ready = true; … … 592 668 m_shader->Bind(); 593 669 m_shader->SetUniform(m_texeluni, m_texel_settings); 670 m_shader->SetUniform(m_screenuni, m_screen_settings); 594 671 m_shader->SetUniform(m_zoomuni, m_zoom_settings); 595 672 #if !defined __CELLOS_LV2__ && !defined __ANDROID__ … … 642 719 GLuint m_tco; 643 720 #endif 644 int m_vertexattrib, m_texattrib, m_texeluni, m_ zoomuni;645 int m_frame, m_ dirty[4];646 bool m_ready ;721 int m_vertexattrib, m_texattrib, m_texeluni, m_screenuni, m_zoomuni; 722 int m_frame, m_slices, m_dirty[4]; 723 bool m_ready, m_drag; 647 724 648 725 f64cmplx m_center, m_translate; 649 726 double m_zoom_speed, m_radius; 650 vec4 m_texel_settings ;727 vec4 m_texel_settings, m_screen_settings; 651 728 mat4 m_zoom_settings; 652 729 f64cmplx m_deltashift[4];
Note: See TracChangeset
for help on using the changeset viewer.