Eevee: add Principled Volume shader.

This commit is contained in:
Brecht Van Lommel 2018-02-22 20:04:20 +01:00
parent 77062e8bbb
commit 38ccd1fe33
2 changed files with 147 additions and 2 deletions

View File

@ -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)

View File

@ -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 */