浏览代码

RGBA16F saving support for probes

Tim Barnes 6 年之前
父节点
当前提交
6937989d61

+ 29 - 37
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -116,7 +116,7 @@ ReflectionProbe::ReflectionProbe()
    mRadius = 10;
 
    mUseCubemap = false;
-   mUseHDRCaptures = false;
+   mUseHDRCaptures = true;
 
    mStaticCubemap = NULL;
    mReflectionPath = "";
@@ -584,19 +584,17 @@ bool ReflectionProbe::createClientResources()
       mIrridianceMap->createMap();
    }
 
-   if (!mUseHDRCaptures)
-   {
-      String irrPath = getIrradianceMapPath();
-      if (Platform::isFile(irrPath))
-      {
-         mIrridianceMap->setCubemapFile(FileName(irrPath));
-         mIrridianceMap->updateFaces();
-      }
 
-      if (mIrridianceMap->mCubemap.isNull())
-         Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
+   String irrPath = getIrradianceMapPath();
+   if (Platform::isFile(irrPath))
+   {
+      mIrridianceMap->setCubemapFile(FileName(irrPath));
+      mIrridianceMap->updateFaces();
    }
 
+   if (mIrridianceMap->mCubemap.isNull())
+      Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
+
    //
    if (!mPrefilterMap)
    {
@@ -606,19 +604,16 @@ bool ReflectionProbe::createClientResources()
       mPrefilterMap->createMap();
    }
 
-   if (!mUseHDRCaptures)
+   String prefilPath = getPrefilterMapPath();
+   if (Platform::isFile(prefilPath))
    {
-      String prefilPath = getPrefilterMapPath();
-      if (Platform::isFile(prefilPath))
-      {
-         mPrefilterMap->setCubemapFile(FileName(prefilPath));
-         mPrefilterMap->updateFaces();
-      }
-
-      if (mPrefilterMap->mCubemap.isNull())
-         Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
+      mPrefilterMap->setCubemapFile(FileName(prefilPath));
+      mPrefilterMap->updateFaces();
    }
 
+   if (mPrefilterMap->mCubemap.isNull())
+      Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
+
    //brdf lookup texture   
    String brdfPath = Con::getVariable("$Core::BRDFTexture", "core/art/pbr/brdfTexture.dds");
    mBrdfTexture = TEXMGR->createTexture(brdfPath, &GFXTexturePersistentProfile);
@@ -776,11 +771,11 @@ void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
 	  const MatrixF worldToObjectXfm = getTransform();
 
       Box3F cube(-Point3F(mRadius, mRadius, mRadius),Point3F(mRadius, mRadius, mRadius));
-	  Box3F wb = getWorldBox();
+      Box3F wb = getWorldBox();
       cube.setCenter(getPosition()+mProbePosOffset);
-	  wb.setCenter(getPosition() + mProbePosOffset);
+      wb.setCenter(getPosition() + mProbePosOffset);
       draw->drawCube(desc, cube, color, &worldToObjectXfm);
-	  draw->drawCube(desc, wb, color, &worldToObjectXfm);
+      draw->drawCube(desc, wb, color, &worldToObjectXfm);
    }
 }
 
@@ -874,7 +869,7 @@ void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithPro
       mDynamicCubemap = GFX->createCubemap();
 
       if(mUseHDRCaptures)
-         mDynamicCubemap->initDynamic(resolution, GFXFormatR16G16B16A16);
+         mDynamicCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
       else
          mDynamicCubemap->initDynamic(resolution, GFXFormatB8G8R8A8);
 
@@ -922,7 +917,7 @@ void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithPro
    for (U32 i = 0; i < 6; ++i)
    {
       GFXTexHandle blendTex;
-      blendTex.set(resolution, resolution, GFXFormatR16G16B16A16, &GFXRenderTargetProfile, "");
+      blendTex.set(resolution, resolution, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, "");
 
       GFXTextureTargetRef baseTarget = GFX->allocRenderToTextureTarget();
 
@@ -980,10 +975,11 @@ void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithPro
       MathUtils::makeFrustum(&left, &right, &top, &bottom, M_HALFPI_F, 1.0f, nearPlane);
       Frustum frustum(false, left, right, top, bottom, nearPlane, farDist);
 
-	  F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust;
-	  TSShapeInstance::smDetailAdjust *= getNextPow2(resolution);
+      F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust;
+      TSShapeInstance::smDetailAdjust *= getNextPow2(resolution);
       renderFrame(&baseTarget, matView, frustum, mCaptureMask & EDITOR_RENDER_TYPEMASK, gCanvasClearColor);
-	  TSShapeInstance::smDetailAdjust = detailAdjustBackup;
+      TSShapeInstance::smDetailAdjust = detailAdjustBackup;
+
       baseTarget->resolve();
    }
 
