Skip to content

Commit

Permalink
UPBGE: Implement dynamic object ligthing layer. (#734)
Browse files Browse the repository at this point in the history
Previously the ligthing of the objects based on a layer was fixed
at the conversion time by the construction of BL_BlenderShader
with the member m_lightLayer. Also because of the blender
material managment the object layer was used only when binding
the material and not when binding object dependent uniforms.

The situation is changed firstly because the usage of one
layer for all the object using the same material is totally wrong.
Secondly the layers were not dynamic per object.

To solve this situation the fastest way is to expose a layer into
the shader, the function lamp_visible is designed for. It receives
the lamp layer, object layer, lamp color and lamp energy and
updates out color and energy if the lamp layer mask the object
layer, to avoid branching the test computes a value of 0 or 1
and multiply the color and energy by it.

The object layer is defined as a material builtin uniform and
each GPULamp holds a dynlayer used as a dynamic uniform.
At each call to GPU_material_bind_uniforms the object layer
is updated. Concerning the lamps the dynlayer value is updated
in a preparing stage before rendering any material, this stage
intents to update the textures and the lamps. The main caller
is RAS_BucketManager::PrepareBuckets calling for each material
the Prepare function redirected to BL_BlenderShader::UpdateLights.
This last function is calling GPU_material_update_lamps which
over all lamps update the "dyn" value for color and matrices.

Inside GPU_material_bind the lamp layer is computed. As it is
not the only way to decide of the visibility of a lamp, if the
lamp is hidden or the layer is set to 0, else if the lamp is not
using a "layer only" option then all layers are enabled, else if
the layer is not in the scene layer the layer is set to 0
else to the actual lamp object layer.

As GPU_material_bind_uniforms now use the object layer,
RAS_MeshUser store the layer of the object to allow BL_BlenderShader
to get this value and send it to the GPU_ function.
In the same time the calls to SetFrontFace are reduced to
only updating when the object node transform changed.

No performance win neither loss were noticed.
  • Loading branch information
panzergame authored Aug 2, 2018
1 parent ce3a765 commit c024480
Show file tree
Hide file tree
Showing 22 changed files with 233 additions and 105 deletions.
2 changes: 1 addition & 1 deletion source/blender/editors/space_view3d/view3d_draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3107,7 +3107,7 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
GPUMaterial *gpumat = GPU_material_world(scene, scene->world);

/* calculate full shader for background */
GPU_material_bind(gpumat, 1, 1, 1.0, true, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
GPU_material_bind(gpumat, 1, 1.0, true, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));

bool material_not_bound = !GPU_material_bound(gpumat);

Expand Down
29 changes: 17 additions & 12 deletions source/blender/gpu/GPU_material.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ typedef enum GPUType {
GPU_MAT3 = 9,
GPU_MAT4 = 16,

GPU_INT = 17,

GPU_TEX2D = 1002,
GPU_SHADOW2D = 1003,
GPU_TEXCUBE = 1004,
Expand Down Expand Up @@ -105,7 +107,8 @@ typedef enum GPUBuiltin {
GPU_INSTANCING_MATRIX_ATTRIB = (1 << 19),
GPU_INSTANCING_POSITION_ATTRIB = (1 << 20),
GPU_TIME = (1 << 21),
GPU_OBJECT_INFO = (1 << 22)
GPU_OBJECT_INFO = (1 << 22),
GPU_OBJECT_LAY = (1 << 23)
} GPUBuiltin;

typedef enum GPUOpenGLBuiltin {
Expand Down Expand Up @@ -172,14 +175,15 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_LAMP_DYNENERGY = 5 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_DYNCOL = 6 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_DYNSPOTSCALE = 7 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_DISTANCE = 8 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_ATT1 = 9 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_ATT2 = 10 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTSIZE = 11 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTBLEND = 12 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_COEFFCONST = 13 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_COEFFLIN = 14 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_COEFFQUAD = 15 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_DYNVISI = 8 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_DISTANCE = 9 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_ATT1 = 10 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_ATT2 = 11 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTSIZE = 12 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTBLEND = 13 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_COEFFCONST = 14 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_COEFFLIN = 15 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_COEFFQUAD = 16 | GPU_DYNAMIC_GROUP_LAMP,

GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER,
GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER,
Expand Down Expand Up @@ -234,7 +238,7 @@ typedef enum GPUDynamicType {

GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_uniform(float *num);
GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_dynamic_uniform(void *num, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_select_uniform(float *num, GPUDynamicType dynamictype, void *data, struct Material *material);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data);
Expand Down Expand Up @@ -264,12 +268,13 @@ void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);

bool GPU_lamp_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
void GPU_material_update_lamps(GPUMaterial *material, float viewmat[4][4], float viewinv[4][4]);
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
GPUMaterial *material, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
void GPU_material_bind_uniforms(
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], const float obcol[4],
float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
int oblay, float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
void GPU_material_unbind(GPUMaterial *material);
bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
Expand Down
19 changes: 13 additions & 6 deletions source/blender/gpu/intern/gpu_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ typedef struct GPUFunction {
} GPUFunction;

/* Indices match the GPUType enum */
static const char *GPU_DATATYPE_STR[17] = {
static const char *GPU_DATATYPE_STR[18] = {
"", "float", "vec2", "vec3", "vec4",
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4",
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4", "int"
};

/* GLSL code parsing for finding function definitions.
Expand Down Expand Up @@ -172,7 +172,7 @@ static void gpu_parse_functions_string(GHash *hash, char *code)

/* test for type */
type = GPU_NONE;
for (i = 1; i <= 16; i++) {
for (i = 1; i <= 17; i++) {
if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
type = i;
break;
Expand Down Expand Up @@ -426,6 +426,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unftime";
else if (builtin == GPU_OBJECT_INFO)
return "unfobjectinfo";
else if (builtin == GPU_OBJECT_LAY)
return "unfobjectlay";
else
return "";
}
Expand Down Expand Up @@ -1085,8 +1087,13 @@ void GPU_pass_update_uniforms(GPUPass *pass)
/* pass dynamic inputs to opengl, others were removed */
for (input = inputs->first; input; input = input->next) {
if (!(input->ima || input->tex || input->prv || input->texptr)) {
GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
input->dynamicvec);
if (input->type == GPU_INT) {
GPU_shader_uniform_vector_int(shader, input->shaderloc, 1, 1, (int *)input->dynamicvec);
}
else {
GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
input->dynamicvec);
}
}
}
}
Expand Down Expand Up @@ -1441,7 +1448,7 @@ GPUNodeLink *GPU_uniform(float *num)
return link;
}

GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
GPUNodeLink *GPU_dynamic_uniform(void *num, GPUDynamicType dynamictype, void *data)
{
GPUNodeLink *link = GPU_node_link_create();

Expand Down
5 changes: 3 additions & 2 deletions source/blender/gpu/intern/gpu_draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1869,12 +1869,13 @@ int GPU_object_material_bind(int nr, void *attribs)
GPU_get_object_info(object_info, mat);
}

GPU_material_update_lamps(gpumat, GMS.gviewmat, GMS.gviewinv);
GPU_material_bind(
gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
gpumat, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);

auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info);
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, GMS.gob->lay, auto_bump_scale, &partile_info, object_info);
GMS.gboundmat = mat;

/* for glsl use alpha blend mode, unless it's set to solid and
Expand Down
Loading

0 comments on commit c024480

Please sign in to comment.