I've written an HLSL shader to add mipmaps to a cubemap texture, but I can't work out how to get rid of those damned seams!
Here's the code I'm currently using -- anyone got any ideas how I could implement an edge fix similar to that used by CubeMapGen?
#include "../Shared/Common.fxh"
#include "../Shared/CommonVariables.fxh"
#include "../Shared/CommonFunctions.fxh"
#undef BINDTEXTURE
#if defined GAME || defined M2_USE_DXRENDERER
#define BINDTEXTURE(a)
#else
#define BINDTEXTURE(a) Texture = (a);
#endif
//half pixel dimensions in UV space (used for an offset in mip generation);
float2 g_TexSize;
//the LOD number to sampled from texture
int g_LODNum;
//the face to sample on a cube map
int g_CubeMapFaceNum;
texture TexRaw : TEXTURE
<
int texcoord = 0;
int MapChannel = 1;
int samplerId = 0;
string UIName = "TexRaw";
>;
sampler samplerRaw : register( s0 ) = sampler_state
{
BINDTEXTURE(Tex0)
};
/***************************************
VERTEXDECL
***************************************/
int vertexInput : VERTEXDECL
<
string POSITION = "POSITION0";
string COLOUR = "COLOR0";
string TEXCOORD0 = "TEXCOORD0";
string TECHNIQUE0 = "defaultTechnique";
> = 0;
struct VS_Input
{
float4 m_position : POSITION0;
float4 m_colour : COLOR0;
float2 m_texCoord0 : TEXCOORD0;
};
struct VS_Output_Cube
{
float4 m_position : POSITION0;
float4 m_texCoord0 : TEXCOORD0;
float4 m_rollover : TEXCOORD1;
};
half4 PS_Sample_Down_Cube( VS_Output_Cube In ) : COLOR
{
float edgeLimit = 4.0/max(g_TexSize.x, g_TexSize.y);
float4 m_texCoord0 = In.m_texCoord0;
float4 m_texCoord1 = In.m_texCoord0;
float m_weighting = 0.0;
float3 limitsTest = m_texCoord0.xyz + In.m_rollover.xyz; // remove the fixed 1
float3 absLimitsTest = abs(limitsTest)+edgeLimit-1.0;
float3 limitsTestSigns = sign(limitsTest);
if (absLimitsTest.x > 0.0)
{
m_texCoord1.x = limitsTestSigns.x;
m_texCoord1 += edgeLimit*In.m_rollover;
m_weighting = min(0.5*absLimitsTest.x/edgeLimit);
m_texCoord0.x = limitsTestSigns.x*(1.0 - edgeLimit);
}
if (absLimitsTest.y > 0.0)
{
m_texCoord1.y = limitsTestSigns.y;
m_texCoord1 += edgeLimit*In.m_rollover;
m_weighting = max(m_weighting, 0.5*absLimitsTest.y/edgeLimit);
m_texCoord0.y = limitsTestSigns.y*(1.0 - edgeLimit);
}
if (absLimitsTest.z > 0.0)
{
m_texCoord1.z = limitsTestSigns.z;
m_texCoord1 += edgeLimit*In.m_rollover;
m_weighting = max(m_weighting, 0.5*absLimitsTest.z/edgeLimit);
m_texCoord0.z = limitsTestSigns.z*(1.0 - edgeLimit);
}
float4 diffuse = Gamma((1.0 - m_weighting)*Degamma(texCUBElod(samplerRaw, m_texCoord0)) + m_weighting*Degamma(texCUBElod(samplerRaw, m_texCoord1)));
return diffuse;
}
VS_Output_Cube ScreenSpaceShaderVS_Cube( VS_Input In )
{
VS_Output_Cube Out;
Out.m_position = In.m_position;
Out.m_position.z = In.m_position.z * (1.0f / 16777215.0f);
float2 rescaledTexCoord = (In.m_texCoord0.xy*2.0f - float2(1, 1));
#ifdef PC
rescaledTexCoord += 1.0/g_TexSize;
#endif
if ( g_CubeMapFaceNum == 1)
{
Out.m_texCoord0 = float4(-1.0, -rescaledTexCoord.y, rescaledTexCoord.x, g_LODNum);
Out.m_rollover = float4(1.0, 0.0, 0.0, 0.0);
}
else if ( g_CubeMapFaceNum == 2)
{
Out.m_texCoord0 = float4(rescaledTexCoord.x, 1.0, rescaledTexCoord.y, g_LODNum);
Out.m_rollover = float4(0.0, -1.0, 0.0, 0.0);
}
else if ( g_CubeMapFaceNum == 3)
{
Out.m_texCoord0 = float4(rescaledTexCoord.x, -1.0, -rescaledTexCoord.y, g_LODNum);
Out.m_rollover = float4(0.0, 1.0, 0.0, 0.0);
}
else if ( g_CubeMapFaceNum == 4)
{
Out.m_texCoord0 = float4(rescaledTexCoord.x, -rescaledTexCoord.y, 1.0, g_LODNum);
Out.m_rollover = float4(0.0, 0.0, -1.0, 0.0);
}
else if ( g_CubeMapFaceNum == 5)
{
Out.m_texCoord0 = float4(-rescaledTexCoord.x, -rescaledTexCoord.y, -1.0, g_LODNum);
Out.m_rollover = float4(0.0, 0.0, 1.0, 0.0);
}
else
{
Out.m_texCoord0 = float4(1.0, -rescaledTexCoord.y, -rescaledTexCoord.x, g_LODNum);
Out.m_rollover = float4(-1.0, 0.0, 0.0, 0.0);
}
return Out;
}
technique GenMipMapsCube
<
string SCE_VP_COMPILE_FLAGS=" ";
string SCE_FP_COMPILE_FLAGS=" ";
DECLARE_HDR();
>
{
pass p0
{
AlphaTestEnable = False;
AlphaBlendEnable = False;
AlphaRef = 1;
ColorWriteEnable = Red|Green|Blue|Alpha;
VERTEXSHADER = compile VS_3_0 ScreenSpaceShaderVS_Cube();
PIXELSHADER = compile PS_3_0 PS_Sample_Down_Cube();
}
}