| OLD | NEW |
| 1 <!-- | 1 <!-- |
| 2 Copyright 2009, Google Inc. | 2 Copyright 2009, Google Inc. |
| 3 All rights reserved. | 3 All rights reserved. |
| 4 | 4 |
| 5 Redistribution and use in source and binary forms, with or without | 5 Redistribution and use in source and binary forms, with or without |
| 6 modification, are permitted provided that the following conditions are | 6 modification, are permitted provided that the following conditions are |
| 7 met: | 7 met: |
| 8 | 8 |
| 9 * Redistributions of source code must retain the above copyright | 9 * Redistributions of source code must retain the above copyright |
| 10 notice, this list of conditions and the following disclaimer. | 10 notice, this list of conditions and the following disclaimer. |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 /** | 209 /** |
| 210 * Removes any callbacks so they don't get called after the page has unloaded. | 210 * Removes any callbacks so they don't get called after the page has unloaded. |
| 211 */ | 211 */ |
| 212 function unload() { | 212 function unload() { |
| 213 if (g_client) { | 213 if (g_client) { |
| 214 g_client.cleanup(); | 214 g_client.cleanup(); |
| 215 } | 215 } |
| 216 } | 216 } |
| 217 </script> | 217 </script> |
| 218 </head> | 218 </head> |
| 219 <body style="width: 100%; height: 100%;"> | 219 <body style="width: 95%; height: 95%;"> |
| 220 <table style="width: 100%; height: 100%;"> | 220 <table style="width: 100%; height: 100%;"> |
| 221 <tr> | 221 <tr> |
| 222 <td> | 222 <td> |
| 223 <h1>Juggler</h1> | 223 <h1>Juggler</h1> |
| 224 <p> | 224 <p> |
| 225 This sample displays a juggling pattern computed entirely in a shader. | 225 This sample displays a juggling pattern computed entirely in a shader. |
| 226 <form name="the_form"> | 226 <form name="the_form"> |
| 227 <input type="radio" name="radio_group" value="3" | 227 <input type="radio" name="radio_group" value="3" |
| 228 onclick=updateNum()>3 Balls | 228 onclick=updateNum()>3 Balls |
| 229 <input type="radio" name="radio_group" value="5" checked | 229 <input type="radio" name="radio_group" value="5" |
| 230 onclick=updateNum()>5 Balls | 230 onclick=updateNum()>5 Balls |
| 231 <input type="radio" name="radio_group" value="7" | 231 <input type="radio" name="radio_group" value="7" |
| 232 onclick=updateNum()>7 Balls | 232 onclick=updateNum()>7 Balls |
| 233 <input type="radio" name="radio_group" value="9" | 233 <input type="radio" name="radio_group" value="9" |
| 234 onclick=updateNum()>9 Balls | 234 onclick=updateNum()>9 Balls |
| 235 <input type="radio" name="radio_group" value="11" checked |
| 236 onclick=updateNum()>11 Balls |
| 237 <input type="radio" name="radio_group" value="13" |
| 238 onclick=updateNum()>13 Balls |
| 239 <input type="radio" name="radio_group" value="15" |
| 240 onclick=updateNum()>15 Balls |
| 241 <input type="radio" name="radio_group" value="17" |
| 242 onclick=updateNum()>17 Balls |
| 235 <input type="checkbox" name="check_box" checked | 243 <input type="checkbox" name="check_box" checked |
| 236 onclick=toggleRenderCallback()>Animate | 244 onclick=toggleRenderCallback()>Animate |
| 237 </form> | 245 </form> |
| 238 </p> | 246 </p> |
| 239 <table id="container" style="width: 100%; height: 80%;"> | 247 <table id="container" style="width: 100%; height: 80%;"> |
| 240 <tr> | 248 <tr> |
| 241 <td height="100%"> | 249 <td height="100%"> |
| 242 <!-- Start of g_o3d plugin --> | 250 <!-- Start of g_o3d plugin --> |
| 243 <div id="o3d" style="width: 100%; height: 100%;"></div> | 251 <div id="o3d" style="width: 100%; height: 100%;"></div> |
| 244 <!-- End of g_o3d plugin --> | 252 <!-- End of g_o3d plugin --> |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 output.color = float4(1, 1, 1, 1); | 287 output.color = float4(1, 1, 1, 1); |
| 280 | 288 |
| 281 return output; | 289 return output; |
| 282 } | 290 } |
| 283 | 291 |
| 284 float length_2(in float2 v) { | 292 float length_2(in float2 v) { |
| 285 return dot(v, v); | 293 return dot(v, v); |
| 286 } | 294 } |
| 287 | 295 |
| 288 // Draw the balls in a single arc. | 296 // Draw the balls in a single arc. |
| 297 // Returns 1 if the pixel is within a ball, 0 if it isn't, and a value in |
| 298 // between for pixels right on the edge, for antialiasing. |
| 289 float drawBallsInArc(in float pi, | 299 float drawBallsInArc(in float pi, |
| 290 in float4 offset, | 300 in float4 offset, |
| 291 in float2 source_hand, | 301 in float2 source_hand, |
| 292 in float2 dest_hand, | 302 in float2 dest_hand, |
| 293 in float height_factor, | 303 in float height_factor, |
| 294 in float baseline, | 304 in float baseline, |
| 295 in float ball_radius_2, | 305 in float ball_radius_2, |
| 296 in float hand_throw_offset, | 306 in float hand_throw_offset, |
| 297 in float2 Z, | 307 in float2 Z, |
| 298 in float threshold) { | 308 in float threshold) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 311 // So (num - 1) is the length of time a parabola takes. | 321 // So (num - 1) is the length of time a parabola takes. |
| 312 | 322 |
| 313 float4 time = fmod(theta / pi + offset, (num - 1)) / (num - 1); | 323 float4 time = fmod(theta / pi + offset, (num - 1)) / (num - 1); |
| 314 float dx = dest_hand.x - source_hand.x; | 324 float dx = dest_hand.x - source_hand.x; |
| 315 float4 x = time * dx + source_hand.x - hand_throw_offset; | 325 float4 x = time * dx + source_hand.x - hand_throw_offset; |
| 316 float4 y = time * (1 - time); | 326 float4 y = time * (1 - time); |
| 317 y = y * height_factor + baseline; | 327 y = y * height_factor + baseline; |
| 318 float4 ZX = Z.x; | 328 float4 ZX = Z.x; |
| 319 float4 ZY = Z.y; | 329 float4 ZY = Z.y; |
| 320 float4 len_2 = (ZX - x) * (ZX - x) + (ZY - y) * (ZY - y); | 330 float4 len_2 = (ZX - x) * (ZX - x) + (ZY - y) * (ZY - y); |
| 331 |
| 332 // This antialiasing fuzzes the balls just a bit larger than they would |
| 333 // otherwise be. |
| 321 float4 temp = clamp((len_2 - ball_radius_2) / threshold, 0, 1); | 334 float4 temp = clamp((len_2 - ball_radius_2) / threshold, 0, 1); |
| 322 | 335 |
| 323 // One minus the product of all entries in temp. | 336 // One minus the product of all entries in temp. |
| 324 temp.xy = temp.xy * temp.zw; | 337 temp.xy = temp.xy * temp.zw; |
| 325 return 1 - temp.x * temp.y; | 338 return 1 - temp.x * temp.y; |
| 326 } | 339 } |
| 327 | 340 |
| 328 float drawAirborneBalls(in float pi, | 341 float4 drawAirborneBalls(in float pi, |
| 329 in float4 offset, | 342 in float4 offset, |
| 330 in float2 right_hand, | 343 in float2 right_hand, |
| 331 in float2 left_hand, | 344 in float2 left_hand, |
| 332 in float height_factor, | 345 in float height_factor, |
| 333 in float baseline, | 346 in float baseline, |
| 334 in float ball_radius_2, | 347 in float ball_radius_2, |
| 335 in float hand_swing_radius, | 348 in float hand_swing_radius, |
| 336 in float2 Z, | 349 in float2 Z, |
| 337 in float threshold) { | 350 in float threshold) { |
| 338 // The expression below is one minus a product. The first factor in the | 351 float value = |
| 339 // product is responsible for balls moving from right to left, and the second | 352 // balls going right to left |
| 340 // factor is responsible for balls moving from left to right. | 353 (drawBallsInArc(pi, offset, right_hand, left_hand, height_factor, |
| 341 return 1 - | 354 baseline, ball_radius_2, hand_swing_radius, Z, threshold) + |
| 342 (1 - drawBallsInArc(pi, offset, right_hand, left_hand, height_factor, | 355 // balls going left to right |
| 343 baseline, ball_radius_2, hand_swing_radius, Z, threshold)) * | 356 drawBallsInArc(pi, offset + 1, left_hand, right_hand, height_factor, |
| 344 (1 - drawBallsInArc(pi, offset + 1, left_hand, right_hand, height_factor, | 357 baseline, ball_radius_2, -hand_swing_radius, Z, threshold)); |
| 345 baseline, ball_radius_2, -hand_swing_radius, Z, threshold)); | 358 return float4(value, value, value, value); |
| 346 } | 359 } |
| 347 | 360 |
| 348 /** | 361 /** |
| 349 * pixelShaderMain - pixel shader | 362 * pixelShaderMain - pixel shader |
| 350 */ | 363 */ |
| 351 | 364 |
| 352 float4 pixelShaderMain(PixelShaderInput input) : COLOR { | 365 float4 pixelShaderMain(PixelShaderInput input) : COLOR { |
| 353 const float pi = 3.14159265; | 366 const float pi = 3.14159265; |
| 354 const float baseline = -1.2; | 367 const float baseline = -1.4; |
| 355 const float2 right_hand = float2(0.8, baseline); | 368 const float2 right_hand = float2(0.8, baseline); |
| 356 const float2 left_hand = float2(-0.8, baseline); | 369 const float2 left_hand = float2(-0.8, baseline); |
| 357 const float hand_swing_radius = 0.3; | 370 const float hand_swing_radius = 0.25; |
| 358 const float hand_radius_2 = 0.15 * 0.15; | 371 const float hand_radius = 0.15; |
| 359 const float ball_radius_2 = 0.1 * 0.1; | 372 const float hand_radius_2 = hand_radius * hand_radius; |
| 373 const float ball_radius = 0.08; |
| 374 const float ball_radius_2 = ball_radius * ball_radius; |
| 360 | 375 |
| 361 const float4 ball_color = float4(1, 1, 1, 1); | |
| 362 const float4 right_hand_color = float4(1, 0, 0, 1); | 376 const float4 right_hand_color = float4(1, 0, 0, 1); |
| 363 const float4 left_hand_color = float4(0, 0, 1, 1); | 377 const float4 left_hand_color = float4(0, 0, 1, 1); |
| 364 const float4 background_color = float4(0, 0, 0, 0); | 378 const float4 background_color = float4(0, 0, 0, 0); |
| 365 | 379 |
| 366 const float threshold = 0.002; // Used in clamp for antialiasing. | 380 const float threshold = 0.002; // Used in clamp for antialiasing. |
| 367 | 381 |
| 368 float height_factor = num; | 382 float height_factor = num * 0.75; |
| 369 | 383 |
| 370 float2 Z = input.texCoord; | 384 float2 Z = input.texCoord; |
| 371 | 385 |
| 372 // Coerce to the range [0, 2 * Pi * num]. | 386 // Coerce to the range [0, 2 * Pi * num]. |
| 373 float2 r_h = hand_swing_radius * float2(-cos(theta), sin(theta)) + right_hand; | 387 float2 r_h = hand_swing_radius * float2(-cos(theta), sin(theta)) + right_hand; |
| 374 float2 l_h = hand_swing_radius * float2(-cos(theta), -sin(theta)) + left_hand; | 388 float2 l_h = hand_swing_radius * float2(-cos(theta), -sin(theta)) + left_hand; |
| 375 | 389 |
| 376 // Initialize color of pixel to background_color. Background color has an | 390 // Initialize color of pixel to background_color. Background color has an |
| 377 // alpha of 0. Color of objects each have alpha 1, so multiplying by | 391 // alpha of 0. Color of objects each have alpha 1, so multiplying by |
| 378 // (1-alpha) before adding the color ensures that nothing gets overdrawn. | 392 // (1-alpha) before adding the color ensures that nothing gets overdrawn. |
| 379 // It's kind of like a rudimentary z-buffer. | 393 // It's kind of like a rudimentary z-buffer. |
| 380 float4 result = background_color; | 394 float4 result = background_color; |
| 381 | 395 |
| 382 // Draw the hands. | 396 // Draw the hands. The antialiasing here fuzzes the hands just a little bit |
| 383 result += (1 - result.a) * ( | 397 // smaller than they would otherwise be. That's the opposite of what we do |
| 398 // for the balls, just because it happens to be cheaper here to do smaller and |
| 399 // cheaper in drawBallsInArc to do larger. |
| 400 result += |
| 384 clamp((hand_radius_2 - length_2(Z - r_h)) / threshold, 0, 1) * | 401 clamp((hand_radius_2 - length_2(Z - r_h)) / threshold, 0, 1) * |
| 385 (Z.y < r_h.y) * right_hand_color + | 402 (Z.y < r_h.y) * right_hand_color + |
| 386 clamp((hand_radius_2 - length_2(Z - l_h)) / threshold, 0, 1) * | 403 clamp((hand_radius_2 - length_2(Z - l_h)) / threshold, 0, 1) * |
| 387 (Z.y < l_h.y) * left_hand_color); | 404 (Z.y < l_h.y) * left_hand_color; |
| 388 | 405 |
| 389 // Draw the ball in the hand. There is always a ball in exactly one hand, and | 406 // Draw the ball in the hand. There is always a ball in exactly one hand, and |
| 390 // which hand that is alternates. | 407 // which hand that is alternates. |
| 391 float2 hand; | 408 float2 hand; |
| 392 if (fmod(floor(theta / pi), 2) > 0.5) { | 409 if (fmod(floor(theta / pi), 2) > 0.5) { |
| 393 hand = r_h; | 410 hand = r_h; |
| 394 } else { | 411 } else { |
| 395 hand = l_h; | 412 hand = l_h; |
| 396 } | 413 } |
| 397 result += (1 - result.a) * ball_color * | 414 // The antialiasing here fuzzes the balls just a bit bigger than they would |
| 398 clamp((ball_radius_2 - length_2(Z - hand)) / threshold, 0, 1); | 415 // otherwise be. This is more work than making them smaller [the extra |
| 399 | 416 // subtraction in the "1 - clamp..." below], but inverting it in |
| 400 float4 offset = float4(0, 2, 4, 6); | 417 // drawBallsInArc would be more expensive, and they have to match so that the |
| 401 | 418 // balls are all the same size. |
| 402 // For each of up-to-4 pairs of balls you want to add, increment offsets by | 419 result += (1 - result.a) * |
| 403 // (8, 8, 8, 8) and call drawAirborneBalls again. | 420 (1 - clamp((length_2(Z - hand) - ball_radius_2) / threshold, 0, 1)); |
| 404 | 421 |
| 405 // Draw airborne balls. | 422 // Draw airborne balls. |
| 423 float4 offset = float4(0, 2, 4, 6); |
| 406 result += (1 - result.a) * drawAirborneBalls(pi, | 424 result += (1 - result.a) * drawAirborneBalls(pi, |
| 407 offset, | 425 offset, |
| 408 right_hand, | 426 right_hand, |
| 427 left_hand, |
| 428 height_factor, |
| 429 baseline, |
| 430 ball_radius_2, |
| 431 hand_swing_radius, |
| 432 Z, |
| 433 threshold); |
| 434 |
| 435 // For each up-to-4 pairs of balls you want to add, increment offset by |
| 436 // (8, 8, 8, 8) and call drawAirborneBalls again. |
| 437 offset += 8; |
| 438 result += (1 - result.a) * drawAirborneBalls(pi, |
| 439 offset, |
| 440 right_hand, |
| 409 left_hand, | 441 left_hand, |
| 410 height_factor, | 442 height_factor, |
| 411 baseline, | 443 baseline, |
| 412 ball_radius_2, | 444 ball_radius_2, |
| 413 hand_swing_radius, | 445 hand_swing_radius, |
| 414 Z, | 446 Z, |
| 415 threshold); | 447 threshold); |
| 416 | 448 |
| 417 return result; | 449 return result; |
| 418 } | 450 } |
| 419 | 451 |
| 420 // Here we tell our effect file *which* functions are | 452 // Here we tell our effect file *which* functions are |
| 421 // our vertex and pixel shaders. | 453 // our vertex and pixel shaders. |
| 422 | 454 |
| 423 // #o3d VertexShaderEntryPoint vertexShaderMain | 455 // #o3d VertexShaderEntryPoint vertexShaderMain |
| 424 // #o3d PixelShaderEntryPoint pixelShaderMain | 456 // #o3d PixelShaderEntryPoint pixelShaderMain |
| 425 // #o3d MatrixLoadOrder RowMajor | 457 // #o3d MatrixLoadOrder RowMajor |
| 426 </textarea> | 458 </textarea> |
| 427 </td> | 459 </td> |
| 428 </tr> | 460 </tr> |
| 429 </table> | 461 </table> |
| 430 </body> | 462 </body> |
| 431 </html> | 463 </html> |
| OLD | NEW |