2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup gpu
|
2014-01-19 23:14:24 +11:00
|
|
|
*
|
|
|
|
|
* Manages materials, lights and textures.
|
2011-02-27 20:25:53 +00:00
|
|
|
*/
|
|
|
|
|
|
2023-08-02 20:15:49 +10:00
|
|
|
#include <cstring>
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
|
|
2018-07-20 20:06:39 +02:00
|
|
|
#include "BLI_listbase.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_vector.h"
|
2018-08-02 18:31:38 +02:00
|
|
|
#include "BLI_string.h"
|
2024-01-19 14:32:28 +01:00
|
|
|
#include "BLI_time.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2025-01-09 17:26:40 +01:00
|
|
|
#include "BKE_material.hh"
|
2024-02-19 15:26:10 +01:00
|
|
|
#include "BKE_node.hh"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2022-01-24 16:18:30 -06:00
|
|
|
#include "NOD_shader.h"
|
|
|
|
|
|
2024-02-01 10:40:24 -05:00
|
|
|
#include "GPU_material.hh"
|
2025-05-22 17:53:22 +02:00
|
|
|
#include "GPU_pass.hh"
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "GPU_shader.hh"
|
|
|
|
|
#include "GPU_texture.hh"
|
2024-02-11 16:10:00 -05:00
|
|
|
#include "GPU_uniform_buffer.hh"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2024-01-05 11:16:57 -05:00
|
|
|
#include "DRW_engine.hh"
|
2018-03-05 00:54:31 +01:00
|
|
|
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "gpu_node_graph.hh"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2022-04-20 14:35:07 +02:00
|
|
|
#include "atomic_ops.h"
|
|
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
static void gpu_material_ramp_texture_build(GPUMaterial *mat);
|
|
|
|
|
static void gpu_material_sky_texture_build(GPUMaterial *mat);
|
|
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
/* Structs */
|
2018-08-10 15:13:39 +02:00
|
|
|
#define MAX_COLOR_BAND 128
|
2022-09-16 15:04:47 +02:00
|
|
|
#define MAX_GPU_SKIES 8
|
2018-08-10 15:13:39 +02:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
struct GPUColorBandBuilder {
|
2018-08-10 15:13:39 +02:00
|
|
|
float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4];
|
|
|
|
|
int current_layer;
|
2023-07-27 14:16:58 +02:00
|
|
|
};
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
struct GPUSkyBuilder {
|
2022-09-16 15:04:47 +02:00
|
|
|
float pixels[MAX_GPU_SKIES][GPU_SKY_WIDTH * GPU_SKY_HEIGHT][4];
|
|
|
|
|
int current_layer;
|
2023-07-27 14:16:58 +02:00
|
|
|
};
|
2022-09-16 15:04:47 +02:00
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
struct GPUMaterial {
|
2022-09-23 14:33:43 +10:00
|
|
|
/* Contains #GPUShader and source code for deferred compilation.
|
2025-05-22 17:53:22 +02:00
|
|
|
* Can be shared between materials sharing same node-tree topology. */
|
|
|
|
|
GPUPass *pass = nullptr;
|
2023-02-14 21:51:03 +01:00
|
|
|
/* Optimized GPUPass, situationally compiled after initial pass for optimal realtime performance.
|
|
|
|
|
* This shader variant bakes dynamic uniform data as constant. This variant will not use
|
|
|
|
|
* the ubo, and instead bake constants directly into the shader source. */
|
2025-05-22 17:53:22 +02:00
|
|
|
GPUPass *optimized_pass = nullptr;
|
|
|
|
|
|
|
|
|
|
/* UBOs for this material parameters. */
|
|
|
|
|
GPUUniformBuf *ubo = nullptr;
|
|
|
|
|
/* Some flags about the nodetree & the needed resources. */
|
|
|
|
|
eGPUMaterialFlag flag = GPU_MATFLAG_UPDATED;
|
|
|
|
|
/* The engine type this material is compiled for. */
|
2023-12-07 16:48:09 +01:00
|
|
|
eGPUMaterialEngine engine;
|
|
|
|
|
/* Identify shader variations (shadow, probe, world background...) */
|
2025-05-22 17:53:22 +02:00
|
|
|
uint64_t uuid = 0;
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Number of generated function. */
|
2025-05-22 17:53:22 +02:00
|
|
|
int generated_function_len = 0;
|
|
|
|
|
|
|
|
|
|
/* Source material, might be null. */
|
|
|
|
|
Material *source_material = nullptr;
|
|
|
|
|
/* 1D Texture array containing all color bands. */
|
|
|
|
|
GPUTexture *coba_tex = nullptr;
|
|
|
|
|
/* Builder for coba_tex. */
|
|
|
|
|
GPUColorBandBuilder *coba_builder = nullptr;
|
|
|
|
|
/* 2D Texture array containing all sky textures. */
|
|
|
|
|
GPUTexture *sky_tex = nullptr;
|
|
|
|
|
/* Builder for sky_tex. */
|
|
|
|
|
GPUSkyBuilder *sky_builder = nullptr;
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Low level node graph(s). Also contains resources needed by the material. */
|
2025-05-22 17:53:22 +02:00
|
|
|
GPUNodeGraph graph = {};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
bool has_surface_output = false;
|
|
|
|
|
bool has_volume_output = false;
|
|
|
|
|
bool has_displacement_output = false;
|
2023-02-14 21:51:03 +01:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
std::string name;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
GPUMaterial(eGPUMaterialEngine engine) : engine(engine)
|
|
|
|
|
{
|
|
|
|
|
graph.used_libraries = BLI_gset_new(
|
|
|
|
|
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries");
|
|
|
|
|
};
|
2022-04-20 14:35:07 +02:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
~GPUMaterial()
|
|
|
|
|
{
|
|
|
|
|
gpu_node_graph_free(&graph);
|
2024-06-07 16:11:50 +02:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
if (optimized_pass != nullptr) {
|
|
|
|
|
GPU_pass_release(optimized_pass);
|
|
|
|
|
}
|
|
|
|
|
if (pass != nullptr) {
|
|
|
|
|
GPU_pass_release(pass);
|
|
|
|
|
}
|
|
|
|
|
if (ubo != nullptr) {
|
|
|
|
|
GPU_uniformbuf_free(ubo);
|
|
|
|
|
}
|
|
|
|
|
if (coba_builder != nullptr) {
|
|
|
|
|
MEM_freeN(coba_builder);
|
|
|
|
|
}
|
|
|
|
|
if (coba_tex != nullptr) {
|
|
|
|
|
GPU_texture_free(coba_tex);
|
|
|
|
|
}
|
|
|
|
|
if (sky_tex != nullptr) {
|
|
|
|
|
GPU_texture_free(sky_tex);
|
|
|
|
|
}
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
};
|
|
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
/* Public API */
|
|
|
|
|
|
|
|
|
|
GPUMaterial *GPU_material_from_nodetree(Material *ma,
|
|
|
|
|
bNodeTree *ntree,
|
|
|
|
|
ListBase *gpumaterials,
|
|
|
|
|
const char *name,
|
|
|
|
|
eGPUMaterialEngine engine,
|
|
|
|
|
uint64_t shader_uuid,
|
|
|
|
|
bool deferred_compilation,
|
|
|
|
|
GPUCodegenCallbackFn callback,
|
|
|
|
|
void *thunk,
|
|
|
|
|
GPUMaterialPassReplacementCallbackFn pass_replacement_cb)
|
|
|
|
|
{
|
|
|
|
|
/* Search if this material is not already compiled. */
|
|
|
|
|
LISTBASE_FOREACH (LinkData *, link, gpumaterials) {
|
|
|
|
|
GPUMaterial *mat = (GPUMaterial *)link->data;
|
|
|
|
|
if (mat->uuid == shader_uuid && mat->engine == engine) {
|
|
|
|
|
if (!deferred_compilation) {
|
|
|
|
|
GPU_pass_ensure_its_ready(mat->pass);
|
|
|
|
|
}
|
|
|
|
|
return mat;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUMaterial *mat = MEM_new<GPUMaterial>(__func__, engine);
|
|
|
|
|
mat->source_material = ma;
|
|
|
|
|
mat->uuid = shader_uuid;
|
|
|
|
|
mat->name = name;
|
|
|
|
|
|
|
|
|
|
/* Localize tree to create links for reroute and mute. */
|
|
|
|
|
bNodeTree *localtree = blender::bke::node_tree_localize(ntree, nullptr);
|
|
|
|
|
ntreeGPUMaterialNodes(localtree, mat);
|
|
|
|
|
|
|
|
|
|
gpu_material_ramp_texture_build(mat);
|
|
|
|
|
gpu_material_sky_texture_build(mat);
|
|
|
|
|
|
|
|
|
|
/* Use default material pass when possible. */
|
|
|
|
|
if (GPUPass *default_pass = pass_replacement_cb ? pass_replacement_cb(thunk, mat) : nullptr) {
|
|
|
|
|
mat->pass = default_pass;
|
|
|
|
|
GPU_pass_acquire(mat->pass);
|
|
|
|
|
/** WORKAROUND:
|
|
|
|
|
* The node tree code is never executed in default replaced passes,
|
|
|
|
|
* but the GPU validation will still complain if the node tree UBO is not bound.
|
|
|
|
|
* So we create a dummy UBO with (at least) the size of the default material one (192 bytes).
|
|
|
|
|
* We allocate 256 bytes to leave some room for future changes. */
|
|
|
|
|
mat->ubo = GPU_uniformbuf_create_ex(256, nullptr, "Dummy UBO");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Create source code and search pass cache for an already compiled version. */
|
|
|
|
|
mat->pass = GPU_generate_pass(
|
|
|
|
|
mat, &mat->graph, mat->name.c_str(), engine, deferred_compilation, callback, thunk, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Determine whether we should generate an optimized variant of the graph.
|
|
|
|
|
* Heuristic is based on complexity of default material pass and shader node graph. */
|
|
|
|
|
if (GPU_pass_should_optimize(mat->pass)) {
|
|
|
|
|
mat->optimized_pass = GPU_generate_pass(
|
|
|
|
|
mat, &mat->graph, mat->name.c_str(), engine, true, callback, thunk, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gpu_node_graph_free_nodes(&mat->graph);
|
|
|
|
|
/* Only free after GPU_pass_shader_get where GPUUniformBuf read data from the local tree. */
|
|
|
|
|
blender::bke::node_tree_free_local_tree(localtree);
|
|
|
|
|
BLI_assert(!localtree->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
|
|
|
|
|
MEM_freeN(localtree);
|
|
|
|
|
|
|
|
|
|
/* Note that even if building the shader fails in some way, we want to keep
|
|
|
|
|
* it to avoid trying to compile again and again, and simply do not use
|
|
|
|
|
* the actual shader on drawing. */
|
|
|
|
|
LinkData *link = MEM_callocN<LinkData>("GPUMaterialLink");
|
|
|
|
|
link->data = mat;
|
|
|
|
|
BLI_addtail(gpumaterials, link);
|
|
|
|
|
|
|
|
|
|
return mat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUMaterial *GPU_material_from_callbacks(eGPUMaterialEngine engine,
|
|
|
|
|
ConstructGPUMaterialFn construct_function_cb,
|
|
|
|
|
GPUCodegenCallbackFn generate_code_function_cb,
|
|
|
|
|
void *thunk)
|
|
|
|
|
{
|
|
|
|
|
/* Allocate a new material and its material graph. */
|
|
|
|
|
GPUMaterial *material = MEM_new<GPUMaterial>(__func__, engine);
|
|
|
|
|
|
|
|
|
|
/* Construct the material graph by adding and linking the necessary GPU material nodes. */
|
|
|
|
|
construct_function_cb(thunk, material);
|
|
|
|
|
|
|
|
|
|
/* Create and initialize the texture storing color bands used by Ramp and Curve nodes. */
|
|
|
|
|
gpu_material_ramp_texture_build(material);
|
|
|
|
|
|
|
|
|
|
/* Lookup an existing pass in the cache or generate a new one. */
|
|
|
|
|
material->pass = GPU_generate_pass(material,
|
|
|
|
|
&material->graph,
|
|
|
|
|
__func__,
|
|
|
|
|
engine,
|
|
|
|
|
false,
|
|
|
|
|
generate_code_function_cb,
|
|
|
|
|
thunk,
|
|
|
|
|
false);
|
|
|
|
|
|
|
|
|
|
/* Determine whether we should generate an optimized variant of the graph.
|
|
|
|
|
* Heuristic is based on complexity of default material pass and shader node graph. */
|
|
|
|
|
if (GPU_pass_should_optimize(material->pass)) {
|
|
|
|
|
material->optimized_pass = GPU_generate_pass(material,
|
|
|
|
|
&material->graph,
|
|
|
|
|
__func__,
|
|
|
|
|
engine,
|
|
|
|
|
true,
|
|
|
|
|
generate_code_function_cb,
|
|
|
|
|
thunk,
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gpu_node_graph_free_nodes(&material->graph);
|
|
|
|
|
|
|
|
|
|
return material;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_free_single(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
MEM_delete(material);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_free(ListBase *gpumaterial)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (LinkData *, link, gpumaterial) {
|
|
|
|
|
GPUMaterial *material = static_cast<GPUMaterial *>(link->data);
|
|
|
|
|
GPU_material_free_single(material);
|
|
|
|
|
}
|
|
|
|
|
BLI_freelistN(gpumaterial);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_materials_free(Main *bmain)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
|
|
|
|
|
GPU_material_free(&ma->gpumaterial);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (World *, wo, &bmain->worlds) {
|
|
|
|
|
GPU_material_free(&wo->gpumaterial);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_material_defaults_free_gpu();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *GPU_material_get_name(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->name.c_str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t GPU_material_uuid_get(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->uuid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Material *GPU_material_get_material(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->source_material;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUPass *GPU_material_get_pass(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
/* If an optimized pass variant is available, and optimization is
|
|
|
|
|
* flagged as complete, we use this one instead. */
|
|
|
|
|
return GPU_material_optimization_status(material) == GPU_MAT_OPTIMIZATION_SUCCESS ?
|
|
|
|
|
material->optimized_pass :
|
|
|
|
|
material->pass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUShader *GPU_material_get_shader(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return GPU_pass_shader_get(GPU_material_get_pass(material));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
switch (GPU_pass_status(mat->pass)) {
|
|
|
|
|
case GPU_PASS_SUCCESS:
|
|
|
|
|
return GPU_MAT_SUCCESS;
|
|
|
|
|
case GPU_PASS_QUEUED:
|
|
|
|
|
return GPU_MAT_QUEUED;
|
|
|
|
|
default:
|
|
|
|
|
return GPU_MAT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eGPUMaterialOptimizationStatus GPU_material_optimization_status(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
if (!GPU_pass_should_optimize(mat->pass)) {
|
|
|
|
|
return GPU_MAT_OPTIMIZATION_SKIP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (GPU_pass_status(mat->optimized_pass)) {
|
|
|
|
|
case GPU_PASS_SUCCESS:
|
|
|
|
|
return GPU_MAT_OPTIMIZATION_SUCCESS;
|
|
|
|
|
case GPU_PASS_QUEUED:
|
|
|
|
|
return GPU_MAT_OPTIMIZATION_QUEUED;
|
|
|
|
|
default:
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return GPU_MAT_OPTIMIZATION_SKIP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t GPU_material_compilation_timestamp(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return GPU_pass_compilation_timestamp(mat->pass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_material_has_surface_output(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->has_surface_output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_material_has_volume_output(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->has_volume_output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_material_has_displacement_output(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->has_displacement_output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
|
|
|
|
|
{
|
|
|
|
|
return (mat->flag & flag) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eGPUMaterialFlag GPU_material_flag(const GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag)
|
|
|
|
|
{
|
|
|
|
|
if ((flag & GPU_MATFLAG_GLOSSY) && (mat->flag & GPU_MATFLAG_GLOSSY)) {
|
|
|
|
|
/* Tag material using multiple glossy BSDF as using clear coat. */
|
|
|
|
|
mat->flag |= GPU_MATFLAG_COAT;
|
|
|
|
|
}
|
|
|
|
|
mat->flag |= flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
|
|
|
|
|
{
|
|
|
|
|
material->ubo = GPU_uniformbuf_create_from_list(inputs, material->name.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUUniformBuf *GPU_material_uniform_buffer_get(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->ubo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListBase GPU_material_attributes(const GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->graph.attributes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListBase GPU_material_textures(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->graph.textures;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const GPUUniformAttrList *GPU_material_uniform_attributes(const GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
const GPUUniformAttrList *attrs = &material->graph.uniform_attrs;
|
|
|
|
|
return attrs->count > 0 ? attrs : nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ListBase *GPU_material_layer_attributes(const GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
const ListBase *attrs = &material->graph.layer_attrs;
|
|
|
|
|
return !BLI_listbase_is_empty(attrs) ? attrs : nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUNodeGraph *gpu_material_node_graph(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return &material->graph;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Resources */
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2022-09-16 15:04:47 +02:00
|
|
|
GPUTexture **gpu_material_sky_texture_layer_set(
|
|
|
|
|
GPUMaterial *mat, int width, int height, const float *pixels, float *row)
|
|
|
|
|
{
|
|
|
|
|
/* In order to put all sky textures into one 2D array texture,
|
|
|
|
|
* we need them to be the same size. */
|
|
|
|
|
BLI_assert(width == GPU_SKY_WIDTH);
|
|
|
|
|
BLI_assert(height == GPU_SKY_HEIGHT);
|
|
|
|
|
UNUSED_VARS_NDEBUG(width, height);
|
|
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->sky_builder == nullptr) {
|
2025-04-22 11:22:18 +02:00
|
|
|
mat->sky_builder = MEM_mallocN<GPUSkyBuilder>("GPUSkyBuilder");
|
2022-09-16 15:04:47 +02:00
|
|
|
mat->sky_builder->current_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int layer = mat->sky_builder->current_layer;
|
2023-07-28 09:38:07 +10:00
|
|
|
*row = float(layer);
|
2022-09-16 15:04:47 +02:00
|
|
|
|
|
|
|
|
if (*row == MAX_GPU_SKIES) {
|
|
|
|
|
printf("Too many sky textures in shader!\n");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
float *dst = (float *)mat->sky_builder->pixels[layer];
|
|
|
|
|
memcpy(dst, pixels, sizeof(float) * GPU_SKY_WIDTH * GPU_SKY_HEIGHT * 4);
|
|
|
|
|
mat->sky_builder->current_layer += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &mat->sky_tex;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-10 15:13:39 +02:00
|
|
|
GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
|
|
|
|
|
int size,
|
2024-07-29 13:01:12 +10:00
|
|
|
const float *pixels,
|
|
|
|
|
float *r_row)
|
2018-08-10 15:13:39 +02:00
|
|
|
{
|
2020-09-07 15:57:12 +10:00
|
|
|
/* In order to put all the color-bands into one 1D array texture,
|
2018-08-10 15:13:39 +02:00
|
|
|
* we need them to be the same size. */
|
|
|
|
|
BLI_assert(size == CM_TABLE + 1);
|
2018-09-10 09:56:14 +02:00
|
|
|
UNUSED_VARS_NDEBUG(size);
|
2018-08-10 15:13:39 +02:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->coba_builder == nullptr) {
|
2025-04-22 11:22:18 +02:00
|
|
|
mat->coba_builder = MEM_mallocN<GPUColorBandBuilder>("GPUColorBandBuilder");
|
2018-08-10 15:13:39 +02:00
|
|
|
mat->coba_builder->current_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int layer = mat->coba_builder->current_layer;
|
2024-07-29 13:01:12 +10:00
|
|
|
*r_row = float(layer);
|
2018-08-10 15:13:39 +02:00
|
|
|
|
2024-07-29 13:01:12 +10:00
|
|
|
if (*r_row == MAX_COLOR_BAND) {
|
2018-08-10 15:13:39 +02:00
|
|
|
printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
float *dst = (float *)mat->coba_builder->pixels[layer];
|
|
|
|
|
memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4);
|
|
|
|
|
mat->coba_builder->current_layer += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &mat->coba_tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gpu_material_ramp_texture_build(GPUMaterial *mat)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->coba_builder == nullptr) {
|
2018-08-10 15:13:39 +02:00
|
|
|
return;
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
2018-08-10 15:13:39 +02:00
|
|
|
|
|
|
|
|
GPUColorBandBuilder *builder = mat->coba_builder;
|
|
|
|
|
|
2023-02-25 01:52:27 +01:00
|
|
|
mat->coba_tex = GPU_texture_create_1d_array("mat_ramp",
|
|
|
|
|
CM_TABLE + 1,
|
|
|
|
|
builder->current_layer,
|
|
|
|
|
1,
|
|
|
|
|
GPU_RGBA16F,
|
|
|
|
|
GPU_TEXTURE_USAGE_SHADER_READ,
|
|
|
|
|
(float *)builder->pixels);
|
2018-08-10 15:13:39 +02:00
|
|
|
|
|
|
|
|
MEM_freeN(builder);
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->coba_builder = nullptr;
|
2018-08-10 15:13:39 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-16 15:04:47 +02:00
|
|
|
static void gpu_material_sky_texture_build(GPUMaterial *mat)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->sky_builder == nullptr) {
|
2022-09-16 15:04:47 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 01:52:27 +01:00
|
|
|
mat->sky_tex = GPU_texture_create_2d_array("mat_sky",
|
|
|
|
|
GPU_SKY_WIDTH,
|
|
|
|
|
GPU_SKY_HEIGHT,
|
|
|
|
|
mat->sky_builder->current_layer,
|
|
|
|
|
1,
|
|
|
|
|
GPU_RGBA32F,
|
2023-04-18 08:11:46 +02:00
|
|
|
GPU_TEXTURE_USAGE_SHADER_READ,
|
2023-02-25 01:52:27 +01:00
|
|
|
(float *)mat->sky_builder->pixels);
|
2022-09-16 15:04:47 +02:00
|
|
|
|
|
|
|
|
MEM_freeN(mat->sky_builder);
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->sky_builder = nullptr;
|
2022-09-16 15:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
/* Code generation */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
void GPU_material_output_surface(GPUMaterial *material, GPUNodeLink *link)
|
|
|
|
|
{
|
|
|
|
|
if (!material->graph.outlink_surface) {
|
|
|
|
|
material->graph.outlink_surface = link;
|
|
|
|
|
material->has_surface_output = true;
|
2022-09-16 15:04:47 +02:00
|
|
|
}
|
2018-06-08 16:11:34 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
void GPU_material_output_volume(GPUMaterial *material, GPUNodeLink *link)
|
2018-06-08 16:11:34 +02:00
|
|
|
{
|
2025-05-22 17:53:22 +02:00
|
|
|
if (!material->graph.outlink_volume) {
|
|
|
|
|
material->graph.outlink_volume = link;
|
|
|
|
|
material->has_volume_output = true;
|
2018-06-08 16:11:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2017-11-14 00:49:54 +01:00
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
void GPU_material_output_displacement(GPUMaterial *material, GPUNodeLink *link)
|
2013-11-25 20:58:23 +09:00
|
|
|
{
|
2025-05-22 17:53:22 +02:00
|
|
|
if (!material->graph.outlink_displacement) {
|
|
|
|
|
material->graph.outlink_displacement = link;
|
|
|
|
|
material->has_displacement_output = true;
|
|
|
|
|
}
|
Materials: add custom object properties as uniform attributes.
This patch allows the user to type a property name into the
Attribute node, which will then output the value of the property
for each individual object, allowing to e.g. customize shaders
by object without duplicating the shader.
In order to make supporting this easier for Eevee, it is necessary
to explicitly choose whether the attribute is varying or uniform
via a dropdown option of the Attribute node. The dropdown also
allows choosing whether instancing should be taken into account.
The Cycles design treats all attributes as one common namespace,
so the Blender interface converts the enum to a name prefix that
can't be entered using keyboard.
In Eevee, the attributes are provided to the shader via a UBO indexed
with resource_id, similar to the existing Object Info data. Unlike it,
however, it is necessary to maintain a separate buffer for every
requested combination of attributes.
This is done using a hash table with the attribute set as the key,
as it is expected that technically different but similar materials
may use the same set of attributes. In addition, in order to minimize
wasted memory, a sparse UBO pool is implemented, so that chunks that
don't contain any data don't have to be allocated.
The back-end Cycles code is already refactored and committed by Brecht.
Differential Revision: https://developer.blender.org/D2057
2020-08-05 19:14:40 +03:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_output_thickness(GPUMaterial *material, GPUNodeLink *link)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
if (!material->graph.outlink_thickness) {
|
|
|
|
|
material->graph.outlink_thickness = link;
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-04 08:13:54 +01:00
|
|
|
void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash)
|
|
|
|
|
{
|
2025-04-12 17:17:24 +02:00
|
|
|
GPUNodeGraphOutputLink *aov_link = MEM_callocN<GPUNodeGraphOutputLink>(__func__);
|
2020-12-04 08:13:54 +01:00
|
|
|
aov_link->outlink = link;
|
|
|
|
|
aov_link->hash = hash;
|
|
|
|
|
BLI_addtail(&material->graph.outlink_aovs, aov_link);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-29 08:37:57 +02:00
|
|
|
void GPU_material_add_output_link_composite(GPUMaterial *material, GPUNodeLink *link)
|
|
|
|
|
{
|
2025-04-12 17:17:24 +02:00
|
|
|
GPUNodeGraphOutputLink *compositor_link = MEM_callocN<GPUNodeGraphOutputLink>(__func__);
|
2022-07-29 08:37:57 +02:00
|
|
|
compositor_link->outlink = link;
|
|
|
|
|
BLI_addtail(&material->graph.outlink_compositor, compositor_link);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
char *GPU_material_split_sub_function(GPUMaterial *material,
|
|
|
|
|
eGPUType return_type,
|
|
|
|
|
GPUNodeLink **link)
|
|
|
|
|
{
|
|
|
|
|
/* Force cast to return type. */
|
|
|
|
|
switch (return_type) {
|
|
|
|
|
case GPU_FLOAT:
|
|
|
|
|
GPU_link(material, "set_value", *link, link);
|
|
|
|
|
break;
|
|
|
|
|
case GPU_VEC3:
|
|
|
|
|
GPU_link(material, "set_rgb", *link, link);
|
|
|
|
|
break;
|
|
|
|
|
case GPU_VEC4:
|
|
|
|
|
GPU_link(material, "set_rgba", *link, link);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BLI_assert(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-12 17:17:24 +02:00
|
|
|
GPUNodeGraphFunctionLink *func_link = MEM_callocN<GPUNodeGraphFunctionLink>(__func__);
|
2022-04-14 18:47:58 +02:00
|
|
|
func_link->outlink = *link;
|
|
|
|
|
SNPRINTF(func_link->name, "ntree_fn%d", material->generated_function_len++);
|
|
|
|
|
BLI_addtail(&material->graph.material_functions, func_link);
|
|
|
|
|
|
|
|
|
|
return func_link->name;
|
|
|
|
|
}
|