Exemplo n.º 1
0
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;
	}