mipwork, laregly courtesy of @mmarauder2k9-torque

This commit is contained in:
AzaezelX 2025-08-03 20:25:31 -05:00
parent 81504fb089
commit cacd8a6064
8 changed files with 128 additions and 128 deletions

View file

@ -151,7 +151,13 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te
mTargetSize.set( tex->getSize().x, tex->getSize().y ); mTargetSize.set( tex->getSize().x, tex->getSize().y );
mTargetFormat = tex->getFormat(); mTargetFormat = tex->getFormat();
} }
} }
if (mGenMips)
{
mTargetSRViews[slot] = d3dto->getSRView();
mTargetSRViews[slot]->AddRef();
}
} }
// Update surface size // Update surface size

View file

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

View file

@ -1414,13 +1414,13 @@ void GFXTextureManager::_validateTexParams( const U32 width, const U32 height,
{ {
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 // If a texture is not power-of-2 in size for both dimensions, it must
// have only 1 mip level. // have only 1 mip level.
inOutNumMips = 1; inOutNumMips = mFloor(mLog2(mMax(width, height))) + 1;
} }
// Check format, and compatibility with texture profile requirements // Check format, and compatibility with texture profile requirements
bool autoGenSupp = ( inOutNumMips == 0 ); bool autoGenSupp = ( inOutNumMips == 0 );

View file

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

View file

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

View file

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

View file

@ -25,7 +25,7 @@
TORQUE_UNIFORM_SAMPLER2D(inputTex, 0); TORQUE_UNIFORM_SAMPLER2D(inputTex, 0);
uniform float2 oneOverTargetSize; uniform float2 oneOverTargetSize;
uniform int mipId; uniform int mipCount0;
float4 main(PFXVertToPix IN) : TORQUE_TARGET0 float4 main(PFXVertToPix IN) : TORQUE_TARGET0
{ {
@ -33,49 +33,51 @@ float4 main(PFXVertToPix IN) : TORQUE_TARGET0
float x = oneOverTargetSize.x; float x = oneOverTargetSize.x;
float y = oneOverTargetSize.y; float y = oneOverTargetSize.y;
float3 a = TORQUE_TEX2D(inputTex, float2(IN.uv0.x - 2 * x, IN.uv0.y + 2*y)).rgb; for (int mipId = 0; mipId<mipCount0; mipId++)
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;
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 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 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 group[5];
switch (mipId)
{ {
case 0: float3 a = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x - 2 * x, IN.uv0.y + 2*y, 0, mipId)).rgb;
group[0] = (a+b+d+e) * (0.125f/4.0f); float3 b = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x , IN.uv0.y + 2*y, 0, mipId)).rgb;
group[1] = (b+c+e+f) * (0.125f/4.0f); float3 c = TORQUE_TEX2DLOD(inputTex, float4(IN.uv0.x + 2 * x, IN.uv0.y + 2*y, 0, mipId)).rgb;
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;
}
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_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_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;
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;
}
}
return downSample; return downSample;
} }

View file

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