@@ -1009,8 +1005,8 @@ void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithPro
       //Prep it with whatever resolution we've dictated for our bake
       if (mUseHDRCaptures)
       {
-         mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16);
-         mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16);
+         mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
+         mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
       }
       else
       {
@@ -1026,12 +1022,8 @@ void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithPro
       IBLUtilities::GenerateIrradianceMap(renderTarget, sceneCaptureCubemap, mIrridianceMap->mCubemap);
       IBLUtilities::GeneratePrefilterMap(renderTarget, sceneCaptureCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
 
-      //We can't save HDR captures at the moment
-      if (!mUseHDRCaptures)
-      {
-         IBLUtilities::SaveCubeMap(getIrradianceMapPath(), mIrridianceMap->mCubemap);
-         IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);
-      }
+      IBLUtilities::SaveCubeMap(getIrradianceMapPath(), mIrridianceMap->mCubemap);
+      IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);
    }
    else
    {

+ 24 - 9
Engine/source/gfx/D3D11/gfxD3D11TextureObject.cpp

@@ -177,8 +177,8 @@ bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
    // check format limitations
    // at the moment we only support RGBA for the source (other 4 byte formats should
    // be easy to add though)
-   AssertFatal(mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB, "copyToBmp: invalid format");
-   if (mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB)
+   AssertFatal(mFormat == GFXFormatR16G16B16A16F || mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB, "copyToBmp: invalid format");
+   if (mFormat != GFXFormatR16G16B16A16F && mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB)
       return false;
 
    PROFILE_START(GFXD3D11TextureObject_copyToBmp);
@@ -190,11 +190,18 @@ bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
    bmp->setHasTransparency(mHasTransparency);
 
    // set some constants
-   const U32 sourceBytesPerPixel = 4;
+   U32 sourceBytesPerPixel = 4;
    U32 destBytesPerPixel = 0;
 
    const GFXFormat fmt = bmp->getFormat();
-   if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatR8G8B8A8_SRGB)
+   bool fp16 = false;//is rgba16f format?
+   if (fmt == GFXFormatR16G16B16A16F)
+   {
+      destBytesPerPixel = 8;
+      sourceBytesPerPixel = 8;
+      fp16 = true;
+   }
+   else if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatR8G8B8A8_SRGB)
       destBytesPerPixel = 4;
    else if(bmp->getFormat() == GFXFormatR8G8B8)
       destBytesPerPixel = 3;
