Bläddra i källkod

Merge pull request #1532 from Azaezel/mipwip

render target mipmap generation
Areloch 1 månad sedan
förälder
incheckning
13ec94ef6b

+ 21 - 11
Engine/source/gfx/D3D11/gfxD3D11Target.cpp

@@ -133,17 +133,14 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te
             mTargets[slot] = d3dto->get2DTex();
             mTargets[slot]->AddRef();
             mTargetViews[slot] = d3dto->getRTView();
-            mTargetViews[slot]->AddRef();         
+            mTargetViews[slot]->AddRef();
+            mResolveTargets[slot] = d3dto;
          } 
          else 
          {
             mTargets[slot] = d3dto->getSurface();
             mTargets[slot]->AddRef();
             mTargetViews[slot]->AddRef();
-            // Only assign resolve target if d3dto has a surface to give us.
-            //
-            // That usually means there is an MSAA target involved, which is why
-            // the resolve is needed to get the data out of the target.
             mResolveTargets[slot] = d3dto;
 
             if ( tex && slot == Color0 )
@@ -151,7 +148,13 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te
                mTargetSize.set( tex->getSize().x, tex->getSize().y );
                mTargetFormat = tex->getFormat();
             }
-         }           
+         }
+
+         if (mGenMips)
+         {
+            mTargetSRViews[slot] = d3dto->getSRView();
+            mTargetSRViews[slot]->AddRef();
+         }
       }
 
       // Update surface size
@@ -270,11 +273,18 @@ void GFXD3D11TextureTarget::deactivate()
    //re-gen mip maps
    for (U32 i = 0; i < 6; i++)
    {
-      ID3D11ShaderResourceView* pSRView = mTargetSRViews[GFXTextureTarget::Color0 + i];
-      if (pSRView)
-         D3D11DEVICECONTEXT->GenerateMips(pSRView);
-   }
-   
+      D3D11_TEXTURE2D_DESC desc;
+      if (mResolveTargets[GFXTextureTarget::Color0 + i])
+      {
+         mResolveTargets[GFXTextureTarget::Color0 + i]->get2DTex()->GetDesc(&desc);
+         if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS)
+         {
+            ID3D11ShaderResourceView* pSRView = mTargetSRViews[GFXTextureTarget::Color0 + i];
+            if (pSRView)
+               D3D11DEVICECONTEXT->GenerateMips(pSRView);
+         }
+      }
+   }   
 }
 
 void GFXD3D11TextureTarget::resolve()

+ 1 - 1
Engine/source/gfx/D3D11/gfxD3D11TextureManager.cpp

