[Bf-blender-cvs] [bf6a22ed6f6] blender2.8: GPUMaterial: Group all colorband texture together

Clément Foucault noreply at git.blender.org
Fri Aug 10 16:20:51 CEST 2018


Commit: bf6a22ed6f6bbe7db3e7796e83d32e071aae93cc
Author: Clément Foucault
Date:   Fri Aug 10 15:13:39 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBbf6a22ed6f6bbe7db3e7796e83d32e071aae93cc

GPUMaterial: Group all colorband texture together

This lower the use of texture samplers slots and let users use more real
textures in their shaders.

This patch also make the ramp texture 16 bit floating point. Meaning you
can now use value greater than one in your color ramps.

With the limit of 128 colorband per shader (a color band being either a
color ramp, a wavelength node or a curve node (and maybe wavelength node in
the future)).

Only drawback with the current implementation is that it does not remove
colorband from pruned GPUNodes but it shouldn't really matter in practice.

This should fix T56010

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

M	source/blender/draw/intern/draw_manager_data.c
M	source/blender/gpu/GPU_material.h
M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/intern/gpu_codegen.c
M	source/blender/gpu/intern/gpu_codegen.h
M	source/blender/gpu/intern/gpu_material.c
M	source/blender/gpu/intern/gpu_texture.c
M	source/blender/gpu/shaders/gpu_shader_material.glsl
M	source/blender/nodes/shader/nodes/node_shader_blackbody.c
M	source/blender/nodes/shader/nodes/node_shader_curves.c
M	source/blender/nodes/shader/nodes/node_shader_valToRgb.c
M	source/blender/nodes/shader/nodes/node_shader_volume_principled.c

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

diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 6b15803723b..b97101c0e6d 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -776,7 +776,9 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct
 		}
 		/* Color Ramps */
 		else if (input->tex) {
-			DRW_shgroup_uniform_texture(grp, input->shadername, input->tex);
+			/* HACK : input->tex is a (GPUTexture **) in this case. */
+			GPUTexture *tex = *((GPUTexture **)input->tex);
+			DRW_shgroup_uniform_texture(grp, input->shadername, tex);
 		}
 		/* Floats */
 		else {
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 9dcf308a414..6b0296361ec 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -80,6 +80,7 @@ typedef enum GPUType {
 	GPU_MAT4 = 16,
 
 	/* Values not in GPU_DATATYPE_STR */
+	GPU_TEX1D_ARRAY = 1001,
 	GPU_TEX2D = 1002,
 	GPU_TEX3D = 1003,
 	GPU_SHADOW2D = 1004,
@@ -229,7 +230,7 @@ GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype);
 GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
 GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data);
 GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