@@ -249,11 +256,19 @@ bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
       {
          for (U32 col = 0; col < width; ++col)
          {
-            destPtr[0] = srcPtr[2]; // red
-            destPtr[1] = srcPtr[1]; // green
-            destPtr[2] = srcPtr[0]; // blue 
-            if (destBytesPerPixel == 4)
-               destPtr[3] = srcPtr[3]; // alpha
+            //we can just copy data straight in with RGBA16F format
+            if (fp16)
+            {
+               dMemcpy(destPtr, srcPtr, sizeof(U16) * 4);
+            }
+            else
+            {            
+               destPtr[0] = srcPtr[2]; // red
+               destPtr[1] = srcPtr[1]; // green
+               destPtr[2] = srcPtr[0]; // blue 
+               if (destBytesPerPixel == 4)
+                  destPtr[3] = srcPtr[3]; // alpha
+            }
 
             // go to next pixel in src
             srcPtr += sourceBytesPerPixel;

+ 3 - 5
Engine/source/gfx/bitmap/cubemapSaver.cpp

@@ -52,6 +52,7 @@ namespace CubemapSaver
       GFXFormat targetFmt = pCubemap->getFormat();
       //setup render targets
       GFXTexHandle pTextures[CubeFaces];
+
       for (U32 face = 0; face < CubeFaces; face++)
       {
          pTextures[face].set(faceSize, faceSize, targetFmt,
@@ -75,9 +76,6 @@ namespace CubemapSaver
             Con::errorf("CubemapSaver: cubemap number %u failed to copy", i);
             error = true;
          }
-         //gen mip maps if there are none
-         if(!hasMips)
-            pBitmaps[i]->extrudeMipLevels();
       }
 
       if (!error)
@@ -85,8 +83,8 @@ namespace CubemapSaver
          DDSFile *pDds = DDSFile::createDDSCubemapFileFromGBitmaps(pBitmaps);
          if (pDds)
          {
-            // non compressed format needs swizzling
-            if (!compressedFormat)
+            // compressed and floating point don't need swizzling
+            if (!compressedFormat && targetFmt != GFXFormatR16G16B16A16F)
                ImageUtil::swizzleDDS(pDds, Swizzles::bgra);
 
             if(compressedFormat)

+ 126 - 0
Engine/source/gfx/bitmap/ddsData.h

@@ -742,6 +742,132 @@ namespace dds
       }
    }
 
+   const U32 getBitsPerPixel(DXGI_FORMAT fmt)
+   {
+      switch (fmt)
+      {
+      case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+      case DXGI_FORMAT_R32G32B32A32_FLOAT:
+      case DXGI_FORMAT_R32G32B32A32_UINT:
+      case DXGI_FORMAT_R32G32B32A32_SINT:
+         return 128;
+
+      case DXGI_FORMAT_R32G32B32_TYPELESS:
+      case DXGI_FORMAT_R32G32B32_FLOAT:
+      case DXGI_FORMAT_R32G32B32_UINT:
+      case DXGI_FORMAT_R32G32B32_SINT:
+         return 96;
+
+      case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+      case DXGI_FORMAT_R16G16B16A16_FLOAT:
+      case DXGI_FORMAT_R16G16B16A16_UNORM:
+      case DXGI_FORMAT_R16G16B16A16_UINT:
+      case DXGI_FORMAT_R16G16B16A16_SNORM:
+      case DXGI_FORMAT_R16G16B16A16_SINT:
+      case DXGI_FORMAT_R32G32_TYPELESS:
+      case DXGI_FORMAT_R32G32_FLOAT:
+      case DXGI_FORMAT_R32G32_UINT:
+      case DXGI_FORMAT_R32G32_SINT:
+      case DXGI_FORMAT_R32G8X24_TYPELESS:
+      case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+      case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+      case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+         return 64;
+
+      case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+      case DXGI_FORMAT_R10G10B10A2_UNORM:
+      case DXGI_FORMAT_R10G10B10A2_UINT:
+      case DXGI_FORMAT_R11G11B10_FLOAT:
+      case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+      case DXGI_FORMAT_R8G8B8A8_UNORM:
+      case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+      case DXGI_FORMAT_R8G8B8A8_UINT:
+      case DXGI_FORMAT_R8G8B8A8_SNORM:
+      case DXGI_FORMAT_R8G8B8A8_SINT:
+      case DXGI_FORMAT_R16G16_TYPELESS:
+      case DXGI_FORMAT_R16G16_FLOAT:
+      case DXGI_FORMAT_R16G16_UNORM:
+      case DXGI_FORMAT_R16G16_UINT:
+      case DXGI_FORMAT_R16G16_SNORM:
+      case DXGI_FORMAT_R16G16_SINT:
+      case DXGI_FORMAT_R32_TYPELESS:
+      case DXGI_FORMAT_D32_FLOAT:
+      case DXGI_FORMAT_R32_FLOAT:
+      case DXGI_FORMAT_R32_UINT:
+      case DXGI_FORMAT_R32_SINT:
+      case DXGI_FORMAT_R24G8_TYPELESS:
+      case DXGI_FORMAT_D24_UNORM_S8_UINT:
+      case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+      case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+      case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+      case DXGI_FORMAT_R8G8_B8G8_UNORM:
+      case DXGI_FORMAT_G8R8_G8B8_UNORM:
+      case DXGI_FORMAT_B8G8R8A8_UNORM:
+      case DXGI_FORMAT_B8G8R8X8_UNORM:
+      case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+      case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+      case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+      case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+      case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+         return 32;
+
+      case DXGI_FORMAT_R8G8_TYPELESS:
+      case DXGI_FORMAT_R8G8_UNORM:
+      case DXGI_FORMAT_R8G8_UINT:
+      case DXGI_FORMAT_R8G8_SNORM:
+      case DXGI_FORMAT_R8G8_SINT:
+      case DXGI_FORMAT_R16_TYPELESS:
+      case DXGI_FORMAT_R16_FLOAT:
+      case DXGI_FORMAT_D16_UNORM:
+      case DXGI_FORMAT_R16_UNORM:
+      case DXGI_FORMAT_R16_UINT:
+      case DXGI_FORMAT_R16_SNORM:
+      case DXGI_FORMAT_R16_SINT:
+      case DXGI_FORMAT_B5G6R5_UNORM:
+      case DXGI_FORMAT_B5G5R5A1_UNORM:
+         return 16;
+
+      case DXGI_FORMAT_R8_TYPELESS:
+      case DXGI_FORMAT_R8_UNORM:
+      case DXGI_FORMAT_R8_UINT:
+      case DXGI_FORMAT_R8_SNORM:
+      case DXGI_FORMAT_R8_SINT:
+      case DXGI_FORMAT_A8_UNORM:
+         return 8;
+
+      case DXGI_FORMAT_R1_UNORM:
+         return 1;
+
+      case DXGI_FORMAT_BC1_TYPELESS:
+      case DXGI_FORMAT_BC1_UNORM:
+      case DXGI_FORMAT_BC1_UNORM_SRGB:
+      case DXGI_FORMAT_BC4_TYPELESS:
+      case DXGI_FORMAT_BC4_UNORM:
+      case DXGI_FORMAT_BC4_SNORM:
+         return 4;
+
+      case DXGI_FORMAT_BC2_TYPELESS:
+      case DXGI_FORMAT_BC2_UNORM:
+      case DXGI_FORMAT_BC2_UNORM_SRGB:
+      case DXGI_FORMAT_BC3_TYPELESS:
+      case DXGI_FORMAT_BC3_UNORM:
+      case DXGI_FORMAT_BC3_UNORM_SRGB:
+      case DXGI_FORMAT_BC5_TYPELESS:
+      case DXGI_FORMAT_BC5_UNORM:
+      case DXGI_FORMAT_BC5_SNORM:
+      case DXGI_FORMAT_BC6H_TYPELESS:
+      case DXGI_FORMAT_BC6H_UF16:
+      case DXGI_FORMAT_BC6H_SF16:
+      case DXGI_FORMAT_BC7_TYPELESS:
+      case DXGI_FORMAT_BC7_UNORM:
+      case DXGI_FORMAT_BC7_UNORM_SRGB:
+         return 8;
+
+      default:
+         return 0;
+      }
+   }
+
    const bool validateHeader(const DDS_HEADER &header)
    {
       if (header.size != DDS_HEADER_SIZE)

+ 8 - 5
Engine/source/gfx/bitmap/ddsFile.cpp

@@ -272,7 +272,7 @@ bool DDSFile::readHeader(Stream &s)
          mFlags.set(CompressedData);
       else
       {
-         mBytesPerPixel = header.ddspf.bpp / 8;
+         mBytesPerPixel = dds::getBitsPerPixel(dx10header.dxgiFormat) / 8;
          mFlags.set(RGBData);
       }
 
@@ -397,8 +397,8 @@ bool DDSFile::read(Stream &s, U32 dropMipCount)
          }
 
          // Load all the mips.
-         for(S32 l=0; l<mMipMapCount; l++)
-            mSurfaces[i]->readNextMip(this, s, mHeight, mWidth, l, l < dropMipCount );
+         for(S32 mip=0; mip<mMipMapCount; mip++)
+            mSurfaces[i]->readNextMip(this, s, mHeight, mWidth, mip, mip < dropMipCount );
       }
 
    }