@@ -105,7 +105,7 @@ void GFXD3D11TextureManager::_innerCreateTexture( GFXD3D11TextureObject *retTex,
    }
 
    if( !forceMips && !retTex->mProfile->isSystemMemory() &&
-       numMipLevels == 0 &&
+       (numMipLevels == 0 || numMipLevels > 1)&&
        !(depth > 0) )
    {
       miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;

+ 15 - 4
Engine/source/gfx/gfxTextureManager.cpp

@@ -1410,17 +1410,28 @@ void GFXTextureManager::_validateTexParams( const U32 width, const U32 height,
                                           U32 &inOutNumMips, GFXFormat &inOutFormat  )
 {
    // Validate mipmap parameter. If this profile requests no mips, set mips to 1.
-   if( profile->noMip() )
+   if( profile->noMip()|| inOutNumMips == 1)
    {
       inOutNumMips = 1;
    }
-   else if( !isPow2( width ) || !isPow2( height ) )
+   else if (!isPow2(width) || !isPow2(height))
    {
       // If a texture is not power-of-2 in size for both dimensions, it must
       // have only 1 mip level.
-      inOutNumMips = 1;
+      if (profile->isRenderTarget())
+      {
+         if (inOutNumMips == 0) //auto
+            inOutNumMips = mFloor(mLog2(mMax(width, height))) + 1;
+         else if (inOutNumMips > 1) //capped
+            inOutNumMips = mMin(inOutNumMips,mFloor(mLog2(mMax(width, height))) + 1);
+         inOutNumMips = mClampF(inOutNumMips, 1, 13);
+      }
+      else
+      {
+         inOutNumMips = 1;
+      }
    }
-   
+
    // Check format, and compatibility with texture profile requirements
    bool autoGenSupp = ( inOutNumMips == 0 );
 

+ 9 - 1
Engine/source/gfx/gl/gfxGLTextureManager.cpp

@@ -116,10 +116,18 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
    {
       retTex->mMipLevels = numMipLevels > 1 ? numMipLevels : 0;
    }
-   else if(profile->testFlag(GFXTextureProfile::NoMipmap) || profile->testFlag(GFXTextureProfile::RenderTarget) || numMipLevels == 1 || retTex->mIsNPoT2)
+   else if(profile->testFlag(GFXTextureProfile::NoMipmap) || numMipLevels == 1)
    {
       retTex->mMipLevels = 1;
    }
+   else if (profile->testFlag(GFXTextureProfile::RenderTarget))
+   {
+         if (numMipLevels == 0) //auto
+            numMipLevels = mFloor(mLog2(mMax(width, height))) + 1;
+         else if (numMipLevels > 1) //capped
+            numMipLevels = mMin(numMipLevels, mFloor(mLog2(mMax(width, height))) + 1);
+         retTex->mMipLevels = mClampF(numMipLevels, 1, 13);
+   }
    else
    {
       retTex->mMipLevels = numMipLevels;

+ 16 - 8
Engine/source/postFx/postEffect.cpp

@@ -142,25 +142,23 @@ IMPLEMENT_CONOBJECT(PostEffect);
 
 GFX_ImplementTextureProfile( PostFxTextureProfile,
                             GFXTextureProfile::DiffuseMap,
-                            GFXTextureProfile::Static | GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap,
+                            GFXTextureProfile::Static | GFXTextureProfile::PreserveSize,
                             GFXTextureProfile::NONE );
 
 GFX_ImplementTextureProfile( PostFxTextureSRGBProfile,
                              GFXTextureProfile::DiffuseMap,
-                             GFXTextureProfile::Static | GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::SRGB,
+                             GFXTextureProfile::Static | GFXTextureProfile::PreserveSize | GFXTextureProfile::SRGB,
                              GFXTextureProfile::NONE);
 
 GFX_ImplementTextureProfile( VRTextureProfile,
                             GFXTextureProfile::DiffuseMap,
                             GFXTextureProfile::PreserveSize |
-                            GFXTextureProfile::RenderTarget |
-                            GFXTextureProfile::NoMipmap,
+                            GFXTextureProfile::RenderTarget,
                             GFXTextureProfile::NONE );
 
 GFX_ImplementTextureProfile( VRDepthProfile,
                             GFXTextureProfile::DiffuseMap,
                             GFXTextureProfile::PreserveSize |
-                            GFXTextureProfile::NoMipmap |
                             GFXTextureProfile::ZTarget,
                             GFXTextureProfile::NONE );
 
@@ -501,7 +499,8 @@ PostEffect::PostEffect()
       mInvCameraTransSC(NULL),
       mMatCameraToScreenSC(NULL),
       mMatScreenToCameraSC(NULL),
-      mIsCapturingSC(NULL)
+      mIsCapturingSC(NULL),
+      mMipCap(1)
 {
    dMemset( mTexSRGB, 0, sizeof(bool) * NumTextures);
    dMemset( mActiveTextures, 0, sizeof( GFXTextureObject* ) * NumTextures );
@@ -509,7 +508,7 @@ PostEffect::PostEffect()
    dMemset( mActiveTextureViewport, 0, sizeof( RectI ) * NumTextures );
    dMemset( mTexSizeSC, 0, sizeof( GFXShaderConstHandle* ) * NumTextures );
    dMemset( mRenderTargetParamsSC, 0, sizeof( GFXShaderConstHandle* ) * NumTextures );
-
+   dMemset(mMipCountSC, 0, sizeof(GFXShaderConstHandle*) * NumTextures);
 }
 
 PostEffect::~PostEffect()
@@ -538,6 +537,9 @@ void PostEffect::initPersistFields()
 
    addField( "targetScale", TypePoint2F, Offset( mTargetScale, PostEffect ),
        "If targetSize is zero this is used to set a relative size from the current target." );
+
+   addField("mipCap", TypeS32, Offset(mMipCap, PostEffect),
+      "generate up to this many mips. 0 = all, 1 = none, >1 = as specified max."); //todo: de-stupid
        
    addField( "targetSize", TypePoint2I, Offset( mTargetSize, PostEffect ), 
       "If non-zero this is used as the absolute target size." );   
@@ -760,6 +762,7 @@ void PostEffect::_setupConstants( const SceneRenderState *state )
       {
          mTexSizeSC[i] = mShader->getShaderConstHandle(String::ToString("$texSize%d", i));
          mRenderTargetParamsSC[i] = mShader->getShaderConstHandle(String::ToString("$rtParams%d",i));
+         mMipCountSC[i] = mShader->getShaderConstHandle(String::ToString("$mipCount%d", i));
       }
 
       mTargetViewportSC = mShader->getShaderConstHandle( "$targetViewport" );
@@ -843,6 +846,11 @@ void PostEffect::_setupConstants( const SceneRenderState *state )
          texSizeConst.y = (F32)mActiveTextures[i]->getHeight();
          mShaderConsts->set( mTexSizeSC[i], texSizeConst );
       }
+
+      if (mMipCountSC[i]->isValid())
+      {
+         mShaderConsts->set(mMipCountSC[i], (S32)mActiveTextures[i]->getMipLevels());
+      }
    }
 
    for ( U32 i = 0; i < NumTextures; i++ )
@@ -1265,7 +1273,7 @@ void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarg
             mTargetTex.getWidthHeight() != targetSize )
       {
          mTargetTex.set( targetSize.x, targetSize.y, mTargetFormat,
-            &PostFxTargetProfile, "PostEffect::_setupTarget" );
+            &PostFxTargetProfile, "PostEffect::_setupTarget", mMipCap);
 
          if ( mTargetClear == PFXTargetClear_OnCreate )
             *outClearTarget = true;

