static int node_shader_gpu_blackbody(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { 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); float layer; GPUNodeLink *ramp_texture = GPU_color_band(mat, size, data, &layer); return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_constant(&layer)); }
static GPUTexture *create_flame_spectrum_texture(void) { #define SPEC_WIDTH 256 #define FIRE_THRESH 7 #define MAX_FIRE_ALPHA 0.06f #define FULL_ON_FIRE 100 GPUTexture *tex; int i, j, k; float *spec_data = MEM_mallocN(SPEC_WIDTH * 4 * sizeof(float), "spec_data"); float *spec_pixels = MEM_mallocN(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels"); blackbody_temperature_to_rgb_table(spec_data, SPEC_WIDTH, 1500, 3000); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { for (k = 0; k < SPEC_WIDTH; k++) { int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4; if (k >= FIRE_THRESH) { spec_pixels[index] = (spec_data[k * 4]); spec_pixels[index + 1] = (spec_data[k * 4 + 1]); spec_pixels[index + 2] = (spec_data[k * 4 + 2]); spec_pixels[index + 3] = MAX_FIRE_ALPHA * ( (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); } else { zero_v4(&spec_pixels[index]); } } } } tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL); MEM_freeN(spec_data); MEM_freeN(spec_pixels); #undef SPEC_WIDTH #undef FIRE_THRESH #undef MAX_FIRE_ALPHA #undef FULL_ON_FIRE return tex; }
static int node_shader_gpu_volume_principled(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { /* Test if blackbody intensity is enabled. */ bool use_blackbody = (in[8].link || in[8].vec[0] != 0.0f); /* Get volume attributes. */ GPUNodeLink *density = NULL, *color = NULL, *temperature = NULL; for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) { if (sock->typeinfo->type != SOCK_STRING) { continue; } bNodeSocketValueString *value = sock->default_value; GPUNodeLink *outcol, *outvec, *outf; if (STREQ(sock->name, "Density Attribute")) { node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &density); } else if (STREQ(sock->name, "Color Attribute")) { node_shader_gpu_volume_attribute(mat, value->value, &color, &outvec, &outf); } else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) { node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &temperature); } } /* Default values if attributes not found. */ if (!density) { static float one = 1.0f; density = GPU_constant(&one); } if (!color) { static float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; color = GPU_constant(white); } if (!temperature) { static float one = 1.0f; temperature = GPU_constant(&one); } /* Create blackbody spectrum. */ const int size = CM_TABLE + 1; float *data, layer; if (use_blackbody) { data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f); } else { data = MEM_callocN(sizeof(float) * size * 4, "blackbody black"); } GPUNodeLink *spectrummap = GPU_color_band(mat, size, data, &layer); return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap, GPU_constant(&layer)); }