Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee_next/eevee_material.hh')
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_material.hh257
1 files changed, 257 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee_next/eevee_material.hh b/source/blender/draw/engines/eevee_next/eevee_material.hh
new file mode 100644
index 00000000000..0c454128aba
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/eevee_material.hh
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2021 Blender Foundation.
+ */
+
+/** \file
+ * \ingroup eevee
+ */
+
+#pragma once
+
+#include "DRW_render.h"
+
+#include "BLI_map.hh"
+#include "BLI_vector.hh"
+#include "GPU_material.h"
+
+#include "eevee_sync.hh"
+
+namespace blender::eevee {
+
+class Instance;
+
+/* -------------------------------------------------------------------- */
+/** \name MaterialKey
+ *
+ * \{ */
+
+enum eMaterialPipeline {
+ MAT_PIPE_DEFERRED = 0,
+ MAT_PIPE_FORWARD = 1,
+ MAT_PIPE_DEFERRED_PREPASS = 2,
+ MAT_PIPE_FORWARD_PREPASS = 3,
+ MAT_PIPE_VOLUME = 4,
+ MAT_PIPE_SHADOW = 5,
+};
+
+enum eMaterialGeometry {
+ MAT_GEOM_MESH = 0,
+ MAT_GEOM_CURVES = 1,
+ MAT_GEOM_GPENCIL = 2,
+ MAT_GEOM_VOLUME = 3,
+ MAT_GEOM_WORLD = 4,
+};
+
+static inline void material_type_from_shader_uuid(uint64_t shader_uuid,
+ eMaterialPipeline &pipeline_type,
+ eMaterialGeometry &geometry_type)
+{
+ const uint64_t geometry_mask = ((1u << 3u) - 1u);
+ const uint64_t pipeline_mask = ((1u << 3u) - 1u);
+ geometry_type = static_cast<eMaterialGeometry>(shader_uuid & geometry_mask);
+ pipeline_type = static_cast<eMaterialPipeline>((shader_uuid >> 3u) & pipeline_mask);
+}
+
+static inline uint64_t shader_uuid_from_material_type(eMaterialPipeline pipeline_type,
+ eMaterialGeometry geometry_type)
+{
+ return geometry_type | (pipeline_type << 3);
+}
+
+ENUM_OPERATORS(eClosureBits, CLOSURE_AMBIENT_OCCLUSION)
+
+static inline eClosureBits shader_closure_bits_from_flag(const GPUMaterial *gpumat)
+{
+ eClosureBits closure_bits = eClosureBits(0);
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE)) {
+ closure_bits |= CLOSURE_DIFFUSE;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
+ closure_bits |= CLOSURE_TRANSPARENCY;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_EMISSION)) {
+ closure_bits |= CLOSURE_EMISSION;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY)) {
+ closure_bits |= CLOSURE_REFLECTION;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_SUBSURFACE)) {
+ closure_bits |= CLOSURE_SSS;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT)) {
+ closure_bits |= CLOSURE_REFRACTION;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_HOLDOUT)) {
+ closure_bits |= CLOSURE_HOLDOUT;
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_AO)) {
+ closure_bits |= CLOSURE_AMBIENT_OCCLUSION;
+ }
+ return closure_bits;
+}
+
+static inline eMaterialGeometry to_material_geometry(const Object *ob)
+{
+ switch (ob->type) {
+ case OB_CURVES:
+ return MAT_GEOM_CURVES;
+ case OB_VOLUME:
+ return MAT_GEOM_VOLUME;
+ case OB_GPENCIL:
+ return MAT_GEOM_GPENCIL;
+ default:
+ return MAT_GEOM_MESH;
+ }
+}
+
+/** Unique key to identify each material in the hashmap. */
+struct MaterialKey {
+ Material *mat;
+ uint64_t options;
+
+ MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline surface_pipeline)
+ : mat(mat_)
+ {
+ options = shader_uuid_from_material_type(surface_pipeline, geometry);
+ }
+
+ uint64_t hash(void) const
+ {
+ BLI_assert(options < sizeof(*mat));
+ return (uint64_t)mat + options;
+ }
+
+ bool operator<(const MaterialKey &k) const
+ {
+ return (mat < k.mat) || (options < k.options);
+ }
+
+ bool operator==(const MaterialKey &k) const
+ {
+ return (mat == k.mat) && (options == k.options);
+ }
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ShaderKey
+ *
+ * \{ */
+
+struct ShaderKey {
+ GPUShader *shader;
+ uint64_t options;
+
+ ShaderKey(GPUMaterial *gpumat, eMaterialGeometry geometry, eMaterialPipeline pipeline)
+ {
+ shader = GPU_material_get_shader(gpumat);
+ options = shader_uuid_from_material_type(pipeline, geometry);
+ options = (options << 16u) | shader_closure_bits_from_flag(gpumat);
+ }
+
+ uint64_t hash(void) const
+ {
+ return (uint64_t)shader + options;
+ }
+
+ bool operator<(const ShaderKey &k) const
+ {
+ return (shader == k.shader) ? (options < k.options) : (shader < k.shader);
+ }
+
+ bool operator==(const ShaderKey &k) const
+ {
+ return (shader == k.shader) && (options == k.options);
+ }
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Default Material Nodetree
+ *
+ * In order to support materials without nodetree we reuse and configure a standalone nodetree that
+ * we pass for shader generation. The GPUMaterial is still stored inside the Material even if
+ * it does not use the same nodetree.
+ *
+ * \{ */
+
+class DefaultSurfaceNodeTree {
+ private:
+ bNodeTree *ntree_;
+ bNodeSocketValueRGBA *color_socket_;
+ bNodeSocketValueFloat *metallic_socket_;
+ bNodeSocketValueFloat *roughness_socket_;
+ bNodeSocketValueFloat *specular_socket_;
+
+ public:
+ DefaultSurfaceNodeTree();
+ ~DefaultSurfaceNodeTree();
+
+ bNodeTree *nodetree_get(::Material *ma);
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Material
+ *
+ * \{ */
+
+struct MaterialPass {
+ GPUMaterial *gpumat = nullptr;
+ DRWShadingGroup *shgrp = nullptr;
+};
+
+struct Material {
+ bool init = false;
+ bool is_alpha_blend_transparent;
+ MaterialPass shadow, shading, prepass;
+};
+
+struct MaterialArray {
+ Vector<Material *> materials;
+ Vector<GPUMaterial *> gpu_materials;
+};
+
+class MaterialModule {
+ public:
+ ::Material *diffuse_mat_;
+ ::Material *glossy_mat_;
+
+ private:
+ Instance &inst_;
+
+ Map<MaterialKey, Material *> material_map_;
+ Map<ShaderKey, DRWShadingGroup *> shader_map_;
+
+ MaterialArray material_array_;
+
+ DefaultSurfaceNodeTree default_surface_ntree_;
+
+ ::Material *error_mat_;
+
+ int64_t queued_shaders_count_ = 0;
+
+ public:
+ MaterialModule(Instance &inst);
+ ~MaterialModule();
+
+ void begin_sync(void);
+
+ MaterialArray &material_array_get(Object *ob);
+ Material &material_get(Object *ob, int mat_nr, eMaterialGeometry geometry_type);
+
+ private:
+ Material &material_sync(::Material *blender_mat, eMaterialGeometry geometry_type);
+
+ ::Material *material_from_slot(Object *ob, int slot);
+ MaterialPass material_pass_get(::Material *blender_mat,
+ eMaterialPipeline pipeline_type,
+ eMaterialGeometry geometry_type);
+};
+
+/** \} */
+
+} // namespace blender::eevee \ No newline at end of file