+ 2 - 0
Engine/source/postFx/postEffect.h

@@ -133,6 +133,7 @@ protected:
 
    GFXShaderConstHandle *mTexSizeSC[NumTextures];
    GFXShaderConstHandle *mRenderTargetParamsSC[NumTextures];
+   GFXShaderConstHandle* mMipCountSC[NumTextures];
 
    GFXShaderConstHandle *mViewportOffsetSC;
 
@@ -176,6 +177,7 @@ protected:
 
    String mTargetName;
    GFXTexHandle mTargetTex;
+   S32 mMipCap;
 
    String mTargetDepthStencilName;
    GFXTexHandle mTargetDepthStencil;

+ 28 - 49
Templates/BaseGame/game/core/postFX/scripts/HDR/HDRPostFX.tscript

@@ -117,8 +117,7 @@ singleton ShaderData( HDR_BloomUpSampleShader )
    OGLVertexShaderFile= $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
    OGLPixelShaderFile = "./HDR_Bloom/upSampleP.glsl";
    
-   samplerNames[0] = "$nxtTex";
-   samplerNames[1] = "$mipTex";
+   samplerNames[0] = "$hdrbloomDown";
    
    pixVersion = 3.0;
 };
@@ -292,13 +291,7 @@ function HDRPostFX::setShaderConsts( %this )
    %bloom.skip = (!$PostFX::HDRPostFX::enableBloom || !$pref::PostFX::EnableHDRBloom);
 
    %bloom.setShaderConst("$threshold", $PostFX::HDRPostFX::threshold);
-
-   for (%idx = 0; %idx < %this.mipsCount; %idx++)
-   {
-     %mip = %bloom.getObject(%this.mipsCount + %idx);
-     %mip.setShaderConst("$filterRadius", $PostFX::HDRPostFX::radius);
-     %mip.setShaderConst("$mipId", %idx);
-   }
+   %bloom-->upFX.setShaderConst("$filterRadius", $PostFX::HDRPostFX::radius);
 
    %strength = $PostFX::HDRPostFX::intensity;
    if (!$PostFX::HDRPostFX::enableBloom || !$pref::PostFX::EnableHDRBloom)
@@ -524,50 +517,36 @@ function HDRPostFX::SetupBloomFX( %this )
      shader = HDR_BloomThresholdShader;
      stateBlock = HDR_DownSampleStateBlock;
      texture[0] = "#hdrInitBloom";
-     target = "#hdrbloom_0";
+     target = "#hdrbloomIn";
+     mipCap = "5";
      targetFormat = %this.mipTexFormat;
    };
-  
-   %textureName = "#hdrbloom_0";
-   for (%idx = 0; %idx < %this.mipsCount; %idx++)
+   
+   %downFX = new PostEffect()
    {
-     %mipName = "hdrbloom_" @ (%idx + 1);
-     %mipFX = new PostEffect()
-     { 
-       internalName = %mipName;
-       allowReflectPass = false;
-       shader = HDR_BloomDownSampleShader;
-       stateBlock = HDR_DownSampleStateBlock;
-       texture[0] = %textureName;
-       target = "#" @ %mipName;
-       targetScale = "0.5 0.5";
-       targetFormat = %this.mipTexFormat;
-     };
-     
-     %bloomFX.add(%mipFX);
-     %textureName = "#" @ %mipName;
-   }
+      internalName = "downFX";
+      allowReflectPass = false;
+      shader = HDR_BloomDownSampleShader;
+      stateBlock = HDR_DownSampleStateBlock;
+      texture[0] = "#hdrbloomIn";
+      target = "#hdrbloomDown";
+      mipCap = "5";
+      targetScale = "0.5 0.5";
+      targetFormat = %this.mipTexFormat;
+   };
+   %bloomFX.add(%downFX);
    
