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/gpu/intern/gpu_material.c')
-rw-r--r--source/blender/gpu/intern/gpu_material.c556
1 files changed, 100 insertions, 456 deletions
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index f39cad20b9b..a08bef4472a 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -60,11 +60,14 @@
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
#include "gpu_codegen.h"
+#include "gpu_lamp_private.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_DerivedMesh.h"
@@ -92,12 +95,15 @@ static struct GPUWorld {
} GPUWorld;
struct GPUMaterial {
- Scene *scene;
+ Scene *scene; /* DEPRECATED was only usefull for lamps */
Material *ma;
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
- int type;
+ int type; /* DEPRECATED */
+
+ const void *engine_type; /* attached engine type */
+ int options; /* to identify shader variations (shadow, probe, world background...) */
/* for creating the material */
ListBase nodes;
@@ -128,50 +134,7 @@ struct GPUMaterial {
bool bound;
bool is_opensubdiv;
-};
-
-struct GPULamp {
- Scene *scene;
- Object *ob;
- Object *par;
- Lamp *la;
-
- int type, mode, lay, hide;
-
- float dynenergy, dyncol[3];
- float energy, col[3];
-
- float co[3], vec[3];
- float dynco[3], dynvec[3];
- float obmat[4][4];
- float imat[4][4];
- float dynimat[4][4];
-
- float spotsi, spotbl, k;
- float spotvec[2];
- float dyndist, dynatt1, dynatt2;
- float dist, att1, att2;
- float coeff_const, coeff_lin, coeff_quad;
- float shadow_color[3];
-
- float bias, d, clipend;
- int size;
-
- int falloff_type;
- struct CurveMapping *curfalloff;
-
- float winmat[4][4];
- float viewmat[4][4];
- float persmat[4][4];
- float dynpersmat[4][4];
-
- GPUFrameBuffer *fb;
- GPUFrameBuffer *blurfb;
- GPUTexture *tex;
- GPUTexture *depthtex;
- GPUTexture *blurtex;
-
- ListBase materials;
+ GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
};
/* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */
@@ -289,21 +252,10 @@ void GPU_material_free(ListBase *gpumaterial)
if (material->pass)
GPU_pass_free(material->pass);
- for (LinkData *nlink = material->lamps.first; nlink; nlink = nlink->next) {
- GPULamp *lamp = nlink->data;
-
- if (material->ma) {
- Material *ma = material->ma;
-
- LinkData *next = NULL;
- for (LinkData *mlink = lamp->materials.first; mlink; mlink = next) {
- next = mlink->next;
- if (mlink->data == ma)
- BLI_freelinkN(&lamp->materials, mlink);
- }
- }
+ if (material->ubo != NULL) {
+ GPU_uniformbuffer_free(material->ubo);
}
-
+
BLI_freelistN(&material->lamps);
MEM_freeN(material);
@@ -312,18 +264,6 @@ void GPU_material_free(ListBase *gpumaterial)
BLI_freelistN(gpumaterial);
}
-bool GPU_lamp_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
-{
- if (lamp->hide)
- return false;
- else if (srl && srl->light_override)
- return BKE_group_object_exists(srl->light_override, lamp->ob);
- else if (ma && ma->group)
- return BKE_group_object_exists(ma->group, lamp->ob);
- else
- return true;
-}
-
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock)
@@ -490,6 +430,34 @@ GPUMatType GPU_Material_get_type(GPUMaterial *material)
return material->type;
}
+GPUPass *GPU_material_get_pass(GPUMaterial *material)
+{
+ return material->pass;
+}
+
+GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material)
+{
+ return material->ubo;
+}
+
+/**
+ * Create dynamic UBO from parameters
+ * \param ListBase of BLI_genericNodeN(GPUInput)
+ */
+void GPU_material_create_uniform_buffer(GPUMaterial *material, ListBase *inputs)
+{
+ material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL);
+}
+
+void GPU_material_uniform_buffer_tag_dirty(ListBase *gpumaterials)
+{
+ for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *material = link->data;
+ if (material->ubo != NULL) {
+ GPU_uniformbuffer_tag_dirty(material->ubo);
+ }
+ }
+}
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
@@ -951,14 +919,12 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
}
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
return;
}
}
}
else if ((mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) {
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
return;
}
else
@@ -1025,7 +991,6 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
}
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
}
static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
@@ -2150,6 +2115,64 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
return mat;
}
+GPUMaterial *GPU_material_from_nodetree_find(
+ ListBase *gpumaterials, const void *engine_type, int options)
+{
+ for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial *)link->data;
+ if (current_material->engine_type == engine_type &&
+ current_material->options == options)
+ {
+ return current_material;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * TODO: This is supposed to replace GPU_material_from_blender/_world in the future
+ *
+ * \note Caller must use #GPU_material_from_nodetree_find to re-use existing materials,
+ * This is enforced since constructing other arguments to this function may be expensive
+ * so only do this when they are needed.
+ */
+GPUMaterial *GPU_material_from_nodetree(
+ Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+
+ /* Caller must re-use materials. */
+ BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
+
+ /* allocate material */
+ mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
+ mat->scene = scene;
+ mat->engine_type = engine_type;
+ mat->options = options;
+
+ ntreeGPUMaterialNodes(ntree, mat, NODE_NEWER_SHADING);
+
+ /* Let Draw manager finish the construction. */
+ if (mat->outlink) {
+ outlink = mat->outlink;
+ mat->pass = GPU_generate_pass_new(
+ mat, &mat->nodes, outlink, &mat->attribs, vert_code, geom_code, frag_lib, defines);
+ }
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(gpumaterials, link);
+
+ return mat;
+}
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
{
@@ -2237,386 +2260,6 @@ void GPU_materials_free(void)
/* Lamps and shadow buffers */
-static void gpu_lamp_calc_winmat(GPULamp *lamp)
-{
- float temp, angle, pixsize, wsize;
-
- if (lamp->type == LA_SUN) {
- wsize = lamp->la->shadow_frustum_size;
- orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
- }
- else if (lamp->type == LA_SPOT) {
- angle = saacos(lamp->spotsi);
- temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
- pixsize = lamp->d / temp;
- wsize = pixsize * 0.5f * lamp->size;
- /* compute shadows according to X and Y scaling factors */
- perspective_m4(
- lamp->winmat,
- -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
- -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
- lamp->d, lamp->clipend);
- }
-}
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
-{
- float mat[4][4];
- float obmat_scale[3];
-
- lamp->lay = lay;
- lamp->hide = hide;
-
- normalize_m4_m4_ex(mat, obmat, obmat_scale);
-
- copy_v3_v3(lamp->vec, mat[2]);
- copy_v3_v3(lamp->co, mat[3]);
- copy_m4_m4(lamp->obmat, mat);
- invert_m4_m4(lamp->imat, mat);
-
- if (lamp->type == LA_SPOT) {
- /* update spotlamp scale on X and Y axis */
- lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
- lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
- }
-
- if (GPU_lamp_has_shadow_buffer(lamp)) {
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
- }
-}
-
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
-{
- lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = r;
- lamp->col[1] = g;
- lamp->col[2] = b;
-}
-
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad)
-{
- lamp->dist = distance;
- lamp->att1 = att1;
- lamp->att2 = att2;
- lamp->coeff_const = coeff_const;
- lamp->coeff_lin = coeff_lin;
- lamp->coeff_quad = coeff_quad;
-}
-
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
-{
- lamp->spotsi = cosf(spotsize * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-}
-
-static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
-{
- lamp->scene = scene;
- lamp->ob = ob;
- lamp->par = par;
- lamp->la = la;
-
- /* add_render_lamp */
- lamp->mode = la->mode;
- lamp->type = la->type;
-
- lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = la->r;
- lamp->col[1] = la->g;
- lamp->col[2] = la->b;
-
- GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
-
- lamp->spotsi = la->spotsize;
- if (lamp->mode & LA_HALO)
- if (lamp->spotsi > DEG2RADF(170.0f))
- lamp->spotsi = DEG2RADF(170.0f);
- lamp->spotsi = cosf(lamp->spotsi * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
- lamp->k = la->k;
-
- lamp->dist = la->dist;
- lamp->falloff_type = la->falloff_type;
- lamp->att1 = la->att1;
- lamp->att2 = la->att2;
- lamp->coeff_const = la->coeff_const;
- lamp->coeff_lin = la->coeff_lin;
- lamp->coeff_quad = la->coeff_quad;
- lamp->curfalloff = la->curfalloff;
-
- /* initshadowbuf */
- lamp->bias = 0.02f * la->bias;
- lamp->size = la->bufsize;
- lamp->d = la->clipsta;
- lamp->clipend = la->clipend;
-
- /* arbitrary correction for the fact we do no soft transition */
- lamp->bias *= 0.25f;
-}
-
-static void gpu_lamp_shadow_free(GPULamp *lamp)
-{
- if (lamp->tex) {
- GPU_texture_free(lamp->tex);
- lamp->tex = NULL;
- }
- if (lamp->depthtex) {
- GPU_texture_free(lamp->depthtex);
- lamp->depthtex = NULL;
- }
- if (lamp->fb) {
- GPU_framebuffer_free(lamp->fb);
- lamp->fb = NULL;
- }
- if (lamp->blurtex) {
- GPU_texture_free(lamp->blurtex);
- lamp->blurtex = NULL;
- }
- if (lamp->blurfb) {
- GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb = NULL;
- }
-}
-
-GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
-{
- Lamp *la;
- GPULamp *lamp;
- LinkData *link;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = (GPULamp *)link->data;
-
- if (lamp->par == par && lamp->scene == scene)
- return link->data;
- }
-
- lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
-
- link = MEM_callocN(sizeof(LinkData), "GPULampLink");
- link->data = lamp;
- BLI_addtail(&ob->gpulamp, link);
-
- la = ob->data;
- gpu_lamp_from_blender(scene, ob, par, la, lamp);
-
- if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
- (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
- {
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
- lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
- lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
-
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
- }
- else {
- lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- }
-
- GPU_framebuffer_restore();
-
- lamp->shadow_color[0] = la->shdwr;
- lamp->shadow_color[1] = la->shdwg;
- lamp->shadow_color[2] = la->shdwb;
- }
- else {
- lamp->shadow_color[0] = 1.0;
- lamp->shadow_color[1] = 1.0;
- lamp->shadow_color[2] = 1.0;
- }
-
- return lamp;
-}
-
-void GPU_lamp_free(Object *ob)
-{
- GPULamp *lamp;
- LinkData *link;
- LinkData *nlink;
- Material *ma;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = link->data;
-
- while (lamp->materials.first) {
- nlink = lamp->materials.first;
- ma = nlink->data;
- BLI_freelinkN(&lamp->materials, nlink);
-
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
- }
-
- gpu_lamp_shadow_free(lamp);
-
- MEM_freeN(lamp);
- }
-
- BLI_freelistN(&ob->gpulamp);
-}
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
-{
- return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
- !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
- lamp->tex && lamp->fb);
-}
-
-void GPU_lamp_update_buffer_mats(GPULamp *lamp)
-{
- float rangemat[4][4], persmat[4][4];
-
- /* initshadowbuf */
- invert_m4_m4(lamp->viewmat, lamp->obmat);
- normalize_v3(lamp->viewmat[0]);
- normalize_v3(lamp->viewmat[1]);
- normalize_v3(lamp->viewmat[2]);
-
- /* makeshadowbuf */
- mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
-
- /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
- unit_m4(rangemat);
- rangemat[0][0] = 0.5f;
- rangemat[1][1] = 0.5f;
- rangemat[2][2] = 0.5f;
- rangemat[3][0] = 0.5f;
- rangemat[3][1] = 0.5f;
- rangemat[3][2] = 0.5f;
-
- mul_m4_m4m4(lamp->persmat, rangemat, persmat);
-}
-
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
-{
- GPU_lamp_update_buffer_mats(lamp);
-
- /* opengl */
- glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
- GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
-
- /* set matrices */
- copy_m4_m4(viewmat, lamp->viewmat);
- copy_m4_m4(winmat, lamp->winmat);
- *winsize = lamp->size;
-}
-
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
-{
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
- }
-
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
- GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
-}
-
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
-{
- return lamp->la->shadowmap_type;
-}
-
-int GPU_lamp_shadow_bind_code(GPULamp *lamp)
-{
- return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
-}
-
-float *GPU_lamp_dynpersmat(GPULamp *lamp)
-{
- return &lamp->dynpersmat[0][0];
-}
-
-int GPU_lamp_shadow_layer(GPULamp *lamp)
-{
- if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
- return lamp->lay;
- else
- return -1;
-}
-
GPUNodeLink *GPU_lamp_get_data(
GPUMaterial *mat, GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy)
@@ -2658,7 +2301,6 @@ GPUNodeLink *GPU_lamp_get_data(
/* ensure shadow buffer and lamp textures will be updated */
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, mat->ma);
return visifac;
}
@@ -2735,6 +2377,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
case GPU_VEC4:
case GPU_MAT3:
case GPU_MAT4:
+ case GPU_CLOSURE:
case GPU_ATTRIB:
break;
}
@@ -2763,6 +2406,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
break;
case GPU_NONE:
+ case GPU_CLOSURE:
case GPU_TEX2D:
case GPU_TEXCUBE:
case GPU_SHADOW2D: