0 Replies Latest reply on Dec 21, 2010 3:33 PM by GCarty

    CubeMapGen-like functionality in HLSL

    GCarty

      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();
          }
      }