-   for (%idx = %this.mipsCount - 1; %idx >= 0; %idx--)
+   %upFX = new PostEffect()
    {
-     %nxt = "#hdrbloom_" @ %idx;
-     %mipName = "hdrbloom_up_" @ %idx;
-     
-     %mipFX = new PostEffect()
-     {
-       internalName = %mipName;
-       allowReflectPass = false;
-       shader = HDR_BloomUpSampleShader;
-       stateBlock = HDR_DownSampleStateBlock;
-       texture[0] = %nxt;
-       texture[1] = %textureName;
-       target = "#" @ %mipName;
-       targetFormat = %this.mipTexFormat;
-     };
-     
-     %bloomFX.add(%mipFX);
-     %textureName = "#" @ %mipName;
-   }
+      internalName = "upFX";
+      allowReflectPass = false;
+      shader = HDR_BloomUpSampleShader;
+      stateBlock = HDR_DownSampleStateBlock;
+      texture[0] = "#hdrbloomDown";
+      target = "#hdrbloomUp";
+      targetFormat = %this.mipTexFormat;
+   };
+   %bloomFX.add(%upFX);
 
    %finalFX = new PostEffect()
    {
@@ -575,7 +554,7 @@ function HDRPostFX::SetupBloomFX( %this )
      allowReflectPass = false;
      shader = HDR_BloomDirtShader;
      stateBlock = HDR_LensDirtStateBlock;
-     texture[0] = "#hdrbloom_up_0";
+     texture[0] = "#hdrbloomUp";
      target = "#hdrbloom_end";
      targetFormat = %this.mipTexFormat;
    };

+ 49 - 42
Templates/BaseGame/game/core/postFX/scripts/HDR/HDR_Bloom/downSampleP.glsl

@@ -28,59 +28,66 @@
 #line 28
 uniform sampler2D inputTex;
 uniform vec2 oneOverTargetSize;
