void APacmanTerrain::PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) { Super::PostEditChangeProperty(PropertyChangedEvent); if (PropertyChangedEvent.MemberProperty->GetName() == GET_MEMBER_NAME_STRING_CHECKED(APacmanTerrain, WorldMap)) { // We are only concerned on top mip map level auto &Mip = WorldMap->PlatformData->Mips[0]; const FColor *Pixels = reinterpret_cast<const FColor*>(Mip.BulkData.LockReadOnly()); FindBlockSize(Pixels, Mip.SizeX, Mip.SizeY); Mip.BulkData.Unlock(); } }
bool BaseHierarchical::SetupStage (LuminanceComputeStage& stage, int inputW, int inputH, int minSize, iTextureHandle* inputTex, iShader* computeShader) { stage.svInput.AttachNew (new csShaderVariable ( svNameStringSet->Request ("tex diffuse"))); size_t pticket; CS::Graphics::RenderMeshModes modes; // Just keep defaults csShaderVariableStack svstack; { PostEffectManager::Layer* tempLayer; PostEffectManager::LayerInputMap inputMap; inputMap.manualInput = stage.svInput; tempLayer = computeFX.AddLayer (computeShader, 1, &inputMap); // Determine 'priority ticket' for stage svstack.Setup (shaderManager->GetSVNameStringset ()->GetSize ()); computeFX.GetLayerRenderSVs (tempLayer, svstack); pticket = computeShader->GetPrioritiesTicket (modes, svstack); computeFX.RemoveLayer (tempLayer); } int maxBlockSizeX = 16; int maxBlockSizeY = 16; csRef<iShader> shader; FindBlockSize (computeShader, pticket, modes, svstack, inputW, inputH, maxBlockSizeX, maxBlockSizeY, 0); csArray<ProcessingPartFinal> finalParts; csFIFO<ProcessingPart> remainingParts; { ProcessingPart firstPart; firstPart.sourceRect.Set (0, 0, inputW, inputH); firstPart.destOffsX = 0; firstPart.destOffsY = 0; remainingParts.Push (firstPart); } while (remainingParts.GetSize() > 0) { ProcessingPart part = remainingParts.PopTop(); int blockSizeX = 16; int blockSizeY = 16; csRef<iShader> shader; FindBlockSize (computeShader, pticket, modes, svstack, part.sourceRect.Width(), part.sourceRect.Height(), blockSizeX, blockSizeY, &shader); // @@@ Handle failure int destW = part.sourceRect.Width()/blockSizeX; int destH = part.sourceRect.Height()/blockSizeY; int coveredW = destW*blockSizeX; int coveredH = destH*blockSizeY; int remainderX = part.sourceRect.Width()-coveredW; int remainderY = part.sourceRect.Height()-coveredH; if (remainderX > 0) { ProcessingPart newPart; newPart.sourceRect.Set ( part.sourceRect.xmin+coveredW, part.sourceRect.ymin, part.sourceRect.xmin+coveredW+remainderX, part.sourceRect.ymin+coveredH); newPart.destOffsX = part.destOffsX+destW; newPart.destOffsY = part.destOffsY; remainingParts.Push (newPart); } if (remainderY > 0) { ProcessingPart newPart; newPart.sourceRect.Set ( part.sourceRect.xmin, part.sourceRect.ymin+coveredH, part.sourceRect.xmin+coveredW, part.sourceRect.ymin+coveredH+remainderY); newPart.destOffsX = part.destOffsX; newPart.destOffsY = part.destOffsY+destH; remainingParts.Push (newPart); } if ((remainderX > 0) && (remainderY > 0)) { ProcessingPart newPart; newPart.sourceRect.Set ( part.sourceRect.xmin+coveredW, part.sourceRect.ymin+coveredH, part.sourceRect.xmin+coveredW+remainderX, part.sourceRect.ymin+coveredH+remainderY); newPart.destOffsX = part.destOffsX+destW; newPart.destOffsY = part.destOffsY+destH; remainingParts.Push (newPart); } ProcessingPartFinal finalPart; finalPart.sourceRect.Set ( part.sourceRect.xmin, part.sourceRect.ymin, part.sourceRect.xmin+coveredW, part.sourceRect.ymin+coveredH); finalPart.destRect.Set ( part.destOffsX, part.destOffsY, part.destOffsX+destW, part.destOffsY+destH); finalPart.shader = shader; finalParts.Push (finalPart); } stage.targetW = finalParts[0].destRect.xmax; stage.targetH = finalParts[0].destRect.ymax; for (size_t l = 1; l < finalParts.GetSize(); l++) { stage.targetW = csMax (stage.targetW, finalParts[l].destRect.xmax); stage.targetH = csMax (stage.targetH, finalParts[l].destRect.ymax); } bool lastStage = (stage.targetW <= minSize) && (stage.targetH <= minSize); uint texFlags = CS_TEXTURE_3D | CS_TEXTURE_NPOTS | CS_TEXTURE_CLAMP | CS_TEXTURE_SCALE_UP | CS_TEXTURE_NOMIPMAPS; csString stageFormat; if (lastStage) stageFormat = readbackFmt.GetCanonical(); else stageFormat = computeFX.GetIntermediateTargetFormat(); stage.target = graphics3D->GetTextureManager ()->CreateTexture (stage.targetW, stage.targetH, csimg2D, stageFormat, texFlags); int targetPixels = stage.targetW * maxBlockSizeX * stage.targetH * maxBlockSizeY; int sourcePixels = inputW * inputH; stage.svWeightCoeff.AttachNew (new csShaderVariable ( svNameStringSet->Request ("weight coeff"))); stage.svWeightCoeff->SetValue (float(targetPixels)/float(sourcePixels)); // Set measureTex as input to first layer of computeFX stage.svInput->SetValue (inputTex); PostEffectManager::Layer* outputLayer = 0; for (size_t l = 0; l < finalParts.GetSize(); l++) { PostEffectManager::Layer* layer; PostEffectManager::LayerInputMap inputMap; inputMap.manualInput = stage.svInput; inputMap.sourceRect = finalParts[l].sourceRect; inputMap.inputPixelSizeName = "input pixel size"; PostEffectManager::LayerOptions options; options.targetRect = finalParts[l].destRect; if (outputLayer == 0) { options.manualTarget = stage.target; options.readback = lastStage; } else options.renderOn = outputLayer; //inputMap.manualTexcoords = computeTexcoordBuf; layer = computeFX.AddLayer (finalParts[l].shader, options, 1, &inputMap); layer->GetSVContext()->AddVariable (stage.svInput); layer->GetSVContext()->AddVariable (stage.svWeightCoeff); stage.layers.Push (layer); if (outputLayer == 0) outputLayer = layer; } return !lastStage; }