-GPUNodeLink *GPU_texture(int size, float *pixels);
+GPUNodeLink *GPU_texture_ramp(GPUMaterial *mat, int size, float *pixels, float *layer);
 GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data);
 GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 1ddf801e166..23b88645e33 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -163,6 +163,8 @@ GPUTexture *GPU_texture_create_nD(
 
 GPUTexture *GPU_texture_create_1D(
         int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_array(
+        int w, int h, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
 GPUTexture *GPU_texture_create_2D(
         int w, int h, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
 GPUTexture *GPU_texture_create_2D_multisample(
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index cc4b7cc8ebc..289befe674e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -257,6 +257,9 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
 			if (!type && gpu_str_prefix(code, "sampler2DShadow")) {
 				type = GPU_SHADOW2D;
 			}
+			if (!type && gpu_str_prefix(code, "sampler1DArray")) {
+				type = GPU_TEX1D_ARRAY;
+			}
 			if (!type && gpu_str_prefix(code, "sampler2D")) {
 				type = GPU_TEX2D;
 			}
@@ -617,6 +620,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
 				if (codegen_input_has_texture(input) && input->bindtex) {
 					BLI_dynstr_appendf(
 					        ds, "uniform %s samp%d;\n",
+					        (input->textype == GPU_TEX1D_ARRAY) ? "sampler1DArray" :
 					        (input->textype == GPU_TEX2D) ? "sampler2D" :
 					        (input->textype == GPU_TEXCUBE) ? "samplerCube" : "sampler2DShadow",
 					        input->texid);
@@ -1330,15 +1334,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
 		/* small texture created on the fly, like for colorbands */
 		input->type = GPU_VEC4;
 		input->source = GPU_SOURCE_TEX;
-		input->textype = type;
-
-#if 0
-		input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
-#endif
-		input->tex = GPU_texture_create_2D(link->texturesize, 1, GPU_RGBA8, link->ptr1, NULL);
-		input->textarget = GL_TEXTURE_2D;
-
-		MEM_freeN(link->ptr1);
+		input->textype = GPU_TEX1D_ARRAY;
+		input->tex = link->ptr1; /* HACK ptr1 is actually a (GPUTexture **). */
+		input->textarget = GL_TEXTURE_1D_ARRAY;
 		MEM_freeN(link);
 	}
 	else if (link->image) {
@@ -1687,13 +1685,14 @@ GPUNodeLink *GPU_image_preview(PreviewImage *prv)
 }
 
 
-GPUNodeLink *GPU_texture(int size, float *pixels)
+GPUNodeLink *GPU_texture_ramp(GPUMaterial *mat, int size, float *pixels, float *row)
 {
 	GPUNodeLink *link = GPU_node_link_create();
 
 	link->texture = true;
-	link->texturesize = size;
-	link->ptr1 = pixels;
+	link->ptr1 = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
+
+	MEM_freeN(pixels);
 
 	return link;
 }
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 4af87c6a226..77e6e5cf4ef 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -197,6 +197,7 @@ void gpu_codegen_exit(void);
 
 const char *GPU_builtin_name(GPUBuiltin builtin);
 void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
+struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row);
 int GPU_link_changed(struct GPUNodeLink *link);
 
 #endif
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 69c3a3a73ba..b03df2c643c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -63,6 +63,12 @@
 #endif
 
 /* Structs */
+#define MAX_COLOR_BAND 128
+
+typedef struct GPUColorBandBuilder {
+	float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4];
+	int current_layer;
+} GPUColorBandBuilder;
 
 struct GPUMaterial {
 	Scene *scene; /* DEPRECATED was only usefull for lamps */
@@ -125,6 +131,9 @@ struct GPUMaterial {
 	float sss_sharpness;
 	bool sss_dirty;
 
+	GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */
+	GPUColorBandBuilder *coba_builder;
+
 #ifndef NDEBUG
 	char name[64];
 #endif
@@ -138,6 +147,47 @@ enum {
 
 /* Functions */
 
+/* Returns the adress of the future pointer to coba_tex */
+GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row)
+{
+	/* In order to put all the colorbands into one 1D array texture,
+	 * we need them to be the same size. */
+	BLI_assert(size == CM_TABLE + 1);
+
+	if (mat->coba_builder == NULL) {
+		mat->coba_builder = MEM_mallocN(sizeof(GPUColorBandBuilder), "GPUColorBandBuilder");
+		mat->coba_builder->current_layer = 0;
+	}
+
+	int layer = mat->coba_builder->current_layer;
+	*row = (float)layer;
+
+	if (*row == MAX_COLOR_BAND) {
+		printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n");
+	}
+	else {
+		float *dst = (float *)mat->coba_builder->pixels[layer];
+		memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4);
+		mat->coba_builder->current_layer += 1;
+	}
+
+	return &mat->coba_tex;
+}
+
+static void gpu_material_ramp_texture_build(GPUMaterial *mat)
+{
+	if (mat->coba_builder == NULL)
+		return;
+
+	GPUColorBandBuilder *builder = mat->coba_builder;
+
+	mat->coba_tex = GPU_texture_create_1D_array(CM_TABLE + 1, builder->current_layer, GPU_RGBA16F,
+	                                            (float *)builder->pixels, NULL);
+
+	MEM_freeN(builder);
+	mat->coba_builder = NULL;
+}
+
 static void gpu_material_free_single(GPUMaterial *material)
 {
 	/* Cancel / wait any pending lazy compilation. */
@@ -146,20 +196,21 @@ static void gpu_material_free_single(GPUMaterial *material)
 	GPU_pass_free_nodes(&material->nodes);
 	GPU_inputs_free(&material->inputs);
 
-	if (material->pass)
+	if (material->pass != NULL) {
 		GPU_pass_release(material->pass);
-
+	}
 	if (material->ubo != NULL) {
 		GPU_uniformbuffer_free(material->ubo);
 	}
-
 	if (material->sss_tex_profile != NULL) {
 		GPU_texture_free(material->sss_tex_profile);
 	}
-
 	if (material->sss_profile != NULL) {
 		GPU_uniformbuffer_free(material->sss_profile);
 	}
+	if (material->coba_tex != NULL) {
+		GPU_texture_free(material->coba_tex);
+	}
 }
 
 void GPU_material_free(ListBase *gpumaterial)
@@ -622,6 +673,8 @@ GPUMaterial *GPU_material_from_nodetree(
 	bNodeTree *localtree = ntreeLocalize(ntree);
 	ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output);
 
+	gpu_material_ramp_texture_build(mat);
+
 	if (has_surface_output) {
 		mat->domain |= GPU_DOMAIN_SURFACE;
 	}
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index a5dfb6a6b73..2ccc9f10269 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -871,6 +871,13 @@ GPUTexture *GPU_texture_create_1D(
 	return GPU_texture_create_nD(w, 0, 0, 1, pixels, tex_format, data_format, 0, false, err_out);
 }
 
+GPUTexture *GPU_texture_create_1D_array(
+        int w, int h, GPUTextureFormat tex_format, const float *pixels, char err_out[256])
+{
+	GPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format);
+	return GPU_texture_create_nD(w, h, 0, 1, pixels, tex_format, data_format, 0, false, err_out);
+}
+
 GPUTexture *GPU_texture_create_2D(
         int w, int h, GPUTextureFormat tex_format, const float *pixels, char err_out[256])
 {
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 56fa6291c65..91104fe51bd 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -480,27 +480,26 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
 	outdot = dot(normalize(dir), nor);
 }
 
-void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
+void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec)
 {
-	outvec.x = texture(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
-	outvec.y = texture(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
-	outvec.z = texture(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
-
-	if (fac != 1.0)
-		outvec = (outvec * fac) + (vec * (1.0 - fac));
-
+	vec4 co = vec4(vec * 0.5 + 0.5, layer);
+	outvec.x = texture(curvemap, co.xw).x;
+	outvec.y = texture(curvemap, co.yw).y;
+	outvec.z = t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list