-uniform int mipId;
+uniform int mipCount0;
 
 out vec4 OUT_col;
  
 void main()
 {
   vec4 downSample = vec4(0, 0, 0, 0);
-  float x = oneOverTargetSize.x;
-  float y = oneOverTargetSize.y;
+  vec4 finalOut = float4(0, 0, 0, 0);
+
+  for (int mipId = 0; mipId<mipCount0; mipId++)
+  {
+    float mipWeight = float(mipId)/float(mipCount0);
+    float mipIDf = float(mipId);
+    float x = oneOverTargetSize.x*pow(0.5, mipId);
+    float y = oneOverTargetSize.y*pow(0.5, mipId);
   
-  vec3 a = texture(inputTex, vec2(IN_uv0.x - 2 * x, IN_uv0.y + 2 * y)).rgb;
-  vec3 b = texture(inputTex, vec2(IN_uv0.x,         IN_uv0.y + 2 * y)).rgb;
-  vec3 c = texture(inputTex, vec2(IN_uv0.x + 2 * x, IN_uv0.y + 2 * y)).rgb;
+    vec3 a = textureLod(inputTex, vec2(IN_uv0.x - 2 * x, IN_uv0.y + 2 * y), mipIDf).rgb;
+    vec3 b = textureLod(inputTex, vec2(IN_uv0.x,         IN_uv0.y + 2 * y), mipIDf).rgb;
+    vec3 c = textureLod(inputTex, vec2(IN_uv0.x + 2 * x, IN_uv0.y + 2 * y), mipIDf).rgb;
 
-  vec3 d = texture(inputTex, vec2(IN_uv0.x - 2 * x, IN_uv0.y)).rgb;
-  vec3 e = texture(inputTex, vec2(IN_uv0.x,         IN_uv0.y)).rgb;
-  vec3 f = texture(inputTex, vec2(IN_uv0.x + 2 * x, IN_uv0.y)).rgb;
+    vec3 d = textureLod(inputTex, vec2(IN_uv0.x - 2 * x, IN_uv0.y), mipIDf).rgb;
+    vec3 e = textureLod(inputTex, vec2(IN_uv0.x,         IN_uv0.y), mipIDf).rgb;
+    vec3 f = textureLod(inputTex, vec2(IN_uv0.x + 2 * x, IN_uv0.y), mipIDf).rgb;
 
-  vec3 g = texture(inputTex, vec2(IN_uv0.x - 2 * x, IN_uv0.y - 2 * y)).rgb;
-  vec3 h = texture(inputTex, vec2(IN_uv0.x,         IN_uv0.y - 2 * y)).rgb;
-  vec3 i = texture(inputTex, vec2(IN_uv0.x + 2 * x, IN_uv0.y - 2 * y)).rgb;
+    vec3 g = textureLod(inputTex, vec2(IN_uv0.x - 2 * x, IN_uv0.y - 2 * y), mipIDf).rgb;
+    vec3 h = textureLod(inputTex, vec2(IN_uv0.x,         IN_uv0.y - 2 * y), mipIDf).rgb;
+    vec3 i = textureLod(inputTex, vec2(IN_uv0.x + 2 * x, IN_uv0.y - 2 * y), mipIDf).rgb;
 
-  vec3 j = texture(inputTex, vec2(IN_uv0.x - x, IN_uv0.y + y)).rgb;
-  vec3 k = texture(inputTex, vec2(IN_uv0.x + x, IN_uv0.y + y)).rgb;
-  vec3 l = texture(inputTex, vec2(IN_uv0.x - x, IN_uv0.y - y)).rgb;
-  vec3 m = texture(inputTex, vec2(IN_uv0.x + x, IN_uv0.y - y)).rgb;
+    vec3 j = textureLod(inputTex, vec2(IN_uv0.x - x, IN_uv0.y + y), mipIDf).rgb;
+    vec3 k = textureLod(inputTex, vec2(IN_uv0.x + x, IN_uv0.y + y), mipIDf).rgb;
+    vec3 l = textureLod(inputTex, vec2(IN_uv0.x - x, IN_uv0.y - y), mipIDf).rgb;
+    vec3 m = textureLod(inputTex, vec2(IN_uv0.x + x, IN_uv0.y - y), mipIDf).rgb;
 
-  vec3 group[5];
-  switch (mipId)
-  {
-	case 0:
-		group[0] = (a+b+d+e) * (0.125/4.0);
-		group[1] = (b+c+e+f) * (0.125/4.0);
-		group[2] = (d+e+g+h) * (0.125/4.0);
-		group[3] = (e+f+h+i) * (0.125/4.0);
-		group[4] = (j+k+l+m) * (0.5/4.0);
-		group[0] *= KarisAverage(group[0]);
-		group[1] *= KarisAverage(group[1]);
-		group[2] *= KarisAverage(group[2]);
-		group[3] *= KarisAverage(group[3]);
-		group[4] *= KarisAverage(group[4]);
-		downSample.rgb = group[0]+group[1]+group[2]+group[3]+group[4];
-		downSample.a = 1.0;
-		break;
+    vec3 group[5];
+    switch (mipId)
+    {
+        case 0:
+            group[0] = (a+b+d+e) * (0.125/4.0);
+            group[1] = (b+c+e+f) * (0.125/4.0);
+            group[2] = (d+e+g+h) * (0.125/4.0);
+            group[3] = (e+f+h+i) * (0.125/4.0);
+            group[4] = (j+k+l+m) * (0.5/4.0);
+            group[0] *= KarisAverage(group[0]);
+            group[1] *= KarisAverage(group[1]);
+            group[2] *= KarisAverage(group[2]);
+            group[3] *= KarisAverage(group[3]);
+            group[4] *= KarisAverage(group[4]);
+            downSample.rgb = group[0]+group[1]+group[2]+group[3]+group[4];
+            downSample.a = 1.0;
+            break;
 		
-	default:
-		downSample.rgb = e*0.125;
-		downSample.rgb += (a+c+g+i)*0.03125;
-		downSample.rgb += (b+d+f+h)*0.0625;
-		downSample.rgb += (j+k+l+m)*0.125;
-		downSample.a = 1.0;
-		break;
+        default:
+            downSample.rgb = e*mipWeight;
+            downSample.rgb += (a+c+g+i)*mipWeight*0.125;
+            downSample.rgb += (b+d+f+h)*mipWeight*0.25;
+            downSample.rgb += (j+k+l+m)*mipWeight*0.5;
+            downSample.a = 1.0;
+            break;
+    }
+    finalOut += downSample*(1.0-mipWeight);
   }
-  
-  OUT_col = downSample;
+  OUT_col = finalOut;
 }

+ 49 - 43
Templates/BaseGame/game/core/postFX/scripts/HDR/HDR_Bloom/downSampleP.hlsl

@@ -25,57 +25,63 @@
 
 TORQUE_UNIFORM_SAMPLER2D(inputTex, 0);
 uniform float2 oneOverTargetSize;
-uniform int mipId;
+uniform int mipCount0;
  
 float4 main(PFXVertToPix IN) : TORQUE_TARGET0
 {
-  float4 downSample = float4(0, 0, 0, 0);
-  float x = oneOverTargetSize.x;
-  float y = oneOverTargetSize.y;
+  float4 downSample = float4(0, 0, 0, 0);  
+  float4 finalOut = float4(0, 0, 0, 0);
   
-  float3 a = TORQUE_TEX2D(inputTex, float2(IN.uv0.x - 2 * x, IN.uv0.y + 2*y)).rgb;
-  float3 b = TORQUE_TEX2D(inputTex, float2(IN.uv0.x		   , IN.uv0.y + 2*y)).rgb;
-  float3 c = TORQUE_TEX2D(inputTex, float2(IN.uv0.x + 2 * x, IN.uv0.y + 2*y)).rgb;
+  for (int mipId = 0; mipId<mipCount0; mipId++)
+  {
+    float mipWeight = float(mipId)/float(mipCount0);
+    float x = oneOverTargetSize.x*pow(0.5, mipId);
+    float y = oneOverTargetSize.y*pow(0.5, mipId);
+    
+    float3 a = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x - 2 * x, IN.uv0.y + 2*y, 0, mipId)).rgb;
+    float3 b = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x		   , IN.uv0.y + 2*y, 0, mipId)).rgb;
+    float3 c = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x + 2 * x, IN.uv0.y + 2*y, 0, mipId)).rgb;
   
