[Bf-blender-cvs] [cfba534403c] tmp-gltexture: GPUTexture: Implement back 3D texture resize

Clément Foucault noreply at git.blender.org
Sat Sep 5 01:58:28 CEST 2020


Commit: cfba534403c04387353f2d6190885f0172304a54
Author: Clément Foucault
Date:   Fri Sep 4 21:09:42 2020 +0200
Branches: tmp-gltexture
https://developer.blender.org/rBcfba534403c04387353f2d6190885f0172304a54

GPUTexture: Implement back 3D texture resize

But this time implement it outside the texture module.
This makes more sense as only the volume textures need this feature.

===================================================================

M	source/blender/draw/intern/draw_fluid.c
M	source/blender/gpu/intern/gpu_texture.cc

===================================================================

diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c
index 89714c04351..c9f181f53db 100644
--- a/source/blender/draw/intern/draw_fluid.c
+++ b/source/blender/draw/intern/draw_fluid.c
@@ -131,6 +131,100 @@ static void swizzle_texture_channel_single(GPUTexture *tex)
   GPU_texture_swizzle_set(tex, "rrr1");
 }
 
+static float *rescale_3d(const int dim[3],
+                         const int final_dim[3],
+                         int channels,
+                         const float *fpixels)
+{
+  const uint w = dim[0], h = dim[1], d = dim[2];
+  const uint fw = final_dim[0], fh = final_dim[1], fd = final_dim[2];
+  const uint xf = w / fw, yf = h / fh, zf = d / fd;
+  const uint pixel_count = fw * fh * fd;
+  float *nfpixels = (float *)MEM_mallocN(channels * sizeof(float) * pixel_count, __func__);
+
+  if (nfpixels) {
+    printf("Performance: You need to scale a 3D texture, feel the pain!\n");
+
+    for (uint k = 0; k < fd; k++) {
+      for (uint j = 0; j < fh; j++) {
+        for (uint i = 0; i < fw; i++) {
+          /* Obviously doing nearest filtering here,
+           * it's going to be slow in any case, let's not make it worse. */
+          float xb = i * xf;
+          float yb = j * yf;
+          float zb = k * zf;
+          uint offset = k * (fw * fh) + i * fh + j;
+          uint offset_orig = (zb) * (w * h) + (xb)*h + (yb);
+
+          if (channels == 4) {
+            nfpixels[offset * 4] = fpixels[offset_orig * 4];
+            nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+            nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+            nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+          }
+          else if (channels == 1) {
+            nfpixels[offset] = fpixels[offset_orig];
+          }
+          else {
+            BLI_assert(0);
+          }
+        }
+      }
+    }
+  }
+  return nfpixels;
+}
+
+/* Will resize input to fit GL system limits. */
+static GPUTexture *create_volume_texture(const int dim[3],
+                                         eGPUTextureFormat format,
+                                         const float *data)
+{
+  GPUTexture *tex = NULL;
+  int final_dim[3] = {UNPACK3(dim)};
+
+  while (1) {
+    tex = GPU_texture_create_nD(
+        UNPACK3(final_dim), 3, NULL, format, GPU_DATA_FLOAT, 0, false, NULL);
+
+    if (tex != NULL) {
+      break;
+    }
+
+    if (final_dim[0] == 1 && final_dim[1] == 1 && final_dim[2] == 1) {
+      break;
+    }
+
+    for (int i = 0; i < 3; i++) {
+      final_dim[i] = max_ii(1, final_dim[i] / 2);
+    }
+  }
+
+  if (tex == NULL) {
+    printf("Error: Could not create 3D texture.\n");
+    tex = GPU_texture_create_error(3, false);
+  }
+  else if (equals_v3v3_int(dim, final_dim)) {
+    /* No need to resize, just upload the data. */
+    GPU_texture_update_sub(tex, GPU_DATA_FLOAT, data, 0, 0, 0, UNPACK3(final_dim));
+  }
+  else {
+    /* We need to resize the input. */
+    int channels = (format == GPU_R8) ? 1 : 4;
+    float *rescaled_data = rescale_3d(dim, final_dim, channels, data);
+    if (rescaled_data) {
+      GPU_texture_update_sub(tex, GPU_DATA_FLOAT, rescaled_data, 0, 0, 0, UNPACK3(final_dim));
+      MEM_freeN(rescaled_data);
+    }
+    else {
+      printf("Error: Could not allocate rescaled 3d texture!\n");
+      GPU_texture_free(tex);
+      tex = GPU_texture_create_error(3, false);
+    }
+  }
+  return tex;
+}
+
 static GPUTexture *create_field_texture(FluidDomainSettings *fds)
 {
   float *field = NULL;
@@ -182,9 +276,7 @@ static GPUTexture *create_field_texture(FluidDomainSettings *fds)
       return NULL;
   }
 
-  GPUTexture *tex = GPU_texture_create_nD(
-      UNPACK3(fds->res), 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
-
+  GPUTexture *tex = create_volume_texture(fds->res, GPU_R8, field);
   swizzle_texture_channel_single(tex);
   return tex;
 }
@@ -201,11 +293,8 @@ static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres)
     data = manta_smoke_get_density(fds->fluid);
   }
 
-  GPUTexture *tex = GPU_texture_create_nD(
-      UNPACK3(dim), 3, data, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
-
+  GPUTexture *tex = create_volume_texture(dim, GPU_R8, data);
   swizzle_texture_channel_single(tex);
-
   return tex;
 }
 
@@ -233,8 +322,7 @@ static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres)
     manta_smoke_get_rgba(fds->fluid, data, 0);
   }
 
-  GPUTexture *tex = GPU_texture_create_nD(
-      dim[0], dim[1], dim[2], 3, data, GPU_RGBA8, GPU_DATA_FLOAT, 0, true, NULL);
+  GPUTexture *tex = create_volume_texture(dim, GPU_RGBA8, data);
 
   MEM_freeN(data);
 
@@ -259,11 +347,8 @@ static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres)
     source = manta_smoke_get_flame(fds->fluid);
   }
 
-  GPUTexture *tex = GPU_texture_create_nD(
-      dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
-
+  GPUTexture *tex = create_volume_texture(dim, GPU_R8, source);
   swizzle_texture_channel_single(tex);
-
   return tex;
 }
 
@@ -354,14 +439,8 @@ void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
       fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
     }
     if (!fds->tex_shadow) {
-      fds->tex_shadow = GPU_texture_create_nD(UNPACK3(fds->res),
-                                              3,
-                                              manta_smoke_get_shadow(fds->fluid),
-                                              GPU_R8,
-                                              GPU_DATA_FLOAT,
-                                              0,
-                                              true,
-                                              NULL);
+      fds->tex_shadow = create_volume_texture(
+          fds->res, GPU_R8, manta_smoke_get_shadow(fds->fluid));
     }
   }
 #endif /* WITH_FLUID */
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index 29a6138eed2..f3d1d4fdb42 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -218,13 +218,6 @@ GPUTexture *GPU_texture_create_nD(int w,
       break;
   }
 
-#if 0 /* TODO */
-  if (can_rescale && n == 3) {
-    /* Search small enough supported texture on the system. */
-    /* Rescale input. */
-  }
-#endif
-
   if (!success) {
     delete tex;
     return NULL;



More information about the Bf-blender-cvs mailing list