EEVEE Next: Volumes #107176
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
frag_gen << "}\n\n";
|
||||
}
|
||||
|
||||
info.fragment_source_generated = frag_gen.str();
|
||||
}
|
||||
pragma37 marked this conversation as resolved
Outdated
Clément Foucault
commented
This is kind of a codestyle thing. But this block is supposed to the the frag gen. so just add 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
|
||||
|
|
|
@ -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 ? */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
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.