-  float3 d = TORQUE_TEX2D(inputTex, float2(IN.uv0.x - 2 * x, IN.uv0.y)).rgb;
-  float3 e = TORQUE_TEX2D(inputTex, float2(IN.uv0.x		   , IN.uv0.y)).rgb;
-  float3 f = TORQUE_TEX2D(inputTex, float2(IN.uv0.x + 2 * x, IN.uv0.y)).rgb;
+    float3 d = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x - 2 * x, IN.uv0.y, 0, mipId)).rgb;
+    float3 e = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x		   , IN.uv0.y, 0, mipId)).rgb;
+    float3 f = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x + 2 * x, IN.uv0.y, 0, mipId)).rgb;
   
-  float3 g = TORQUE_TEX2D(inputTex, float2(IN.uv0.x - 2 * x, IN.uv0.y - 2*y)).rgb;
-  float3 h = TORQUE_TEX2D(inputTex, float2(IN.uv0.x		   , IN.uv0.y - 2*y)).rgb;
-  float3 i = TORQUE_TEX2D(inputTex, float2(IN.uv0.x + 2 * x, IN.uv0.y - 2*y)).rgb;
+    float3 g = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x - 2 * x, IN.uv0.y - 2*y, 0, mipId)).rgb;
+    float3 h = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x		   , IN.uv0.y - 2*y, 0, mipId)).rgb;
+    float3 i = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x + 2 * x, IN.uv0.y - 2*y, 0, mipId)).rgb;
   
-  float3 j = TORQUE_TEX2D(inputTex, float2(IN.uv0.x - x, IN.uv0.y + y)).rgb;
-  float3 k = TORQUE_TEX2D(inputTex, float2(IN.uv0.x + x, IN.uv0.y + y)).rgb;
-  float3 l = TORQUE_TEX2D(inputTex, float2(IN.uv0.x - x, IN.uv0.y - y)).rgb;
-  float3 m = TORQUE_TEX2D(inputTex, float2(IN.uv0.x + x, IN.uv0.y - y)).rgb;
+    float3 j = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x - x, IN.uv0.y + y, 0, mipId)).rgb;
+    float3 k = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x + x, IN.uv0.y + y, 0, mipId)).rgb;
+    float3 l = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x - x, IN.uv0.y - y, 0, mipId)).rgb;
+    float3 m = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x + x, IN.uv0.y - y, 0, mipId)).rgb;
   
-  float3 group[5];
-  switch (mipId)
-  {
-	case 0:
-		group[0] = (a+b+d+e) * (0.125f/4.0f);
-		group[1] = (b+c+e+f) * (0.125f/4.0f);
-		group[2] = (d+e+g+h) * (0.125f/4.0f);
-		group[3] = (e+f+h+i) * (0.125f/4.0f);
-		group[4] = (j+k+l+m) * (0.5f/4.0f);
-		group[0] *= KarisAverage(group[0]);
-		group[1] *= KarisAverage(group[1]);
-		group[2] *= KarisAverage(group[2]);
-		group[3] *= KarisAverage(group[3]);
-		group[4] *= KarisAverage(group[4]);
-		downSample.rgb = group[0]+group[1]+group[2]+group[3]+group[4];
-		downSample.a = 1.0;
-		break;
+    float3 group[5];
+    switch (mipId)
+    {
+        case 0:
+            group[0] = (a+b+d+e) * (0.125f/4.0f);
+            group[1] = (b+c+e+f) * (0.125f/4.0f);
+            group[2] = (d+e+g+h) * (0.125f/4.0f);
+            group[3] = (e+f+h+i) * (0.125f/4.0f);
+            group[4] = (j+k+l+m) * (0.5f/4.0f);
+            group[0] *= KarisAverage(group[0]);
+            group[1] *= KarisAverage(group[1]);
+            group[2] *= KarisAverage(group[2]);
+            group[3] *= KarisAverage(group[3]);
+            group[4] *= KarisAverage(group[4]);
+            downSample.rgb = group[0]+group[1]+group[2]+group[3]+group[4];
+            downSample.a = 1.0;
+            break;
 		
-	default:
-		downSample.rgb = e*0.125;
-		downSample.rgb += (a+c+g+i)*0.03125;
-		downSample.rgb += (b+d+f+h)*0.0625;
-		downSample.rgb += (j+k+l+m)*0.125;
-		downSample.a = 1.0;
-		break;
+        default:
+            downSample.rgb = e*mipWeight;
+            downSample.rgb += (a+c+g+i)*mipWeight*0.125;
+            downSample.rgb += (b+d+f+h)*mipWeight*0.25;
+            downSample.rgb += (j+k+l+m)*mipWeight*0.5;
+            downSample.a = 1.0;
+            break;
+    }
+    finalOut += downSample*(1.0-mipWeight);
   }
