Eevee: add Principled Volume shader.
This commit is contained in:
parent
77062e8bbb
commit
38ccd1fe33
|
@ -3089,6 +3089,71 @@ void node_blackbody(float temperature, sampler2D spectrummap, out vec4 color)
|
|||
}
|
||||
}
|
||||
|
||||
void node_volume_principled(
|
||||
vec4 color,
|
||||
float density,
|
||||
float anisotropy,
|
||||
vec4 absorption_color,
|
||||
float emission_strength,
|
||||
vec4 emission_color,
|
||||
float blackbody_intensity,
|
||||
vec4 blackbody_tint,
|
||||
float temperature,
|
||||
float density_attribute,
|
||||
vec4 color_attribute,
|
||||
float temperature_attribute,
|
||||
sampler2D spectrummap,
|
||||
out Closure result)
|
||||
{
|
||||
#ifdef VOLUMETRICS
|
||||
vec3 absorption_coeff = vec3(0.0);
|
||||
vec3 scatter_coeff = vec3(0.0);
|
||||
vec3 emission_coeff = vec3(0.0);
|
||||
|
||||
/* Compute density. */
|
||||
density = max(density, 0.0);
|
||||
|
||||
if(density > 1e-5) {
|
||||
density = max(density * density_attribute, 0.0);
|
||||
}
|
||||
|
||||
if(density > 1e-5) {
|
||||
/* Compute scattering and absorption coefficients. */
|
||||
vec3 scatter_color = color.rgb * color_attribute.rgb;
|
||||
|
||||
scatter_coeff = scatter_color * density;
|
||||
absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * density;
|
||||
}
|
||||
|
||||
/* Compute emission. */
|
||||
emission_strength = max(emission_strength, 0.0);
|
||||
|
||||
if(emission_strength > 1e-5) {
|
||||
emission_coeff += emission_strength * emission_color.rgb;
|
||||
}
|
||||
|
||||
if(blackbody_intensity > 1e-3) {
|
||||
/* Add temperature from attribute. */
|
||||
float T = max(temperature * max(temperature_attribute, 0.0), 0.0);
|
||||
|
||||
/* Stefan-Boltzman law. */
|
||||
float T4 = (T * T) * (T * T);
|
||||
float sigma = 5.670373e-8 * 1e-6 / M_PI;
|
||||
float intensity = sigma * mix(1.0, T4, blackbody_intensity);
|
||||
|
||||
if(intensity > 1e-5) {
|
||||
vec4 bb;
|
||||
node_blackbody(T, spectrummap, bb);
|
||||
emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
|
||||
}
|
||||
}
|
||||
|
||||
result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy);
|
||||
#else
|
||||
result = CLOSURE_DEFAULT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* closures */
|
||||
|
||||
void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
|
||||
|
|
|
@ -62,9 +62,89 @@ static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *
|
|||
}
|
||||
}
|
||||
|
||||
static int node_shader_gpu_volume_principled(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
|
||||
static void node_shader_gpu_volume_attribute(GPUMaterial *mat, const char *name, GPUNodeLink **outcol, GPUNodeLink **outvec, GPUNodeLink **outf)
|
||||
{
|
||||
return false;
|
||||
if (strcmp(name, "density") == 0) {
|
||||
GPU_link(mat, "node_attribute_volume_density",
|
||||
GPU_builtin(GPU_VOLUME_DENSITY),
|
||||
outcol, outvec, outf);
|
||||
}
|
||||
else if (strcmp(name, "color") == 0) {
|
||||
GPU_link(mat, "node_attribute_volume_color",
|
||||
GPU_builtin(GPU_VOLUME_DENSITY),
|
||||
outcol, outvec, outf);
|
||||
}
|
||||
else if (strcmp(name, "flame") == 0) {
|
||||
GPU_link(mat, "node_attribute_volume_flame",
|
||||
GPU_builtin(GPU_VOLUME_FLAME),
|
||||
outcol, outvec, outf);
|
||||
}
|
||||
else if (strcmp(name, "temperature") == 0) {
|
||||
GPU_link(mat, "node_attribute_volume_temperature",
|
||||
GPU_builtin(GPU_VOLUME_FLAME),
|
||||
GPU_builtin(GPU_VOLUME_TEMPERATURE),
|
||||
outcol, outvec, outf);
|
||||
}
|
||||
else {
|
||||
*outcol = *outvec = *outf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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_uniform(&one);
|
||||
}
|
||||
if (!color) {
|
||||
static float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
color = GPU_uniform(white);
|
||||
}
|
||||
if (!temperature) {
|
||||
static float one = 1.0f;
|
||||
temperature = GPU_uniform(&one);
|
||||
}
|
||||
|
||||
/* Create blackbody spectrum. */
|
||||
GPUNodeLink *spectrummap;
|
||||
if (use_blackbody) {
|
||||
const int size = 256;
|
||||
float *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);
|
||||
}
|
||||
|
||||
return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap);
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
|
|
Loading…
Reference in New Issue