コード例 #1
0
    private static void Resize3D(Texture srcTexture, int srcMipIndex, int srcArrayOrFaceIndex, Texture dstTexture, int dstMipIndex, int dstArrayOrFaceIndex, Filter filter, bool alphaTransparency, TextureAddressMode wrapMode)
    {
      int srcIndex = srcTexture.GetImageIndex(srcMipIndex, srcArrayOrFaceIndex, 0);
      int srcWidth = srcTexture.Images[srcIndex].Width;
      int srcHeight = srcTexture.Images[srcIndex].Height;
      int srcDepth = srcTexture.GetDepth(srcMipIndex);

      int dstIndex = dstTexture.GetImageIndex(dstMipIndex, dstArrayOrFaceIndex, 0);
      int dstWidth = dstTexture.Images[dstIndex].Width;
      int dstHeight = dstTexture.Images[dstIndex].Height;
      int dstDepth = dstTexture.GetDepth(dstMipIndex);

      // Resize volume.
      var kernelX = new PolyphaseKernel(filter, srcWidth, dstWidth, 32);
      var kernelY = new PolyphaseKernel(filter, srcHeight, dstHeight, 32);
      var kernelZ = new PolyphaseKernel(filter, srcDepth, dstDepth, 32);

      var tmpTexture = new Texture(new TextureDescription
      {
        Dimension = TextureDimension.Texture3D,
        Width = dstWidth,
        Height = srcHeight,
        Depth = srcDepth,
        MipLevels = 1,
        ArraySize = 1,
        Format = DataFormat.R32G32B32A32_FLOAT
      });
      var tmpTexture2 = new Texture(new TextureDescription
      {
        Dimension = TextureDimension.Texture3D,
        Width = dstWidth,
        Height = dstHeight,
        Depth = srcDepth,
        MipLevels = 1,
        ArraySize = 1,
        Format = DataFormat.R32G32B32A32_FLOAT
      });

      // ReSharper disable AccessToDisposedClosure
      using (var srcVolume = new VolumeAccessor(srcTexture, srcMipIndex, srcArrayOrFaceIndex))
      using (var tmpVolume = new VolumeAccessor(tmpTexture, 0, 0))
      using (var tmpVolume2 = new VolumeAccessor(tmpTexture2, 0, 0))
      using (var dstVolume = new VolumeAccessor(dstTexture, dstMipIndex, dstArrayOrFaceIndex))
      {
        // Resize horizontally: srcVolume --> tmpVolume
        {
          float scale = (float)tmpVolume.Width / srcVolume.Width;
          float inverseScale = 1.0f / scale;

#if SINGLE_THREADED
          for (int z = 0; z < tmpVolume.Depth; z++)
#else
          Parallel.For(0, tmpVolume.Depth, z =>
#endif
          {
            for (int y = 0; y < tmpVolume.Height; y++)
            {
              // Apply polyphase kernel horizontally.
              for (int x = 0; x < tmpVolume.Width; x++)
              {
                float center = (x + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelX.Width);
                int right = (int)Math.Ceiling(center + kernelX.Width);
                Debug.Assert(right - left <= kernelX.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelX.WindowSize; i++)
                {
                  Vector4F color = srcVolume.GetPixel(left + i, y, z, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelX.Weights[x, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                tmpVolume.SetPixel(x, y, z, sum);
              }
            }
          }
#if !SINGLE_THREADED
          );
#endif
        }

        // Resize vertically: tmpVolume --> tmpVolume2
        {
          float scale = (float)tmpVolume2.Height / tmpVolume.Height;
          float inverseScale = 1.0f / scale;

#if SINGLE_THREADED
          for (int z = 0; z < tmpVolume2.Depth; z++)
#else
          Parallel.For(0, tmpVolume2.Depth, z =>
#endif
          {
            for (int x = 0; x < tmpVolume2.Width; x++)
            {
              // Apply polyphase kernel vertically.
              for (int y = 0; y < tmpVolume2.Height; y++)
              {
                float center = (y + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelY.Width);
                int right = (int)Math.Ceiling(center + kernelY.Width);
                Debug.Assert(right - left <= kernelY.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelY.WindowSize; i++)
                {
                  Vector4F color = tmpVolume.GetPixel(x, left + i, z, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelY.Weights[y, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                tmpVolume2.SetPixel(x, y, z, sum);
              }
            }
          }
#if !SINGLE_THREADED
          );
#endif
        }

        // Resize depth: tmpVolume2 --> dstVolume
        {
          float scale = (float)dstVolume.Depth / tmpVolume2.Depth;
          float inverseScale = 1.0f / scale;

#if SINGLE_THREADED
          for (int y = 0; y < dstVolume.Height; y++)
#else
          Parallel.For(0, dstVolume.Height, y =>
#endif
          {
            for (int x = 0; x < dstVolume.Width; x++)
            {
              // Apply polyphase kernel along z direction.
              for (int z = 0; z < dstVolume.Depth; z++)
              {
                float center = (z + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelZ.Width);
                int right = (int)Math.Ceiling(center + kernelZ.Width);
                Debug.Assert(right - left <= kernelZ.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelZ.WindowSize; i++)
                {
                  Vector4F color = tmpVolume2.GetPixel(x, y, left + i, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelZ.Weights[z, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                dstVolume.SetPixel(x, y, z, sum);
              }
            }
          }
#if !SINGLE_THREADED
          );
#endif
        }
      }
      // ReSharper restore AccessToDisposedClosure
    }
コード例 #2
0
        private static void Resize3D(Texture srcTexture, int srcMipIndex, int srcArrayOrFaceIndex, Texture dstTexture, int dstMipIndex, int dstArrayOrFaceIndex, Filter filter, bool alphaTransparency, TextureAddressMode wrapMode)
        {
            int srcIndex = srcTexture.GetImageIndex(srcMipIndex, srcArrayOrFaceIndex, 0);
              int srcWidth = srcTexture.Images[srcIndex].Width;
              int srcHeight = srcTexture.Images[srcIndex].Height;
              int srcDepth = srcTexture.GetDepth(srcMipIndex);

              int dstIndex = dstTexture.GetImageIndex(dstMipIndex, dstArrayOrFaceIndex, 0);
              int dstWidth = dstTexture.Images[dstIndex].Width;
              int dstHeight = dstTexture.Images[dstIndex].Height;
              int dstDepth = dstTexture.GetDepth(dstMipIndex);

              // Resize volume.
              var kernelX = new PolyphaseKernel(filter, srcWidth, dstWidth, 32);
              var kernelY = new PolyphaseKernel(filter, srcHeight, dstHeight, 32);
              var kernelZ = new PolyphaseKernel(filter, srcDepth, dstDepth, 32);

              var tmpTexture = new Texture(new TextureDescription
              {
            Dimension = TextureDimension.Texture3D,
            Width = dstWidth,
            Height = srcHeight,
            Depth = srcDepth,
            MipLevels = 1,
            ArraySize = 1,
            Format = DataFormat.R32G32B32A32_FLOAT
              });
              var tmpTexture2 = new Texture(new TextureDescription
              {
            Dimension = TextureDimension.Texture3D,
            Width = dstWidth,
            Height = dstHeight,
            Depth = srcDepth,
            MipLevels = 1,
            ArraySize = 1,
            Format = DataFormat.R32G32B32A32_FLOAT
              });

              // ReSharper disable AccessToDisposedClosure
              using (var srcVolume = new VolumeAccessor(srcTexture, srcMipIndex, srcArrayOrFaceIndex))
              using (var tmpVolume = new VolumeAccessor(tmpTexture, 0, 0))
              using (var tmpVolume2 = new VolumeAccessor(tmpTexture2, 0, 0))
              using (var dstVolume = new VolumeAccessor(dstTexture, dstMipIndex, dstArrayOrFaceIndex))
              {
            // Resize horizontally: srcVolume --> tmpVolume
            {
              float scale = (float)tmpVolume.Width / srcVolume.Width;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int z = 0; z < tmpVolume.Depth; z++)
            #else
              Parallel.For(0, tmpVolume.Depth, z =>
            #endif
              {
            for (int y = 0; y < tmpVolume.Height; y++)
            {
              // Apply polyphase kernel horizontally.
              for (int x = 0; x < tmpVolume.Width; x++)
              {
                float center = (x + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelX.Width);
                int right = (int)Math.Ceiling(center + kernelX.Width);
                Debug.Assert(right - left <= kernelX.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelX.WindowSize; i++)
                {
                  Vector4F color = srcVolume.GetPixel(left + i, y, z, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelX.Weights[x, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                tmpVolume.SetPixel(x, y, z, sum);
              }
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }

            // Resize vertically: tmpVolume --> tmpVolume2
            {
              float scale = (float)tmpVolume2.Height / tmpVolume.Height;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int z = 0; z < tmpVolume2.Depth; z++)
            #else
              Parallel.For(0, tmpVolume2.Depth, z =>
            #endif
              {
            for (int x = 0; x < tmpVolume2.Width; x++)
            {
              // Apply polyphase kernel vertically.
              for (int y = 0; y < tmpVolume2.Height; y++)
              {
                float center = (y + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelY.Width);
                int right = (int)Math.Ceiling(center + kernelY.Width);
                Debug.Assert(right - left <= kernelY.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelY.WindowSize; i++)
                {
                  Vector4F color = tmpVolume.GetPixel(x, left + i, z, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelY.Weights[y, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                tmpVolume2.SetPixel(x, y, z, sum);
              }
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }

            // Resize depth: tmpVolume2 --> dstVolume
            {
              float scale = (float)dstVolume.Depth / tmpVolume2.Depth;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int y = 0; y < dstVolume.Height; y++)
            #else
              Parallel.For(0, dstVolume.Height, y =>
            #endif
              {
            for (int x = 0; x < dstVolume.Width; x++)
            {
              // Apply polyphase kernel along z direction.
              for (int z = 0; z < dstVolume.Depth; z++)
              {
                float center = (z + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelZ.Width);
                int right = (int)Math.Ceiling(center + kernelZ.Width);
                Debug.Assert(right - left <= kernelZ.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelZ.WindowSize; i++)
                {
                  Vector4F color = tmpVolume2.GetPixel(x, y, left + i, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelZ.Weights[z, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                dstVolume.SetPixel(x, y, z, sum);
              }
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }
              }
              // ReSharper restore AccessToDisposedClosure
        }