-  
-  return downSample;
+  return float4(finalOut.rgb,1);
 }

+ 26 - 21
Templates/BaseGame/game/core/postFX/scripts/HDR/HDR_Bloom/upSampleP.glsl

@@ -24,38 +24,43 @@
 #include "core/rendering/shaders/postFX/gl/postFx.glsl"
 #include "shadergen:/autogenConditioners.h"
 #line 26
-uniform sampler2D nxtTex;
-uniform sampler2D mipTex;
+uniform sampler2D hdrbloomDown;
 uniform float filterRadius;
 uniform vec2 oneOverTargetSize;
+uniform int mipCount0;
 
 out vec4 OUT_col;
 
 void main()
 {
   vec4 upSample = vec4(0, 0, 0, 0);
-  float x = filterRadius*oneOverTargetSize.x;
-  float y = filterRadius*oneOverTargetSize.y;
+  vec4 finalOut = float4(0, 0, 0, 0);
+  for (int mipId = 0; mipId<mipCount0; mipId++)
+  {    
+    float x = filterRadius*oneOverTargetSize.x*pow(0.5, mipId);
+    float y = filterRadius*oneOverTargetSize.y*pow(0.5, mipId);
+    float mipIDf = float(mipId);
 
-  vec3 a = texture(mipTex, vec2(IN_uv1.x - x, IN_uv1.y + y)).rgb;
-  vec3 b = texture(mipTex, vec2(IN_uv1.x,     IN_uv1.y + y)).rgb;
-  vec3 c = texture(mipTex, vec2(IN_uv1.x + x, IN_uv1.y + y)).rgb;
+    vec3 a = textureLod(hdrbloomDown, vec2(IN_uv0.x - x, IN_uv0.y + y), mipIDf).rgb;
+    vec3 b = textureLod(hdrbloomDown, vec2(IN_uv0.x,     IN_uv0.y + y), mipIDf).rgb;
+    vec3 c = textureLod(hdrbloomDown, vec2(IN_uv0.x + x, IN_uv0.y + y), mipIDf).rgb;
 
-  vec3 d = texture(mipTex, vec2(IN_uv1.x - x, IN_uv1.y)).rgb;
-  vec3 e = texture(mipTex, vec2(IN_uv1.x,     IN_uv1.y)).rgb;
-  vec3 f = texture(mipTex, vec2(IN_uv1.x + x, IN_uv1.y)).rgb;
+    vec3 d = textureLod(hdrbloomDown, vec2(IN_uv0.x - x, IN_uv0.y), mipIDf).rgb;
+    vec3 e = textureLod(hdrbloomDown, vec2(IN_uv0.x,     IN_uv0.y), mipIDf).rgb;
+    vec3 f = textureLod(hdrbloomDown, vec2(IN_uv0.x + x, IN_uv0.y), mipIDf).rgb;
 
-  vec3 g = texture(mipTex, vec2(IN_uv1.x - x, IN_uv1.y - y)).rgb;
-  vec3 h = texture(mipTex, vec2(IN_uv1.x,     IN_uv1.y - y)).rgb;
-  vec3 i = texture(mipTex, vec2(IN_uv1.x + x, IN_uv1.y - y)).rgb;
+    vec3 g = textureLod(hdrbloomDown, vec2(IN_uv0.x - x, IN_uv0.y - y), mipIDf).rgb;
+    vec3 h = textureLod(hdrbloomDown, vec2(IN_uv0.x,     IN_uv0.y - y), mipIDf).rgb;
+    vec3 i = textureLod(hdrbloomDown, vec2(IN_uv0.x + x, IN_uv0.y - y), mipIDf).rgb;
 
-  upSample.rgb = e*4.0;
-  upSample.rgb += (b+d+f+h)*2.0;
-  upSample.rgb += (a+c+g+i);
-  upSample.rgb *= 1.0 / 16.0; 
-  upSample.a = 1.0;
+    upSample.rgb = e*4.0;
+    upSample.rgb += (b+d+f+h)*2.0;
+    upSample.rgb += (a+c+g+i);
+    upSample.rgb *= 1.0 / 16.0; 
+    finalOut += upSample;
+ } 
+ finalOut /= mipCount0;
+ finalOut.a = 1.0;  
   
-  upSample = texture(nxtTex, IN_uv0) + upSample;
-  
-  OUT_col = upSample;
+  OUT_col = finalOut;
 }

