Browse Source

3D textures on D3D11. Fixed the ColorCorrection shader.

Lasse Öörni 10 years ago
parent
commit
4e308f21c3

+ 39 - 0
Source/Urho3D/Graphics/Direct3D11/D3D11Texture.cpp

@@ -367,6 +367,27 @@ SharedArrayPtr<unsigned char> Texture::ConvertRGBToRGBA(int width, int height, c
     return ret;
 }
 
+SharedArrayPtr<unsigned char> Texture::ConvertRGBToRGBA(int width, int height, int depth, const unsigned char* data)
+{
+    if (!width || !height || !depth)
+        return SharedArrayPtr<unsigned char>();
+
+    SharedArrayPtr<unsigned char> ret(new unsigned char[width * height * depth * 4]);
+    unsigned char* dest = ret.Get();
+
+    for (int i = 0; i < width * height * depth; ++i)
+    {
+        dest[0] = data[0];
+        dest[1] = data[1];
+        dest[2] = data[2];
+        dest[3] = 255;
+        dest += 4;
+        data += 3;
+    }
+
+    return ret;
+}
+
 unsigned Texture::CheckMaxLevels(int width, int height, unsigned requestedLevels)
 {
     unsigned maxLevels = 1;
@@ -383,6 +404,24 @@ unsigned Texture::CheckMaxLevels(int width, int height, unsigned requestedLevels
         return requestedLevels;
 }
 
+unsigned Texture::CheckMaxLevels(int width, int height, int depth, unsigned requestedLevels)
+{
+    unsigned maxLevels = 1;
+    while (width > 1 && height > 1 && depth > 1)
+    {
+        ++maxLevels;
+        width >>= 1;
+        height >>= 1;
+        depth >>= 1;
+    }
+
+    if (!requestedLevels || maxLevels < requestedLevels)
+        return maxLevels;
+    else
+        return requestedLevels;
+}
+
+
 unsigned Texture::GetSRVFormat(unsigned format)
 {
     if (format == DXGI_FORMAT_R24G8_TYPELESS)

+ 4 - 0
Source/Urho3D/Graphics/Direct3D11/D3D11Texture.h

@@ -120,8 +120,12 @@ public:
     
     /// Convert RGB data to RGBA for loading into a texture.
     static SharedArrayPtr<unsigned char> ConvertRGBToRGBA(int width, int height, const unsigned char* data);
+    /// Convert RGB data to RGBA for loading into a 3D texture.
+    static SharedArrayPtr<unsigned char> ConvertRGBToRGBA(int width, int height, int depth, const unsigned char* data);
     /// Check maximum allowed mip levels for a specific texture size.
     static unsigned CheckMaxLevels(int width, int height, unsigned requestedLevels);
+    /// Check maximum allowed mip levels for a specific 3D texture size.
+    static unsigned CheckMaxLevels(int width, int height, int depth, unsigned requestedLevels);
     /// Return the shader resource view format corresponding to a texture format. Handles conversion of typeless depth texture formats.
     static unsigned GetSRVFormat(unsigned format);
     /// Return the depth-stencil view format corresponding to a texture format. Handles conversion of typeless depth texture formats.

+ 102 - 14
Source/Urho3D/Graphics/Direct3D11/D3D11Texture3D.cpp

@@ -230,12 +230,6 @@ bool Texture3D::SetData(unsigned level, int x, int y, int z, int width, int heig
         return false;
     }
     
-    if (IsCompressed())
-    {
-        x &= ~3;
-        y &= ~3;
-    }
-    
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
     int levelDepth = GetLevelDepth(level);
@@ -245,16 +239,70 @@ bool Texture3D::SetData(unsigned level, int x, int y, int z, int width, int heig
         return false;
     }
     
+    // If compressed, align the update region on a block
     if (IsCompressed())
     {
-        height = (height + 3) >> 2;
-        y >>= 2;
+        x &= ~3;
+        y &= ~3;
+        width += 3;
+        width &= 0xfffffffc;
+        height += 3;
+        height &= 0xfffffffc;
     }
-    
+
     unsigned char* src = (unsigned char*)data;
     unsigned rowSize = GetRowDataSize(width);
-    
-    /// \todo Implement
+    unsigned rowStart = GetRowDataSize(x);
+    unsigned subResource = D3D11CalcSubresource((unsigned)level, 0, (unsigned)levels_);
+
+    if (usage_ == TEXTURE_DYNAMIC)
+    {
+        if (IsCompressed())
+        {
+            height = (height + 3) >> 2;
+            y >>= 2;
+        }
+
+        D3D11_MAPPED_SUBRESOURCE mappedData;
+        mappedData.pData = 0;
+
+        graphics_->GetImpl()->GetDeviceContext()->Map((ID3D11Resource*)object_, subResource, D3D11_MAP_WRITE_DISCARD, 0,
+            &mappedData);
+        if (mappedData.pData)
+        {
+            for (int page = 0; page < depth; ++page)
+            {
+                for (int row = 0; row < height; ++row)
+                {
+                    memcpy((unsigned char*)mappedData.pData + (page + z) * mappedData.DepthPitch + (row + y) * mappedData.RowPitch
+                        + rowStart, src + row * rowSize, rowSize);
+                }
+            }
+
+            graphics_->GetImpl()->GetDeviceContext()->Unmap((ID3D11Resource*)object_, subResource);
+        }
+        else
+        {
+            LOGERROR("Failed to map texture for update");
+            return false;
+        }
+    }
+    else
+    {
+        if (IsCompressed())
+            levelHeight = (levelHeight + 3) >> 2;
+
+        D3D11_BOX destBox;
+        destBox.left = x;
+        destBox.right = x + width;
+        destBox.top = y;
+        destBox.bottom = y + height;
+        destBox.front = z;
+        destBox.back = z + depth;
+
+        graphics_->GetImpl()->GetDeviceContext()->UpdateSubresource((ID3D11Resource*)object_, subResource, &destBox, data,
+            rowSize, levelHeight * rowSize);
+    }
 
     return true;
 }
@@ -319,6 +367,14 @@ bool Texture3D::SetData(SharedPtr<Image> image, bool useAlpha)
         
         for (unsigned i = 0; i < levels_; ++i)
         {
+            // D3D11 needs RGB data as 4-component
+            SharedArrayPtr<unsigned char> convertedData;
+            if (components == 3)
+            {
+                convertedData = ConvertRGBToRGBA(levelWidth, levelHeight, levelDepth, levelData);
+                levelData = convertedData;
+            }
+
             SetData(i, 0, 0, 0, levelWidth, levelHeight, levelDepth, levelData);
             memoryUse += levelWidth * levelHeight * levelDepth * components;
             
@@ -427,11 +483,43 @@ bool Texture3D::Create()
 {
     Release();
     
-    if (!graphics_ || !width_ || !height_)
+    if (!graphics_ || !width_ || !height_ || !depth_)
         return false;
     
-    /// \todo Implement
-    
+    levels_ = CheckMaxLevels(width_, height_, depth_, requestedLevels_);
+
+    D3D11_TEXTURE3D_DESC textureDesc;
+    memset(&textureDesc, 0, sizeof textureDesc);
+    textureDesc.Width = width_;
+    textureDesc.Height = height_;
+    textureDesc.Depth = depth_;
+    textureDesc.MipLevels = levels_;
+    textureDesc.Format = (DXGI_FORMAT)format_;
+    textureDesc.Usage = usage_ == TEXTURE_DYNAMIC ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
+    textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+    textureDesc.CPUAccessFlags = usage_ == TEXTURE_DYNAMIC ? D3D11_CPU_ACCESS_WRITE : 0;
+
+    graphics_->GetImpl()->GetDevice()->CreateTexture3D(&textureDesc, 0, (ID3D11Texture3D**)&object_);
+    if (!object_)
+    {
+        LOGERROR("Failed to create texture");
+        return false;
+    }
+
+    D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
+    memset(&resourceViewDesc, 0, sizeof resourceViewDesc);
+    resourceViewDesc.Format = (DXGI_FORMAT)GetSRVFormat(textureDesc.Format);
+    resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+    resourceViewDesc.Texture3D.MipLevels = (unsigned)levels_;
+
+    graphics_->GetImpl()->GetDevice()->CreateShaderResourceView((ID3D11Resource*)object_, &resourceViewDesc,
+        (ID3D11ShaderResourceView**)&shaderResourceView_);
+    if (!shaderResourceView_)
+    {
+        LOGERROR("Failed to create shader resource view for texture");
+        return false;
+    }
+
     return true;
 }
 

+ 9 - 5
bin/CoreData/Shaders/HLSL/ColorCorrection.hlsl

@@ -5,8 +5,8 @@
 #include "PostProcess.hlsl"
 
 void VS(float4 iPos : POSITION,
-    out float4 oPos : POSITION,
-    out float2 oScreenPos : TEXCOORD0)
+    out float2 oScreenPos : TEXCOORD0,
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -15,8 +15,12 @@ void VS(float4 iPos : POSITION,
 }
 
 void PS(float2 iScreenPos : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
-    float3 color = tex2D(sDiffMap, iScreenPos).rgb;
-    oColor = float4(ColorCorrection(color, sVolumeMap), 1.0);
+    float3 color = Sample2D(DiffMap, iScreenPos).rgb;
+    #ifndef D3D11
+        oColor = float4(ColorCorrection(color, sVolumeMap), 1.0);
+    #else
+        oColor = float4(ColorCorrection(color, tVolumeMap, sVolumeMap), 1.0);
+    #endif
 }

+ 9 - 1
bin/CoreData/Shaders/HLSL/PostProcess.hlsl

@@ -78,12 +78,20 @@ float3 Uncharted2Tonemap(float3 x)
    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
 }
 
+#ifndef D3D11
 float3 ColorCorrection(float3 color, sampler3D lut)
+#else
+float3 ColorCorrection(float3 color, Texture3D lut, SamplerState lutSampler)
+#endif
 {
     float lutSize = 16.0;
     float scale = (lutSize - 1.0) / lutSize;
     float offset = 1.0 / (2.0 * lutSize);
-    return tex3D(lut, clamp(color, 0.0, 1.0) * scale + offset).rgb;
+    #ifndef D3D11
+        return tex3D(lut, clamp(color, 0.0, 1.0) * scale + offset).rgb;
+    #else
+        return lut.Sample(lutSampler, clamp(color, 0.0, 1.0) * scale + offset).rgb;
+    #endif
 }
 
 static const float Gamma = 2.2;