Browse Source

Scheduled background updates and checked off other completed tasks.

David Piuva 5 years ago
parent
commit
2b55ffccbe
2 changed files with 25 additions and 28 deletions
  1. 24 9
      Source/SDK/SpriteEngine/spriteAPI.cpp
  2. 1 19
      Source/SDK/sandbox/sandbox.cpp

+ 24 - 9
Source/SDK/SpriteEngine/spriteAPI.cpp

@@ -603,7 +603,8 @@ public:
 	SpriteWorldImpl(const OrthoSystem &ortho, int shadowResolution)
 	: ortho(ortho), passiveSprites(ortho_miniUnitsPerTile * 64), passiveModels(ortho_miniUnitsPerTile * 64), shadowResolution(shadowResolution), temporaryShadowMap(shadowResolution) {}
 public:
-	void updateBlockAt(const IRect& blockRegion, const IRect& seenRegion) {
+	// Post-condition: Returns the number of redrawn background blocks. (0 or 1)
+	int updateBlockAt(const IRect& blockRegion, const IRect& seenRegion) {
 		int unusedBlockIndex = -1;
 		// Find an existing block
 		for (int b = 0; b < this->backgroundBlocks.length(); b++) {
@@ -613,12 +614,13 @@ public:
 				if (currentBlockPtr->cameraId == this->ortho.view[this->cameraIndex].id) {
 					// Check location
 					if (currentBlockPtr->worldRegion.left() == blockRegion.left() && currentBlockPtr->worldRegion.top() == blockRegion.top()) {
-						// Update if needed
+						// Update if needed before using the block
 						if (currentBlockPtr->state == BlockState::Dirty) {
 							currentBlockPtr->update(this->passiveSprites, this->passiveModels, blockRegion, this->ortho.view[this->cameraIndex]);
+							return 1;
+						} else {
+							return 0;
 						}
-						// Use the block
-						return;
 					} else {
 						// See if the block is too far from the camera
 						if (currentBlockPtr->worldRegion.right() < seenRegion.left() - BackgroundBlock::maxDistance
@@ -647,6 +649,7 @@ public:
 			// Create a new block
 			this->backgroundBlocks.pushConstruct(this->passiveSprites, this->passiveModels, blockRegion, this->ortho.view[this->cameraIndex]);
 		}
+		return 1;
 	}
 	void invalidateBlockAt(int left, int top) {
 		// Find an existing block
@@ -662,7 +665,10 @@ public:
 		}
 	}
 	// Make sure that each pixel in seenRegion is occupied by an updated background block
-	void updateBlocks(const IRect& seenRegion) {
+	// If maxUpdates is larger than -1, the work is scheduled to do at most maxUpdates per call.
+	// Post-condition: Returns the number of redrawn background blocks.
+	int updateBlocks(const IRect& seenRegion, int maxUpdates = -1) {
+		int updateCount = 0;
 		// Round inclusive pixel indices down to containing blocks and iterate over them in strides along x and y
 		int64_t roundedLeft = roundDown(seenRegion.left(), BackgroundBlock::blockSize);
 		int64_t roundedTop = roundDown(seenRegion.top(), BackgroundBlock::blockSize);
@@ -671,9 +677,14 @@ public:
 		for (int64_t y = roundedTop; y <= roundedBottom; y += BackgroundBlock::blockSize) {
 			for (int64_t x = roundedLeft; x <= roundedRight; x += BackgroundBlock::blockSize) {
 				// Make sure that a block is allocated and pre-drawn at this location
-				this->updateBlockAt(IRect(x, y, BackgroundBlock::blockSize, BackgroundBlock::blockSize), seenRegion);
+				updateCount += this->updateBlockAt(IRect(x, y, BackgroundBlock::blockSize, BackgroundBlock::blockSize), seenRegion);
+				if (maxUpdates > -1 && updateCount >= maxUpdates) {
+					// Skip early if the maximum update count has been reached.
+					return updateCount;
+				}
 			}
 		}
+		return updateCount;
 	}
 	void drawDeferred(OrderedImageRgbaU8& diffuseTarget, OrderedImageRgbaU8& normalTarget, AlignedImageF32& heightTarget, const IRect& seenRegion) {
 		// Check image dimensions
@@ -681,9 +692,13 @@ public:
 		assert(image_getWidth(normalTarget) == seenRegion.width() && image_getHeight(normalTarget) == seenRegion.height());
 		assert(image_getWidth(heightTarget) == seenRegion.width() && image_getHeight(heightTarget) == seenRegion.height());
 		this->dirtyBackground.setTargetResolution(seenRegion.width(), seenRegion.height());
-		// Draw passive sprites to blocks
-		this->updateBlocks(seenRegion);
-
+		// Draw passive sprites and models to blocks
+		int forcedUpdates = this->updateBlocks(seenRegion);
+		// If no critical updates were made to the background
+		if (forcedUpdates < 1) {
+			// Schedule drawing of up to one block from a larger region
+			this->updateBlocks(seenRegion.expanded(128), 1);
+		}
 		// Draw background blocks to the target images
 		for (int b = 0; b < this->backgroundBlocks.length(); b++) {
 			#ifdef DIRTY_RECTANGLE_OPTIMIZATION

+ 1 - 19
Source/SDK/sandbox/sandbox.cpp

@@ -44,12 +44,6 @@ VISUALS:
 		Allow defining decals locally for each level by loading their images from a temporary image pool of level specific content.
 			This can be used to write instructions specific to a certain mission and give a unique look to an otherwise generic level.
 			Billboards and signs can also be possible to reuse with custom images and text.
-	* Static 3D models that are rendered when the background updates.
-		These have normal resolution and can be freely rotated, scaled and colored.
-		They draw shadows just like the pre-rendered sprites.
-	* See if there's a shadow smoothing method worth using on the CPU.
-		The blend filter is already quite heavy with the saturation, so it might as well do something more useful than a single multiplication as the main feature.
-		The difficult thing is to preserve details from normal mapping and tiny details while making shadow edges look smooth.
 	* Allow having many high-quality light sources by introducing fully passive lights.
 		Useful for indirect light from the sky and general ambient light.
 		The background stores RGBA light buffers to make passive lights super cheap.
@@ -68,15 +62,7 @@ VISUALS:
 			of looking it up from the same offset is compensated for somehow.
 		The first cubemap will be persistent and used later for dynamic light.
 		The later cubemaps will be temporary when generating the background's softer light.
-USABILITY:
-	* Tool for selecting and removing passive sprites.
-		Use both unique handles for simplicity and the raw look-up for handling multiple sprites at once:
-			Given an optional integer argument (defaulted to zero) to background sprite construction.
-			This allow making custom filtering of sprites by category or giving a unique index to a sprite.
-			A lookup can later return references to the sprite instances together with the key and allow custom filtering.
-			A deletion lookup can take a function returning true when the background sprite should be deleted.
-				The full 3D location and custom key will be returned for filtering.
-				If the game wants to filter by direction or anything else, then encode that into the key.
+
 OPTIMIZE:
 	* Make a tile based light culling.
 		The background has pre-stored minimum and maximum depth for tiles of 32² pixel blocks.
@@ -92,10 +78,6 @@ OPTIMIZE:
 			1--12-21-10-0
 			1--12-21-10-0
 			1-----10----0
-	* Decrease peak time using a vertical brick pattern using a half row offset on odd background block columns.
-		This is optimized for wide aspect ratios, which is more common than standing formats.
-		Cutting the peak repainting area into half without increasing the minimum buffered region.
-		Scheduling updates of nearby blocks can take one at a time when there's nothing that must be updated instantly.
 	* Create a debug feature in spriteAPI for displaying the octree using lines.
 		One color for the owned space and another for the sprite bounding boxes.
 		Pressing a certain button in Sandbox should toggle the debug drawing to allow asserting that the tree is well balanced for the level's size.