+ 26 - 22
Templates/BaseGame/game/core/postFX/scripts/HDR/HDR_Bloom/upSampleP.hlsl

@@ -22,36 +22,40 @@
 
 #include "core/rendering/shaders/postFX/postFx.hlsl"
 
-TORQUE_UNIFORM_SAMPLER2D(nxtTex, 0);
-TORQUE_UNIFORM_SAMPLER2D(mipTex, 1);
+TORQUE_UNIFORM_SAMPLER2D(hdrbloomDown, 0);
 uniform float filterRadius;
 uniform float2 oneOverTargetSize;
+uniform int mipCount0;
 
 float4 main(PFXVertToPix IN) : TORQUE_TARGET0
 {
   float4 upSample = float4(0, 0, 0, 0);
-  float x = filterRadius*oneOverTargetSize.x;
-  float y = filterRadius*oneOverTargetSize.y;
+  float4 finalOut = float4(0, 0, 0, 0);
+  for (int mipId = 0; mipId<mipCount0; mipId++)
+  {
+    float x = filterRadius*oneOverTargetSize.x*pow(0.5, mipId);
+    float y = filterRadius*oneOverTargetSize.y*pow(0.5, mipId);
   
-  float3 a = TORQUE_TEX2D(mipTex, float2(IN.uv1.x - x, IN.uv1.y + y)).rgb;
-  float3 b = TORQUE_TEX2D(mipTex, float2(IN.uv1.x,     IN.uv1.y + y)).rgb;
-  float3 c = TORQUE_TEX2D(mipTex, float2(IN.uv1.x + x, IN.uv1.y + y)).rgb;
+    float3 a = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x - x, IN.uv0.y + y, 0, mipId)).rgb;
+    float3 b = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x,     IN.uv0.y + y, 0, mipId)).rgb;
+    float3 c = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x + x, IN.uv0.y + y, 0, mipId)).rgb;
   
-  float3 d = TORQUE_TEX2D(mipTex, float2(IN.uv1.x - x, IN.uv1.y)).rgb;
-  float3 e = TORQUE_TEX2D(mipTex, float2(IN.uv1.x,     IN.uv1.y)).rgb;
-  float3 f = TORQUE_TEX2D(mipTex, float2(IN.uv1.x + x, IN.uv1.y)).rgb;
+    float3 d = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x - x, IN.uv0.y, 0, mipId)).rgb;
+    float3 e = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x,     IN.uv0.y, 0, mipId)).rgb;
+    float3 f = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x + x, IN.uv0.y, 0, mipId)).rgb;
 
-  float3 g = TORQUE_TEX2D(mipTex, float2(IN.uv1.x - x, IN.uv1.y - y)).rgb;
-  float3 h = TORQUE_TEX2D(mipTex, float2(IN.uv1.x,     IN.uv1.y - y)).rgb;
-  float3 i = TORQUE_TEX2D(mipTex, float2(IN.uv1.x + x, IN.uv1.y - y)).rgb;
+    float3 g = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x - x, IN.uv0.y - y, 0, mipId)).rgb;
+    float3 h = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x,     IN.uv0.y - y, 0, mipId)).rgb;
+    float3 i = TORQUE_TEX2DLOD(hdrbloomDown, float4(IN.uv0.x + x, IN.uv0.y - y, 0, mipId)).rgb;
   
-  upSample.rgb = e*4.0;
-  upSample.rgb += (b+d+f+h)*2.0;
-  upSample.rgb += (a+c+g+i);
-  upSample.rgb *= 1.0 / 16.0;
-  upSample.a = 1.0;
-  
-  upSample = TORQUE_TEX2D(nxtTex, IN.uv0) + upSample;
-  
-  return upSample;
+    upSample.rgb = e*4.0;
+    upSample.rgb += (b+d+f+h)*2.0;
+    upSample.rgb += (a+c+g+i);
+    upSample.rgb *= 1.0 / 16.0;
+    finalOut += upSample;
+ } 
+ finalOut /= mipCount0;
+ finalOut.a = 1.0;
+   
+  return float4(finalOut.rgb,1);
 }