EEVEE Next: Volumes #107176

Merged
Miguel Pozo merged 126 commits from pragma37/blender:pull-eevee-next-volumes into main 2023-08-04 16:47:22 +02:00
6 changed files with 119 additions and 103 deletions
Showing only changes of commit 9a96591730 - Show all commits

View File

@ -33,6 +33,7 @@ enum eMaterialPipeline {
MAT_PIPE_FORWARD_PREPASS,
MAT_PIPE_FORWARD_PREPASS_VELOCITY,
MAT_PIPE_VOLUME,
MAT_PIPE_WORLD_VOLUME,
MAT_PIPE_SHADOW,
};

View File

@ -318,6 +318,7 @@ class PipelineModule {
return forward.material_opaque_add(blender_mat, gpumat);
case MAT_PIPE_VOLUME:
case MAT_PIPE_WORLD_VOLUME:
/* TODO(fclem) volume pass. */
return nullptr;
case MAT_PIPE_SHADOW:

View File

@ -332,7 +332,7 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
break;
}
const bool do_fragment_attrib_load = (geometry_type == MAT_GEOM_WORLD);
const bool do_fragment_attrib_load = ELEM(geometry_type, MAT_GEOM_WORLD, MAT_GEOM_VOLUME);
if (do_fragment_attrib_load && !info.vertex_out_interfaces_.is_empty()) {
/* Codegen outputs only one interface. */
@ -378,106 +378,106 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
{
frag_gen << ((codegen.material_functions) ? codegen.material_functions : "\n");
if (codegen.displacement) {
/* Bump displacement. Needed to recompute normals after displacement. */
info.define("MAT_DISPLACEMENT_BUMP");
frag_gen << "vec3 nodetree_displacement()\n";
if (ELEM(pipeline_type, MAT_PIPE_WORLD_VOLUME, MAT_PIPE_VOLUME)) {
frag_gen << "Closure nodetree_volume()\n";
frag_gen << "{\n";
frag_gen << codegen.displacement;
/* frag_gen << " closure_weights_reset();\n"; TODO(Miguel Pozo) */
frag_gen << ((codegen.volume) ? codegen.volume : "return Closure(0);\n");
frag_gen << "}\n\n";
}
else {
if (codegen.displacement) {
/* Bump displacement. Needed to recompute normals after displacement. */
info.define("MAT_DISPLACEMENT_BUMP");
frag_gen << "Closure nodetree_surface()\n";
frag_gen << "{\n";
frag_gen << " closure_weights_reset();\n";
frag_gen << ((codegen.surface) ? codegen.surface : "return Closure(0);\n");
frag_gen << "}\n\n";
frag_gen << "vec3 nodetree_displacement()\n";
frag_gen << "{\n";
frag_gen << codegen.displacement;
frag_gen << "}\n\n";
}
frag_gen << "Closure nodetree_volume()\n";
frag_gen << "{\n";
frag_gen << " closure_weights_reset();\n";
frag_gen << ((codegen.volume) ? codegen.volume : "return Closure(0);\n");
frag_gen << "}\n\n";
frag_gen << "Closure nodetree_surface()\n";
frag_gen << "{\n";
frag_gen << " closure_weights_reset();\n";
frag_gen << ((codegen.surface) ? codegen.surface : "return Closure(0);\n");
frag_gen << "}\n\n";
frag_gen << "float nodetree_thickness()\n";
frag_gen << "{\n";
/* TODO(fclem): Better default. */
frag_gen << ((codegen.thickness) ? codegen.thickness : "return 0.1;\n");
frag_gen << "}\n\n";
frag_gen << "float nodetree_thickness()\n";
frag_gen << "{\n";
/* TODO(fclem): Better default. */
frag_gen << ((codegen.thickness) ? codegen.thickness : "return 0.1;\n");
pragma37 marked this conversation as resolved

Having the default case be the compute one is a bit weird. Maybe have do_compute_attrib_load = (pipeline_type == MAT_PIPE_VOLUME) for clarity and test for this instead.

Having the default case be the compute one is a bit weird. Maybe have `do_compute_attrib_load = (pipeline_type == MAT_PIPE_VOLUME)` for clarity and test for this instead.
frag_gen << "}\n\n";
}
info.fragment_source_generated = frag_gen.str();
}
pragma37 marked this conversation as resolved Outdated

This is kind of a codestyle thing. But this block is supposed to the the frag gen. so just add if (!is_compute) here. Same for vertex.

This is kind of a codestyle thing. But this block is supposed to the the frag gen. so just add `if (!is_compute)` here. Same for vertex.
/* Volumes */
if (pipeline_type == MAT_PIPE_VOLUME) {
switch (geometry_type) {
/* TODO (Miguel Pozo): Not technically correct. It's still volume geometry */
case MAT_GEOM_WORLD:
if (geometry_type == MAT_GEOM_VOLUME) {
switch (pipeline_type) {
case MAT_PIPE_WORLD_VOLUME:
info.additional_info("eevee_volume_world");
break;
case MAT_GEOM_VOLUME:
case MAT_PIPE_VOLUME:
info.additional_info("eevee_volume_object");
break;
default:
BLI_assert_unreachable();
}
return;
}
/* Geometry Info. */
switch (geometry_type) {
case MAT_GEOM_WORLD:
info.additional_info("eevee_geom_world");
break;
case MAT_GEOM_VOLUME:
BLI_assert_unreachable();
break;
case MAT_GEOM_GPENCIL:
info.additional_info("eevee_geom_gpencil");
break;
case MAT_GEOM_CURVES:
info.additional_info("eevee_geom_curves");
break;
case MAT_GEOM_MESH:
default:
info.additional_info("eevee_geom_mesh");
break;
}
/* Pipeline Info. */
switch (geometry_type) {
case MAT_GEOM_WORLD:
info.additional_info("eevee_surf_world");
break;
case MAT_GEOM_VOLUME:
BLI_assert_unreachable();
break;
default:
switch (pipeline_type) {
case MAT_PIPE_FORWARD_PREPASS_VELOCITY:
case MAT_PIPE_DEFERRED_PREPASS_VELOCITY:
info.additional_info("eevee_surf_depth", "eevee_velocity_geom");
break;
case MAT_PIPE_FORWARD_PREPASS:
case MAT_PIPE_DEFERRED_PREPASS:
info.additional_info("eevee_surf_depth");
break;
case MAT_PIPE_SHADOW:
info.additional_info("eevee_surf_shadow");
break;
case MAT_PIPE_DEFERRED:
info.additional_info("eevee_surf_deferred");
break;
case MAT_PIPE_FORWARD:
info.additional_info("eevee_surf_forward");
break;
default:
BLI_assert(0);
break;
}
break;
else {
/* Geometry Info. */
switch (geometry_type) {
case MAT_GEOM_WORLD:
info.additional_info("eevee_geom_world");
break;
case MAT_GEOM_VOLUME:
BLI_assert_unreachable();
break;
case MAT_GEOM_GPENCIL:
info.additional_info("eevee_geom_gpencil");
break;
case MAT_GEOM_CURVES:
info.additional_info("eevee_geom_curves");
break;
case MAT_GEOM_MESH:
default:
info.additional_info("eevee_geom_mesh");
break;
}
/* Pipeline Info. */
switch (geometry_type) {
case MAT_GEOM_WORLD:
info.additional_info("eevee_surf_world");
break;
case MAT_GEOM_VOLUME:
BLI_assert_unreachable();
break;
default:
switch (pipeline_type) {
case MAT_PIPE_FORWARD_PREPASS_VELOCITY:
case MAT_PIPE_DEFERRED_PREPASS_VELOCITY:
info.additional_info("eevee_surf_depth", "eevee_velocity_geom");
break;
case MAT_PIPE_FORWARD_PREPASS:
case MAT_PIPE_DEFERRED_PREPASS:
info.additional_info("eevee_surf_depth");
break;
case MAT_PIPE_SHADOW:
info.additional_info("eevee_surf_shadow");
break;
case MAT_PIPE_DEFERRED:
info.additional_info("eevee_surf_deferred");
break;
case MAT_PIPE_FORWARD:
info.additional_info("eevee_surf_forward");
break;
default:
BLI_assert(0);
break;
}
break;
}
}
}
@ -494,9 +494,10 @@ GPUMaterial *ShaderModule::material_shader_get(::Material *blender_mat,
eMaterialGeometry geometry_type,
bool deferred_compilation)
{
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type);
bool is_volume = (pipeline_type == MAT_PIPE_VOLUME);
BLI_assert(pipeline_type != MAT_PIPE_WORLD_VOLUME);
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type);
return DRW_shader_from_material(
blender_mat, nodetree, shader_uuid, is_volume, deferred_compilation, codegen_callback, this);
@ -506,20 +507,15 @@ GPUMaterial *ShaderModule::world_shader_get(::World *blender_world,
struct bNodeTree *nodetree,
eMaterialPipeline pipeline_type)
{
bool is_volume = (pipeline_type == MAT_PIPE_VOLUME);
bool deferred_compilation = false;
bool is_volume = (pipeline_type == MAT_PIPE_WORLD_VOLUME);
BLI_assert(pipeline_type != MAT_PIPE_VOLUME);
eMaterialGeometry geometry_type = MAT_GEOM_WORLD;
eMaterialGeometry geometry_type = is_volume ? MAT_GEOM_VOLUME : MAT_GEOM_WORLD;
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type);
return DRW_shader_from_world(blender_world,
nodetree,
shader_uuid,
is_volume,
deferred_compilation,
codegen_callback,
this);
return DRW_shader_from_world(
blender_world, nodetree, shader_uuid, is_volume, false, codegen_callback, this);
}
/* Variation to compile a material only with a nodetree. Caller needs to maintain the list of

View File

@ -224,7 +224,7 @@ void Volumes::begin_sync()
if (world && world->use_nodes && world->nodetree &&
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
mat = inst_.shaders.world_shader_get(world, world->nodetree, MAT_PIPE_VOLUME);
mat = inst_.shaders.world_shader_get(world, world->nodetree, MAT_PIPE_WORLD_VOLUME);
if (!GPU_material_has_volume_output(mat)) {
/* TODO (Miguel Pozo): This should never happen ? */

View File

@ -210,7 +210,7 @@ float ambient_occlusion_eval(vec3 normal,
#ifndef GPU_METAL
void attrib_load();
Closure nodetree_surface();
Closure nodetree_volume();
/* Closure nodetree_volume(); */
vec3 nodetree_displacement();
float nodetree_thickness();
vec4 closure_to_rgba(Closure cl);

View File

@ -1,6 +1,15 @@
#pragma BLENDER_REQUIRE(eevee_volume_lib.glsl)
/* Needed includes for shader nodes. */
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_attribute_lib.glsl)
#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
#pragma BLENDER_REQUIRE(closure_eval_volume_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
@ -33,6 +42,8 @@ GlobalData init_globals(void)
return surf;
}
/* TODO (Miguel Pozo): Already defined at eevee_attributes_lib.glsl. Check differences. */
#if 0
vec3 coordinate_camera(vec3 P)
{
vec3 vP;
@ -58,6 +69,10 @@ vec3 coordinate_incoming(vec3 P)
{
return cameraVec(P);
}
#endif
Closure nodetree_volume();
void attrib_load();
void main()
{
@ -86,7 +101,7 @@ void main()
#ifndef NO_ATTRIB_LOAD
attrib_load();
#endif
Closure cl = nodetree_exec();
Closure cl = nodetree_volume();
#ifdef MESH_SHADER
cl.scatter *= drw_volume.density_scale;
cl.absorption *= drw_volume.density_scale;
@ -105,15 +120,17 @@ void main()
}
}
/* TODO (Miguel Pozo): Already defined at eevee_attributes_lib.glsl. Check differences. */
#if 0
vec3 grid_coordinates()
{
vec3 co = volumeOrco;
#ifdef MESH_SHADER
# ifdef MESH_SHADER
/* Optional per-grid transform. */
if (drw_volume.grids_xform[attr_id][3][3] != 0.0) {
co = (drw_volume.grids_xform[attr_id] * vec4(objectPosition, 1.0)).xyz;
}
#endif
# endif
attr_id += 1;
return co;
}
@ -149,23 +166,24 @@ float attr_load_float(sampler3D tex)
* the engine side. But as of now, the engines are responsible for loading the attributes. */
float attr_load_temperature_post(float attr)
{
#ifdef MESH_SHADER
# ifdef MESH_SHADER
/* Bring the into standard range without having to modify the grid values */
attr = (attr > 0.01) ? (attr * drw_volume.temperature_mul + drw_volume.temperature_bias) : 0.0;
#endif
# endif
return attr;
}
vec4 attr_load_color_post(vec4 attr)
{
#ifdef MESH_SHADER
# ifdef MESH_SHADER
/* Density is premultiplied for interpolation, divide it out here. */
attr.rgb *= safe_rcp(attr.a);
attr.rgb *= drw_volume.color_mul.rgb;
attr.a = 1.0;
#endif
# endif
return attr;
}
vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
{
return attr;
}
#endif