@@ -483,6 +483,8 @@ bool DDSFile::writeHeader( Stream &s )
    {
       surfaceFlags |= DDS_SURFACE_FLAGS_CUBEMAP;
       cubemapFlags |= DDS_CUBEMAP_ALLFACES;
+      if (hasDx10Header)
+         dx10header.miscFlag = dds::D3D10_RESOURCE_MISC_TEXTURECUBE;
    }
 
    //volume texture
@@ -739,9 +741,10 @@ DDSFile *DDSFile::createDDSCubemapFileFromGBitmaps(GBitmap **gbmps)
    //all cubemaps have the same dimensions and formats
    GBitmap *pBitmap = gbmps[0];
 
-   if (pBitmap->getFormat() != GFXFormatR8G8B8A8)
+   GFXFormat fmt = pBitmap->getFormat();
+   if (fmt != GFXFormatR8G8B8A8 && fmt != GFXFormatR16G16B16A16F)
    {
-      Con::errorf("createDDSCubemapFileFromGBitmaps: Only GFXFormatR8G8B8A8 supported for now");
+      Con::errorf("createDDSCubemapFileFromGBitmaps: unsupported format");
       return NULL;
    }
 

+ 10 - 0
Engine/source/gfx/bitmap/gBitmap.cpp

@@ -379,6 +379,9 @@ void GBitmap::allocateBitmapWithMips(const U32 in_width, const U32 in_height, co
    case GFXFormatR5G6B5:
    case GFXFormatR5G5B5A1:     mBytesPerPixel = 2;
       break;
+   case GFXFormatR16G16B16A16F:
+   case GFXFormatR16G16B16A16: mBytesPerPixel = 8;
+      break;
    default:
       AssertFatal(false, "GBitmap::GBitmap: misunderstood format specifier");
       break;
@@ -452,6 +455,13 @@ void GBitmap::extrudeMipLevels(bool clearBorders)
             bitmapExtrudeRGBA(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
          break;
       }
+
+      case GFXFormatR16G16B16A16F:
+      {
+         for (U32 i = 1; i < mNumMipLevels; i++)
+            bitmapExtrudeFPRGBA(getBits(i - 1), getWritableBits(i), getHeight(i - 1), getWidth(i - 1));
+         break;
+      }
       
       default:
          break;