1 /*{# Copyright (c) 2010-2012 Turbulenz Limited #}*/ 2 ; 3 4 /* 5 * @title: Immediate rendering 6 * @description: 7 * This sample demonstrates how to use the low level API of the Turbulenz graphics device. 8 * It shows how to load shaders, change techniques, and how to create and dispatch dynamic index and vertex buffers 9 * to render simple 2D animations. 10 */ 11 /*{{ javascript("jslib/camera.js") }}*/ 12 /*{{ javascript("jslib/observer.js") }}*/ 13 /*{{ javascript("jslib/utilities.js") }}*/ 14 /*{{ javascript("jslib/requesthandler.js") }}*/ 15 /*{{ javascript("jslib/services/turbulenzservices.js") }}*/ 16 /*{{ javascript("jslib/services/turbulenzbridge.js") }}*/ 17 /*{{ javascript("jslib/services/gamesession.js") }}*/ 18 /*{{ javascript("jslib/services/mappingtable.js") }}*/ 19 /*global RequestHandler: false */ 20 /*global TurbulenzEngine: false */ 21 /*global TurbulenzServices: false */ 22 /*global Camera: false */ 23 TurbulenzEngine.onload = function onloadFn() { 24 var errorCallback = function errorCallback(msg) { 25 window.alert(msg); 26 }; 27 28 // Create the engine devices objects 29 // This sample uses the 'graphicsDevice' to demonstrate different basic rendering techniques 30 var graphicsDeviceParameters = {}; 31 var graphicsDevice = TurbulenzEngine.createGraphicsDevice(graphicsDeviceParameters); 32 33 if (!graphicsDevice.shadingLanguageVersion) { 34 errorCallback("No shading language support detected.\nPlease check your graphics drivers are up to date."); 35 graphicsDevice = null; 36 return; 37 } 38 39 // Clear the background color of the engine window 40 var clearColor = [0.0, 0.0, 0.0, 1.0]; 41 if (graphicsDevice.beginFrame()) { 42 graphicsDevice.clear(clearColor); 43 graphicsDevice.endFrame(); 44 } 45 46 var mathDeviceParameters = {}; 47 var mathDevice = TurbulenzEngine.createMathDevice(mathDeviceParameters); 48 49 var requestHandlerParameters = {}; 50 var requestHandler = RequestHandler.create(requestHandlerParameters); 51 52 var camera = Camera.create(mathDevice); 53 var worldUp = mathDevice.v3BuildYAxis(); 54 camera.lookAt(mathDevice.v3Build(0, 0, -100), worldUp, mathDevice.v3Build(0, 4, 15.0)); 55 camera.updateViewMatrix(); 56 camera.updateProjectionMatrix(); 57 58 var aspectRatio = (graphicsDevice.width / graphicsDevice.height); 59 if (aspectRatio !== camera.aspectRatio) { 60 camera.aspectRatio = aspectRatio; 61 camera.updateProjectionMatrix(); 62 } 63 camera.updateViewProjectionMatrix(); 64 65 // Create techniqueParameters for each object 66 var techniqueParameters = graphicsDevice.createTechniqueParameters({ 67 worldViewProjection: camera.viewProjectionMatrix, 68 constantColor: [1.0, 0.0, 0.0, 0.5] 69 }); 70 var techniqueParametersProceduralTexture = graphicsDevice.createTechniqueParameters({ 71 worldViewProjection: camera.viewProjectionMatrix, 72 diffuse: null 73 }); 74 var techniqueParametersCrateTexture = graphicsDevice.createTechniqueParameters({ 75 worldViewProjection: camera.viewProjectionMatrix, 76 diffuse: null 77 }); 78 var techniqueParametersPoint = graphicsDevice.createTechniqueParameters({ 79 worldViewProjection: camera.viewProjectionMatrix, 80 constantColor: [1.0, 0.0, 0.0, 0.5], 81 pointSize: 1 82 }); 83 84 // Create semantics for specifing the vertices/colors/textureCoords 85 var semanticsTypes = { 86 position: null, 87 color: null, 88 positionAndTexture: null 89 }; 90 var vertexFormatTypes = { 91 position: undefined, 92 color: undefined, 93 positionAndTexture: undefined 94 }; 95 96 // Only the position 97 semanticsTypes.position = graphicsDevice.createSemantics([graphicsDevice.SEMANTIC_POSITION]); 98 vertexFormatTypes.position = [graphicsDevice.VERTEXFORMAT_FLOAT3]; 99 100 // Only the color (with alpha, rgba) 101 semanticsTypes.color = graphicsDevice.createSemantics([graphicsDevice.SEMANTIC_COLOR]); 102 vertexFormatTypes.color = [graphicsDevice.VERTEXFORMAT_FLOAT4]; 103 104 // Both position and texture coordinate 105 semanticsTypes.positionAndTexture = graphicsDevice.createSemantics([graphicsDevice.SEMANTIC_POSITION, graphicsDevice.SEMANTIC_TEXCOORD]); 106 vertexFormatTypes.positionAndTexture = [graphicsDevice.VERTEXFORMAT_FLOAT3, graphicsDevice.VERTEXFORMAT_SHORT2]; 107 108 var shader = null; 109 110 // Creation of render objects 111 // The grid, drawn as lines with a constant color 112 var gridRenderObject = { 113 techniqueName: "constantColor3D", 114 semanticName: "position", 115 primitive: graphicsDevice.PRIMITIVE_LINES, 116 numOfRenderItems: 5, 117 technique: null, 118 vertexFormats: null, 119 semantics: null, 120 techniqueParameters: null, 121 startPosition: [1.0, 1.0, 0.0], 122 color: [1.0, 0.0, 0.0, 0.5], 123 isInit: false, 124 accTime: 0, 125 animPeriod: 0.2, 126 animStep: 1, 127 maxNumOfRenderItems: 5, 128 update: function updateFn(delta) { 129 var numOfLevels = this.numOfRenderItems; 130 var maxNumOfRenderItems = this.maxNumOfRenderItems; 131 var animPeriod = this.animPeriod; 132 133 this.accTime += delta; 134 if (this.accTime > animPeriod) { 135 this.numOfRenderItems = (numOfLevels + this.animStep) % (maxNumOfRenderItems + 1); 136 this.accTime = 0; 137 } 138 }, 139 init: function initFn() { 140 // Initialise the references to semantics/vertexFormats 141 var semanticName = this.semanticName; 142 this.semantics = semanticsTypes[semanticName]; 143 this.vertexFormats = vertexFormatTypes[semanticName]; 144 this.techniqueParameters = techniqueParameters; 145 this.isInit = (this.semantics && this.vertexFormats && this.techniqueParameters); 146 }, 147 draw: function drawFn(graphicsDevice) { 148 var numOfLines = this.numOfRenderItems + 1; 149 var startX = this.startPosition[0]; 150 var startY = this.startPosition[1]; 151 var startZ = this.startPosition[2]; 152 153 var primitive = this.primitive; 154 var techniqueParameters = this.techniqueParameters; 155 var vertexFormats = this.vertexFormats; 156 var semantics = this.semantics; 157 158 if (this.isInit) { 159 // Shared techniqueParameters, so set the color 160 // This is the techniqueParameters to be used for this draw 161 techniqueParameters.constantColor = this.color; 162 graphicsDevice.setTechniqueParameters(techniqueParameters); 163 164 // Draw directly using a writer to populate the vertices 165 // In this case only positions of x,y,z are being written 166 var writer = graphicsDevice.beginDraw(primitive, numOfLines * 4, vertexFormats, semantics); 167 if (writer) { 168 var ns = numOfLines - 1; 169 for (var i = 0; i < numOfLines; i += 1) { 170 var xs = startX + i; 171 var ys = startY + i; 172 var xe = startX + ns; 173 var ye = startY + ns; 174 writer(xs, startY, startZ); 175 writer(xs, ye, startZ); 176 writer(startX, ys, startZ); 177 writer(xe, ys, startZ); 178 } 179 graphicsDevice.endDraw(writer); 180 } 181 } 182 } 183 }; 184 185 // The circle, drawn as points of a constant color 186 var circleRenderObject = { 187 techniqueName: "pointConstantColor3D", 188 semanticName: "position", 189 primitive: graphicsDevice.PRIMITIVE_POINTS, 190 numOfRenderItems: 1500, 191 technique: null, 192 vertexFormats: null, 193 semantics: null, 194 techniqueParameters: null, 195 startPosition: [10.0, 3.5, 0.0], 196 color: [0.0, 1.0, 0.0, 0.5], 197 radius: 2.5, 198 isInit: false, 199 init: function initFn() { 200 var semanticName = this.semanticName; 201 this.semantics = semanticsTypes[semanticName]; 202 this.vertexFormats = vertexFormatTypes[semanticName]; 203 this.techniqueParameters = techniqueParametersPoint; 204 this.isInit = (this.semantics && this.vertexFormats && this.techniqueParameters); 205 }, 206 draw: function drawFn(graphicsDevice) { 207 var numOfRenderItems = this.numOfRenderItems; 208 var startX = this.startPosition[0]; 209 var startY = this.startPosition[1]; 210 var startZ = this.startPosition[2]; 211 212 var primitive = this.primitive; 213 var vertexFormats = this.vertexFormats; 214 var semantics = this.semantics; 215 216 if (this.isInit) { 217 this.techniqueParameters.constantColor = this.color; 218 graphicsDevice.setTechniqueParameters(this.techniqueParameters); 219 220 // Draw using a writer to add only positions (x,y,z) 221 var writer = graphicsDevice.beginDraw(primitive, numOfRenderItems, vertexFormats, semantics); 222 if (writer) { 223 var sinfn = Math.sin; 224 var cosfn = Math.cos; 225 var random = Math.random; 226 227 var pi2 = 2 * Math.PI; 228 var inc = pi2 / 64; 229 230 var radius = this.radius; 231 var sin, cos, r; 232 233 for (var i = 0, t = 0; i < numOfRenderItems; i += 1) { 234 // Random positions are used to make the points clearer to visualise 235 r = radius * random(); 236 sin = sinfn(t); 237 cos = cosfn(t); 238 writer((r * sin) + startX, (r * cos) + startY, startZ); 239 t += inc; 240 if (t > pi2) { 241 t -= pi2; 242 } 243 } 244 245 graphicsDevice.endDraw(writer); 246 } 247 } 248 } 249 }; 250 251 // The spiral, drawn using a procedurally generated texture 252 var spiralRenderObject = { 253 techniqueName: "textured3D", 254 semanticName: "positionAndTexture", 255 primitive: graphicsDevice.PRIMITIVE_TRIANGLES, 256 numOfRenderItems: 17, 257 technique: null, 258 vertexFormats: null, 259 semantics: null, 260 techniqueParameters: null, 261 startPosition: [-4.5, 4.5, 0.0], 262 color: [1.0, 0.0, 1.0, 0.5], 263 scale: 0.5, 264 thetaInc: 0, 265 isInit: false, 266 accTime: 0, 267 animPeriod: 0.5, 268 animStep: 1, 269 maxNumOfRenderItems: 17, 270 update: function updateFn(delta) { 271 var maxNumOfRenderItems = this.maxNumOfRenderItems; 272 var animPeriod = this.animPeriod; 273 274 // Increase/decrease the number of iterations 275 this.accTime += delta; 276 if (this.accTime > animPeriod) { 277 this.numOfRenderItems += this.animStep; 278 if (this.numOfRenderItems < 1) { 279 this.numOfRenderItems = 1; 280 this.animStep *= -1; 281 } else if (this.numOfRenderItems > maxNumOfRenderItems) { 282 this.numOfRenderItems = maxNumOfRenderItems; 283 this.animStep *= -1; 284 } 285 this.accTime = 0; 286 } 287 }, 288 init: function initFn() { 289 var semanticName = this.semanticName; 290 this.semantics = semanticsTypes[semanticName]; 291 this.vertexFormats = vertexFormatTypes[semanticName]; 292 this.techniqueParameters = techniqueParametersProceduralTexture; 293 294 // Pre-calculate the theta amount to increase per step 295 this.thetaInc = (2 * Math.PI) / 16; 296 this.isInit = (this.semantics && this.vertexFormats && this.techniqueParameters); 297 }, 298 draw: function drawFn(graphicsDevice/*, delta */ ) { 299 var numOfRenderLevels = this.numOfRenderItems; 300 var startX = this.startPosition[0]; 301 var startY = this.startPosition[1]; 302 var startZ = this.startPosition[2]; 303 304 var primitive = this.primitive; 305 var techniqueParameters = this.techniqueParameters; 306 var vertexFormats = this.vertexFormats; 307 var semantics = this.semantics; 308 309 var scale = this.scale; 310 var thetaInc = this.thetaInc; 311 312 var sin, cos, at; 313 var theta, absX, absY; 314 var x0, y0, x1, y1, x2, y2, x3, y3; 315 316 techniqueParameters.constantColor = this.color; 317 graphicsDevice.setTechniqueParameters(techniqueParameters); 318 319 if (this.isInit) { 320 // Direct draw, specifying a position (x,y,z) and texture coordinate (u,v) 321 var writer = graphicsDevice.beginDraw(primitive, (numOfRenderLevels * 6), vertexFormats, semantics); 322 if (writer) { 323 var sinfn = Math.sin; 324 var cosfn = Math.cos; 325 var absfn = Math.abs; 326 theta = 0; 327 x0 = startX; 328 y0 = startY; 329 x2 = startX; 330 y2 = startY; 331 332 for (var i = 0; i < numOfRenderLevels; i += 1) { 333 theta += thetaInc; 334 at = scale * theta; 335 sin = sinfn(theta); 336 cos = cosfn(theta); 337 338 x1 = (at * cos) + startX; 339 y1 = (at * sin) + startY; 340 absX = absfn(x0 - startX); 341 absY = absfn(y0 - startY); 342 x3 = x0 + ((x0 > startX) ? scale * absX : -scale * absX); 343 y3 = y0 + ((y0 > startY) ? scale * absY : -scale * absY); 344 345 // Draws two triangles for each iterative step of the algorithm 346 writer(x3, y3, startZ, 0, 0); 347 writer(x1, y1, startZ, 1, 1); 348 writer(x0, y0, startZ, 0, 0); 349 350 writer(x2, y2, startZ, 0, 0); 351 writer(x3, y3, startZ, 1, 1); 352 writer(x0, y0, startZ, 0, 0); 353 354 x0 = x1; 355 y0 = y1; 356 x2 = x3; 357 y2 = y3; 358 } 359 360 graphicsDevice.endDraw(writer); 361 } 362 } 363 } 364 }; 365 366 // The textured panel, drawn using variable vertex colors 367 var panelRenderObject = { 368 techniqueName: "vertexColorTextured3D", 369 primitive: graphicsDevice.PRIMITIVE_TRIANGLES, 370 numOfRenderItems: 5, 371 colorStream: { 372 semanticName: "color", 373 semantics: null, 374 vertexBuffer: null 375 }, 376 positionStream: { 377 semanticName: "positionAndTexture", 378 semantics: null, 379 vertexBuffer: null 380 }, 381 indexBuffer: null, 382 technique: null, 383 techniqueParameters: null, 384 startPosition: [-13.0, 1.0, 0.0], 385 color: [0.0, 1.0, 1.0, 0.5], 386 isInit: false, 387 remapColors: function remapColorsFn(colors) { 388 // Code needs to be updated for efficiency 389 // Update the colors used for the vertices 390 var numOfRenderItems = this.numOfRenderItems; 391 var coloredItems = numOfRenderItems * numOfRenderItems * 4; 392 var random = Math.random; 393 394 if (colors) { 395 var writer = colors.map(); 396 if (writer) { 397 var r, g, b; 398 for (var i = 0; i < coloredItems; i += 1) { 399 r = random(); 400 g = random(); 401 b = random(); 402 writer(r, g, b, 1); 403 } 404 405 colors.unmap(writer); 406 writer = null; 407 } 408 } 409 }, 410 update: function updateFn(/* delta */ ) { 411 if (this.isInit) { 412 this.remapColors(this.colorStream.vertexBuffer); 413 } 414 }, 415 init: function initFn() { 416 var numOfLevels = this.numOfRenderItems; 417 var numOfLevelsSqrd = numOfLevels * numOfLevels; 418 var coloredItems = numOfLevelsSqrd * 4; 419 var colorStream = this.colorStream; 420 var positionStream = this.positionStream; 421 var indexBuffer = this.indexBuffer; 422 423 var writer, i; 424 425 var positionsParameters = { 426 numVertices: coloredItems, 427 attributes: ['FLOAT3', 'SHORT2'], 428 dynamic: false 429 }; 430 431 var colorsParameters = { 432 numVertices: coloredItems, 433 attributes: ['UBYTE4N'], 434 dynamic: true 435 }; 436 437 var positions = graphicsDevice.createVertexBuffer(positionsParameters); 438 var colors = graphicsDevice.createVertexBuffer(colorsParameters); 439 440 colorStream.semantics = semanticsTypes[colorStream.semanticName]; 441 positionStream.semantics = semanticsTypes[positionStream.semanticName]; 442 443 this.remapColors(colors); 444 colorStream.vertexBuffer = colors; 445 446 if (!indexBuffer) { 447 var indexBufferParameters = { 448 numIndices: numOfLevelsSqrd * 6, 449 format: 'USHORT' 450 }; 451 452 indexBuffer = graphicsDevice.createIndexBuffer(indexBufferParameters); 453 454 writer = indexBuffer.map(); 455 if (writer) { 456 var v0, v1, v2, v3; 457 for (i = 0; i < numOfLevelsSqrd; i += 1) { 458 v0 = 4 * i + 0; 459 v1 = 4 * i + 1; 460 v2 = 4 * i + 2; 461 v3 = 4 * i + 3; 462 writer(v0, v1, v2); 463 writer(v2, v3, v0); 464 } 465 466 indexBuffer.unmap(writer); 467 } 468 469 this.indexBuffer = indexBuffer; 470 } 471 472 if (positions) { 473 writer = positions.map(); 474 if (writer) { 475 var startX = this.startPosition[0]; 476 var startY = this.startPosition[1]; 477 var startZ = this.startPosition[2]; 478 479 for (i = 0; i < numOfLevels; i += 1) { 480 var xs = (startX + i); 481 var xe = (xs + 1); 482 for (var j = 0; j < numOfLevels; j += 1) { 483 var ys = (startY + j); 484 var ye = (ys + 1); 485 writer(xs, ys, startZ, 0, 0); 486 writer(xe, ys, startZ, 1, 0); 487 writer(xe, ye, startZ, 1, 1); 488 writer(xs, ye, startZ, 0, 1); 489 } 490 } 491 492 positions.unmap(writer); 493 writer = null; 494 positionStream.vertexBuffer = positions; 495 } 496 } 497 498 // Allows panel to be drawn before the texture is loaded 499 this.techniqueParameters = techniqueParametersCrateTexture; 500 this.isInit = (colorStream.vertexBuffer && positionStream.vertexBuffer && this.techniqueParameters); 501 }, 502 draw: function drawFn(graphicsDevice) { 503 var primitive = this.primitive; 504 var techniqueParameters = this.techniqueParameters; 505 var colors = this.colorStream.vertexBuffer; 506 var colorSemantics = this.colorStream.semantics; 507 var positions = this.positionStream.vertexBuffer; 508 var positionSemantics = this.positionStream.semantics; 509 var indexBuffer = this.indexBuffer; 510 511 if (this.isInit) { 512 // Sets the vertexBuffers to use for the draw call 513 graphicsDevice.setStream(colors, colorSemantics); 514 graphicsDevice.setStream(positions, positionSemantics); 515 516 // Sets the techniqueParameters, in this case a crate texture with shader with vertexColorTextured3D technique 517 graphicsDevice.setTechniqueParameters(techniqueParameters); 518 519 // Draw quads 520 graphicsDevice.setIndexBuffer(indexBuffer); 521 graphicsDevice.drawIndexed(primitive, indexBuffer.numIndices); 522 } 523 } 524 }; 525 526 // Sets objects to render 527 var renderObjects = [ 528 circleRenderObject, 529 gridRenderObject, 530 spiralRenderObject, 531 panelRenderObject 532 ]; 533 534 // Generate texture (Simple checkerboard) 535 var proceduralTextureParameters = { 536 name: "checkers", 537 width: 4, 538 height: 4, 539 depth: 1, 540 format: graphicsDevice.PIXELFORMAT_L8, 541 mipmaps: true, 542 cubemap: false, 543 renderable: false, 544 dynamic: false, 545 data: [ 546 0, 547 255, 548 0, 549 255, 550 255, 551 0, 552 255, 553 0, 554 0, 555 255, 556 0, 557 255, 558 255, 559 0, 560 255, 561 0 562 ] 563 }; 564 565 var proceduralTexture = graphicsDevice.createTexture(proceduralTextureParameters); 566 techniqueParametersProceduralTexture['diffuse'] = proceduralTexture; 567 568 // Init objects 569 spiralRenderObject.init(); 570 gridRenderObject.init(); 571 circleRenderObject.init(); 572 panelRenderObject.init(); 573 574 var intervalID; 575 var previousTime = TurbulenzEngine.time; 576 var renderObj = null; 577 578 var renderFrame = function renderFrameFn() { 579 var currentTime = TurbulenzEngine.time; 580 var deltaTime = currentTime - previousTime; 581 if (deltaTime > 0.1) { 582 deltaTime = 0.1; 583 } 584 585 // Update objects (in this case animate) 586 var renderObjectsCount = renderObjects.length; 587 for (var n = 0; n < renderObjectsCount; n += 1) { 588 renderObj = renderObjects[n]; 589 var updateObj = renderObj.update; 590 if (updateObj) { 591 renderObj.update(deltaTime); 592 } 593 } 594 595 // Update the aspect ratio of the camera in case of window resizes 596 var aspectRatio = (graphicsDevice.width / graphicsDevice.height); 597 if (aspectRatio !== camera.aspectRatio) { 598 camera.aspectRatio = aspectRatio; 599 camera.updateProjectionMatrix(); 600 } 601 camera.updateViewProjectionMatrix(); 602 603 var vp = camera.viewProjectionMatrix; 604 605 if (graphicsDevice.beginFrame()) { 606 graphicsDevice.clear(clearColor, 1.0, 0); 607 608 for (var m = 0; m < renderObjectsCount; m += 1) { 609 renderObj = renderObjects[m]; 610 var technique = renderObj.technique; 611 612 if (!technique) { 613 technique = shader.getTechnique(renderObj.techniqueName); 614 if (technique) { 615 renderObj.technique = technique; 616 } 617 } 618 619 if (technique) { 620 graphicsDevice.setTechnique(technique); 621 622 var techniqueParameters = renderObj.techniqueParameters; 623 if (techniqueParameters) { 624 techniqueParameters.worldViewProjection = vp; 625 } 626 627 renderObj.draw(graphicsDevice); 628 } 629 } 630 631 graphicsDevice.endFrame(); 632 } 633 previousTime = currentTime; 634 }; 635 636 var crateTextureLoaded = false; 637 var loadingLoop = function loadingLoopFn() { 638 if (shader && crateTextureLoaded) { 639 TurbulenzEngine.clearInterval(intervalID); 640 641 intervalID = TurbulenzEngine.setInterval(renderFrame, 1000 / 60); 642 } 643 }; 644 645 // Start calling the loading loop at 10Hz 646 intervalID = TurbulenzEngine.setInterval(loadingLoop, 1000 / 10); 647 648 var mappingTableReceived = function mappingTableReceivedFn(mappingTable) { 649 // Load shader and techniques 650 var shaderLoaded = function shaderLoadedFn(shaderText) { 651 if (shaderText) { 652 var shaderParameters = JSON.parse(shaderText); 653 shader = graphicsDevice.createShader(shaderParameters); 654 } 655 }; 656 657 requestHandler.request({ 658 src: mappingTable.getURL("shaders/generic3D.cgfx"), 659 onload: shaderLoaded 660 }); 661 662 var crateTextureParameters = { 663 src: mappingTable.getURL("textures/crate.jpg"), 664 mipmaps: true, 665 onload: function (texture) { 666 techniqueParametersCrateTexture['diffuse'] = texture; 667 crateTextureLoaded = true; 668 } 669 }; 670 graphicsDevice.createTexture(crateTextureParameters); 671 }; 672 673 var gameSessionCreated = function gameSessionCreatedFn(gameSession) { 674 TurbulenzServices.createMappingTable(requestHandler, gameSession, mappingTableReceived); 675 }; 676 var gameSession = TurbulenzServices.createGameSession(requestHandler, gameSessionCreated); 677 678 // Create a scene destroy callback to run when the window is closed 679 TurbulenzEngine.onunload = function destroyScene() { 680 TurbulenzEngine.clearInterval(intervalID); 681 682 if (gameSession) { 683 gameSession.destroy(); 684 gameSession = null; 685 } 686 687 requestHandler = null; 688 camera = null; 689 techniqueParameters = null; 690 techniqueParametersProceduralTexture = null; 691 techniqueParametersCrateTexture = null; 692 semanticsTypes = null; 693 vertexFormatTypes = null; 694 renderObjects.length = 0; 695 proceduralTexture = null; 696 TurbulenzEngine.flush(); 697 graphicsDevice = null; 698 mathDevice = null; 699 requestHandler = null; 700 }; 701 };