diff options
-rw-r--r-- | source/blender/draw/intern/draw_manager_data.c | 4 | ||||
-rw-r--r-- | source/blender/gpu/GPU_material.h | 3 | ||||
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 23 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 61 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 7 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 48 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_blackbody.c | 7 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_curves.c | 12 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_valToRgb.c | 5 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_volume_principled.c | 14 |
12 files changed, 130 insertions, 57 deletions
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 = texture(curvemap, co.zw).z; + outvec = mix(vec, outvec, fac); } -void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol) +void curves_rgb(float fac, vec4 col, sampler1DArray curvemap, float layer, out vec4 outcol) { - outcol.r = texture(curvemap, vec2(texture(curvemap, vec2(col.r, 0.0)).a, 0.0)).r; - outcol.g = texture(curvemap, vec2(texture(curvemap, vec2(col.g, 0.0)).a, 0.0)).g; - outcol.b = texture(curvemap, vec2(texture(curvemap, vec2(col.b, 0.0)).a, 0.0)).b; - - if (fac != 1.0) - outcol = (outcol * fac) + (col * (1.0 - fac)); - + vec4 co = vec4(col.rgb, layer); + co.x = texture(curvemap, co.xw).a; + co.y = texture(curvemap, co.yw).a; + co.z = texture(curvemap, co.zw).a; + outcol.r = texture(curvemap, co.xw).r; + outcol.g = texture(curvemap, co.yw).g; + outcol.b = texture(curvemap, co.zw).b; outcol.a = col.a; + outcol = mix(col, outcol, fac); } void set_value(float val, out float outval) @@ -813,9 +812,9 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); } -void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha) +void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) { - outcol = texture(colormap, vec2(fac, 0.0)); + outcol = texture(colormap, vec2(fac, layer)); outalpha = outcol.a; } @@ -1464,17 +1463,17 @@ void node_volume_absorption(vec4 color, float density, out Closure result) #endif } -void node_blackbody(float temperature, sampler2D spectrummap, out vec4 color) +void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color) { - if(temperature >= 12000.0) { + if (temperature >= 12000.0) { color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); } - else if(temperature < 965.0) { + else if (temperature < 965.0) { color = vec4(4.70366907, 0.0, 0.0, 1.0); } else { float t = (temperature - 965.0) / (12000.0 - 965.0); - color = vec4(texture(spectrummap, vec2(t, 0.0)).rgb, 1.0); + color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); } } @@ -1491,7 +1490,8 @@ void node_volume_principled( float density_attribute, vec4 color_attribute, float temperature_attribute, - sampler2D spectrummap, + sampler1DArray spectrummap, + float layer, out Closure result) { #ifdef VOLUMETRICS @@ -1533,7 +1533,7 @@ void node_volume_principled( if(intensity > 1e-5) { vec4 bb; - node_blackbody(T, spectrummap, bb); + node_blackbody(T, spectrummap, layer, bb); emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; } } diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.c b/source/blender/nodes/shader/nodes/node_shader_blackbody.c index 76291df41bc..e57f5e0d6cf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_blackbody.c +++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.c @@ -40,12 +40,15 @@ static bNodeSocketTemplate sh_node_blackbody_out[] = { static int node_shader_gpu_blackbody(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - const int size = 256; + const int size = CM_TABLE + 1; float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f); - return GPU_stack_link(mat, node, "node_blackbody", in, out, GPU_texture(size, data)); + float layer; + GPUNodeLink *ramp_texture = GPU_texture_ramp(mat, size, data, &layer); + + return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_uniform(&layer)); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index d5932ff233a..21bdc3cd0d8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -62,11 +62,13 @@ static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node) static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - float *array; + float *array, layer; int size; curvemapping_table_RGBA(node->storage, &array, &size); - return GPU_stack_link(mat, node, "curves_vec", in, out, GPU_texture(size, array)); + GPUNodeLink *tex = GPU_texture_ramp(mat, size, array, &layer); + + return GPU_stack_link(mat, node, "curves_vec", in, out, tex, GPU_uniform(&layer)); } void register_node_type_sh_curve_vec(void) @@ -119,12 +121,14 @@ static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node) static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - float *array; + float *array, layer; int size; curvemapping_initialize(node->storage); curvemapping_table_RGBA(node->storage, &array, &size); - return GPU_stack_link(mat, node, "curves_rgb", in, out, GPU_texture(size, array)); + GPUNodeLink *tex = GPU_texture_ramp(mat, size, array, &layer); + + return GPU_stack_link(mat, node, "curves_rgb", in, out, tex, GPU_uniform(&layer)); } void register_node_type_sh_curve_rgb(void) diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c index b6581cb18cb..00940b5acaf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -65,11 +65,12 @@ static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node) static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - float *array; + float *array, layer; int size; BKE_colorband_evaluate_table_rgba(node->storage, &array, &size); - return GPU_stack_link(mat, node, "valtorgb", in, out, GPU_texture(size, array)); + GPUNodeLink *tex = GPU_texture_ramp(mat, size, array, &layer); + return GPU_stack_link(mat, node, "valtorgb", in, out, tex, GPU_uniform(&layer)); } void register_node_type_sh_valtorgb(void) diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c index a88a7ebb21a..c946c42f9af 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c @@ -132,19 +132,19 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat, bNode *node, bNod } /* Create blackbody spectrum. */ - GPUNodeLink *spectrummap; + const int size = CM_TABLE + 1; + float *data, layer; if (use_blackbody) { - const int size = 256; - float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); + data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f); - spectrummap = GPU_texture(size, data); } else { - float *data = MEM_callocN(sizeof(float) * 4, "blackbody black"); - spectrummap = GPU_texture(1, data); + data = MEM_callocN(sizeof(float) * size * 4, "blackbody black"); } + GPUNodeLink *spectrummap = GPU_texture_ramp(mat, size, data, &layer); - return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap); + return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap, + GPU_uniform(&layer)); } /* node type definition */ |