Eevee: Add Cascaded Shadow Map options.
This commit is contained in:
parent
cc6e97d426
commit
adeaf37e77
|
@ -386,6 +386,13 @@ class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
|
|||
col.prop(lamp, "shadow_buffer_exp", text="Exponent")
|
||||
col.prop(lamp, "shadow_buffer_bleed_bias", text="Bleed Bias")
|
||||
|
||||
col = layout.column()
|
||||
col.label("Cascaded Shadow Map:")
|
||||
col.prop(lamp, "shadow_cascade_max_distance", text="Max Distance")
|
||||
col.prop(lamp, "shadow_cascade_count", text="Count")
|
||||
col.prop(lamp, "shadow_cascade_exponent", text="Distribution")
|
||||
col.prop(lamp, "shadow_cascade_fade", text="Fade")
|
||||
|
||||
|
||||
class DATA_PT_area(DataButtonsPanel, Panel):
|
||||
bl_label = "Area Shape"
|
||||
|
|
|
@ -102,6 +102,10 @@ void BKE_lamp_init(Lamp *la)
|
|||
la->sky_colorspace = BLI_XYZ_CIE;
|
||||
la->sky_exposure = 1.0f;
|
||||
la->shadow_frustum_size = 10.0f;
|
||||
la->cascade_max_dist = 1000.0f;
|
||||
la->cascade_count = 4;
|
||||
la->cascade_exponent = 0.8f;
|
||||
la->cascade_fade = 0.1f;
|
||||
|
||||
curvemapping_initialize(la->curfalloff);
|
||||
}
|
||||
|
|
|
@ -432,6 +432,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "cascade_max_dist")) {
|
||||
for (Lamp *la = main->lamp.first; la; la = la->id.next) {
|
||||
la->cascade_max_dist = 1000.0f;
|
||||
la->cascade_count = 4;
|
||||
la->cascade_exponent = 0.8f;
|
||||
la->cascade_fade = 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
typedef enum eNTreeDoVersionErrors {
|
||||
NTREE_DOVERSION_NO_ERROR = 0,
|
||||
|
|
|
@ -493,10 +493,12 @@ static void frustum_min_bounding_sphere(const float corners[8][4], float r_cente
|
|||
|
||||
static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
||||
{
|
||||
Lamp *la = (Lamp *)ob->data;
|
||||
|
||||
/* Camera Matrices */
|
||||
float persmat[4][4], persinv[4][4];
|
||||
float viewprojmat[4][4], projinv[4][4];
|
||||
float near, far;
|
||||
float view_near, view_far;
|
||||
float near_v[4] = {0.0f, 0.0f, -1.0f, 1.0f};
|
||||
float far_v[4] = {0.0f, 0.0f, 1.0f, 1.0f};
|
||||
bool is_persp = DRW_viewport_is_persp_get();
|
||||
|
@ -507,75 +509,134 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
|
|||
invert_m4_m4(projinv, viewprojmat);
|
||||
mul_m4_v4(projinv, near_v);
|
||||
mul_m4_v4(projinv, far_v);
|
||||
near = near_v[2];
|
||||
far = far_v[2]; /* TODO: Should be a shadow parameter */
|
||||
view_near = near_v[2];
|
||||
view_far = far_v[2]; /* TODO: Should be a shadow parameter */
|
||||
if (is_persp) {
|
||||
near /= near_v[3];
|
||||
far /= far_v[3];
|
||||
view_near /= near_v[3];
|
||||
view_far /= far_v[3];
|
||||
}
|
||||
|
||||
/* Lamps Matrices */
|
||||
float viewmat[4][4], projmat[4][4];
|
||||
int sh_nbr = 1; /* TODO : MSM */
|
||||
int cascade_nbr = MAX_CASCADE_NUM; /* TODO : Custom cascade number */
|
||||
int cascade_nbr = la->cascade_count;
|
||||
|
||||
EEVEE_ShadowCascadeData *sh_data = (EEVEE_ShadowCascadeData *)led->storage;
|
||||
EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
|
||||
EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
|
||||
EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
|
||||
Lamp *la = (Lamp *)ob->data;
|
||||
|
||||
/* The technique consists into splitting
|
||||
* the view frustum into several sub-frustum
|
||||
* that are individually receiving one shadow map */
|
||||
|
||||
float csm_start, csm_end;
|
||||
|
||||
if (is_persp) {
|
||||
csm_start = view_near;
|
||||
csm_end = max_ff(view_far, -la->cascade_max_dist);
|
||||
/* Avoid artifacts */
|
||||
csm_end = min_ff(view_near, csm_end);
|
||||
}
|
||||
else {
|
||||
csm_start = -view_far;
|
||||
csm_end = view_far;
|
||||
}
|
||||
|
||||
/* init near/far */
|
||||
for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
|
||||
cascade_data->split[c] = far;
|
||||
cascade_data->split_start[c] = csm_end;
|
||||
cascade_data->split_end[c] = csm_end;
|
||||
}
|
||||
|
||||
/* Compute split planes */
|
||||
float splits_ndc[MAX_CASCADE_NUM + 1];
|
||||
splits_ndc[0] = -1.0f;
|
||||
splits_ndc[cascade_nbr] = 1.0f;
|
||||
for (int c = 1; c < cascade_nbr; ++c) {
|
||||
const float lambda = 0.8f; /* TODO : Parameter */
|
||||
float splits_start_ndc[MAX_CASCADE_NUM];
|
||||
float splits_end_ndc[MAX_CASCADE_NUM];
|
||||
|
||||
/* View Space */
|
||||
float linear_split = LERP(((float)(c) / (float)cascade_nbr), near, far);
|
||||
float exp_split = near * powf(far / near, (float)(c) / (float)cascade_nbr);
|
||||
|
||||
if (is_persp) {
|
||||
cascade_data->split[c-1] = LERP(lambda, linear_split, exp_split);
|
||||
}
|
||||
else {
|
||||
cascade_data->split[c-1] = linear_split;
|
||||
}
|
||||
|
||||
/* NDC Space */
|
||||
float p[4] = {1.0f, 1.0f, cascade_data->split[c-1], 1.0f};
|
||||
{
|
||||
/* Nearest plane */
|
||||
float p[4] = {1.0f, 1.0f, csm_start, 1.0f};
|
||||
/* TODO: we don't need full m4 multiply here */
|
||||
mul_m4_v4(viewprojmat, p);
|
||||
splits_ndc[c] = p[2];
|
||||
|
||||
splits_start_ndc[0] = p[2];
|
||||
if (is_persp) {
|
||||
splits_ndc[c] /= p[3];
|
||||
splits_start_ndc[0] /= p[3];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* Farthest plane */
|
||||
float p[4] = {1.0f, 1.0f, csm_end, 1.0f};
|
||||
/* TODO: we don't need full m4 multiply here */
|
||||
mul_m4_v4(viewprojmat, p);
|
||||
splits_end_ndc[cascade_nbr - 1] = p[2];
|
||||
if (is_persp) {
|
||||
splits_end_ndc[cascade_nbr - 1] /= p[3];
|
||||
}
|
||||
}
|
||||
|
||||
cascade_data->split_start[0] = csm_start;
|
||||
cascade_data->split_end[cascade_nbr - 1] = csm_end;
|
||||
|
||||
for (int c = 1; c < cascade_nbr; ++c) {
|
||||
/* View Space */
|
||||
float linear_split = LERP(((float)(c) / (float)cascade_nbr), csm_start, csm_end);
|
||||
float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr);
|
||||
|
||||
if (is_persp) {
|
||||
cascade_data->split_start[c] = LERP(la->cascade_exponent, linear_split, exp_split);
|
||||
}
|
||||
else {
|
||||
cascade_data->split_start[c] = linear_split;
|
||||
}
|
||||
cascade_data->split_end[c-1] = cascade_data->split_start[c];
|
||||
|
||||
/* Add some overlap for smooth transition */
|
||||
cascade_data->split_start[c] = LERP(la->cascade_fade, cascade_data->split_end[c-1],
|
||||
(c > 1) ? cascade_data->split_end[c-2] : cascade_data->split_start[0]);
|
||||
|
||||
/* NDC Space */
|
||||
{
|
||||
float p[4] = {1.0f, 1.0f, cascade_data->split_start[c], 1.0f};
|
||||
/* TODO: we don't need full m4 multiply here */
|
||||
mul_m4_v4(viewprojmat, p);
|
||||
splits_start_ndc[c] = p[2];
|
||||
|
||||
if (is_persp) {
|
||||
splits_start_ndc[c] /= p[3];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float p[4] = {1.0f, 1.0f, cascade_data->split_end[c-1], 1.0f};
|
||||
/* TODO: we don't need full m4 multiply here */
|
||||
mul_m4_v4(viewprojmat, p);
|
||||
splits_end_ndc[c-1] = p[2];
|
||||
|
||||
if (is_persp) {
|
||||
splits_end_ndc[c-1] /= p[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set last cascade split fade distance into the first split_start. */
|
||||
float prev_split = (cascade_nbr > 1) ? cascade_data->split_end[cascade_nbr-2] : cascade_data->split_start[0];
|
||||
cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr-1], prev_split);
|
||||
|
||||
/* For each cascade */
|
||||
for (int c = 0; c < cascade_nbr; ++c) {
|
||||
/* Given 8 frustum corners */
|
||||
float corners[8][4] = {
|
||||
/* Near Cap */
|
||||
{-1.0f, -1.0f, splits_ndc[c], 1.0f},
|
||||
{ 1.0f, -1.0f, splits_ndc[c], 1.0f},
|
||||
{-1.0f, 1.0f, splits_ndc[c], 1.0f},
|
||||
{ 1.0f, 1.0f, splits_ndc[c], 1.0f},
|
||||
{-1.0f, -1.0f, splits_start_ndc[c], 1.0f},
|
||||
{ 1.0f, -1.0f, splits_start_ndc[c], 1.0f},
|
||||
{-1.0f, 1.0f, splits_start_ndc[c], 1.0f},
|
||||
{ 1.0f, 1.0f, splits_start_ndc[c], 1.0f},
|
||||
/* Far Cap */
|
||||
{-1.0f, -1.0f, splits_ndc[c+1], 1.0f},
|
||||
{ 1.0f, -1.0f, splits_ndc[c+1], 1.0f},
|
||||
{-1.0f, 1.0f, splits_ndc[c+1], 1.0f},
|
||||
{ 1.0f, 1.0f, splits_ndc[c+1], 1.0f}
|
||||
{-1.0f, -1.0f, splits_end_ndc[c], 1.0f},
|
||||
{ 1.0f, -1.0f, splits_end_ndc[c], 1.0f},
|
||||
{-1.0f, 1.0f, splits_end_ndc[c], 1.0f},
|
||||
{ 1.0f, 1.0f, splits_end_ndc[c], 1.0f}
|
||||
};
|
||||
|
||||
/* Transform them into world space */
|
||||
|
@ -585,6 +646,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
|
|||
corners[i][3] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
/* Project them into light space */
|
||||
invert_m4_m4(viewmat, ob->obmat);
|
||||
normalize_v3(viewmat[0]);
|
||||
|
@ -837,7 +899,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct;
|
||||
srd->clip_near = la->clipsta;
|
||||
srd->clip_far = la->clipend;
|
||||
for (int j = 0; j < MAX_CASCADE_NUM; ++j) {
|
||||
for (int j = 0; j < la->cascade_count; ++j) {
|
||||
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
||||
}
|
||||
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
|
||||
|
@ -849,7 +911,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
DRW_draw_pass(psl->shadow_cascade_pass);
|
||||
|
||||
for (linfo->current_shadow_cascade = 0;
|
||||
linfo->current_shadow_cascade < MAX_CASCADE_NUM;
|
||||
linfo->current_shadow_cascade < la->cascade_count;
|
||||
++linfo->current_shadow_cascade)
|
||||
{
|
||||
linfo->filter_size = la->soft * 0.0005f / (evscd->radius[linfo->current_shadow_cascade] * 0.05f);
|
||||
|
|
|
@ -223,7 +223,8 @@ typedef struct EEVEE_ShadowCube {
|
|||
|
||||
typedef struct EEVEE_ShadowCascade {
|
||||
float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
|
||||
float split[4];
|
||||
float split_start[4];
|
||||
float split_end[4];
|
||||
} EEVEE_ShadowCascade;
|
||||
|
||||
typedef struct EEVEE_ShadowRender {
|
||||
|
|
|
@ -89,7 +89,8 @@ struct ShadowCubeData {
|
|||
|
||||
struct ShadowCascadeData {
|
||||
mat4 shadowmat[MAX_CASCADE_NUM];
|
||||
vec4 split_distances;
|
||||
vec4 split_start_distances;
|
||||
vec4 split_end_distances;
|
||||
};
|
||||
|
||||
/* convenience aliases */
|
||||
|
|
|
@ -78,37 +78,15 @@ float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
|
|||
#endif
|
||||
}
|
||||
|
||||
float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
|
||||
float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid)
|
||||
{
|
||||
/* Finding Cascade index */
|
||||
vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
|
||||
vec4 comp = step(view_z, scd.split_distances);
|
||||
float cascade = dot(comp, comp);
|
||||
mat4 shadowmat;
|
||||
|
||||
/* Manual Unrolling of a loop for better performance.
|
||||
* Doing fetch directly with cascade index leads to
|
||||
* major performance impact. (0.27ms -> 10.0ms for 1 light) */
|
||||
if (cascade == 0.0) {
|
||||
shadowmat = scd.shadowmat[0];
|
||||
}
|
||||
else if (cascade == 1.0) {
|
||||
shadowmat = scd.shadowmat[1];
|
||||
}
|
||||
else if (cascade == 2.0) {
|
||||
shadowmat = scd.shadowmat[2];
|
||||
}
|
||||
else {
|
||||
shadowmat = scd.shadowmat[3];
|
||||
}
|
||||
|
||||
vec4 shpos = shadowmat * vec4(W, 1.0);
|
||||
float dist = shpos.z * abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
|
||||
float dist = shpos.z * range;
|
||||
|
||||
#if defined(SHADOW_VSM)
|
||||
vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid + cascade)).rg;
|
||||
vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid)).rg;
|
||||
#else
|
||||
float z = texture(shadowTexture, vec3(shpos.xy, texid + cascade)).r;
|
||||
float z = texture(shadowTexture, vec3(shpos.xy, texid)).r;
|
||||
#endif
|
||||
|
||||
#if defined(SHADOW_VSM)
|
||||
|
@ -120,6 +98,38 @@ float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
|
|||
#endif
|
||||
}
|
||||
|
||||
float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
|
||||
{
|
||||
vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
|
||||
vec4 weights = smoothstep(scd.split_end_distances, scd.split_start_distances.yzwx, view_z);
|
||||
weights.yzw -= weights.xyz;
|
||||
|
||||
vec4 vis = vec4(1.0);
|
||||
float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
|
||||
if (weights.x > 0.0) {
|
||||
vis.x = evaluate_cascade(sd, scd.shadowmat[0], W, range, texid + 0);
|
||||
}
|
||||
if (weights.y > 0.0) {
|
||||
vis.y = evaluate_cascade(sd, scd.shadowmat[1], W, range, texid + 1);
|
||||
}
|
||||
if (weights.z > 0.0) {
|
||||
vis.z = evaluate_cascade(sd, scd.shadowmat[2], W, range, texid + 2);
|
||||
}
|
||||
if (weights.w > 0.0) {
|
||||
vis.w = evaluate_cascade(sd, scd.shadowmat[3], W, range, texid + 3);
|
||||
}
|
||||
|
||||
float weight_sum = dot(vec4(1.0), weights);
|
||||
if (weight_sum > 0.9999) {
|
||||
float vis_sum = dot(vec4(1.0), vis * weights);
|
||||
return vis_sum / weight_sum;
|
||||
}
|
||||
else {
|
||||
float vis_sum = dot(vec4(1.0), vis * step(0.001, weights));
|
||||
return mix(1.0, vis_sum, weight_sum);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* --------------------- Light Functions --------------------- */
|
||||
/* ----------------------------------------------------------- */
|
||||
|
|
|
@ -57,6 +57,10 @@ float linear_depth(float z)
|
|||
float get_cascade_world_distance(vec2 uvs)
|
||||
{
|
||||
float zdepth = texture(shadowTexture, vec3(uvs, float(cascadeId))).r;
|
||||
if (zdepth == 1.0) {
|
||||
/* Background case */
|
||||
return 1e16;
|
||||
}
|
||||
return zdepth * abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -106,6 +106,12 @@ typedef struct Lamp {
|
|||
short pr_texture, use_nodes;
|
||||
char pad6[4];
|
||||
|
||||
/* Eevee */
|
||||
float cascade_max_dist;
|
||||
float cascade_exponent;
|
||||
float cascade_fade;
|
||||
int cascade_count;
|
||||
|
||||
/* preview */
|
||||
struct PreviewImage *preview;
|
||||
|
||||
|
|
|
@ -476,7 +476,7 @@ static void rna_def_lamp_falloff(StructRNA *srna)
|
|||
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
|
||||
}
|
||||
|
||||
static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
|
||||
static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area, int sun)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
|
@ -698,6 +698,32 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
|
|||
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_LAYER_SHADOW);
|
||||
RNA_def_property_ui_text(prop, "Shadow Layer", "Objects on the same layers only cast shadows");
|
||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||
|
||||
if (sun) {
|
||||
prop = RNA_def_property(srna, "shadow_cascade_max_distance", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "cascade_max_dist");
|
||||
RNA_def_property_range(prop, 0.0f, 9999.0f);
|
||||
RNA_def_property_ui_text(prop, "Cascade Max Distance", "End distance of the cascaded shadow map (only in perspective view)");
|
||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shadow_cascade_count", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "cascade_count");
|
||||
RNA_def_property_range(prop, 1, 4);
|
||||
RNA_def_property_ui_text(prop, "Cascade Count", "Number of texture used by the cascaded shadow map");
|
||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shadow_cascade_exponent", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "cascade_exponent");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Exponential Distribution", "Higher value increase resolution towards the viewpoint");
|
||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shadow_cascade_fade", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "cascade_fade");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Cascade Fade", "How smooth is the transition between each cascade");
|
||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_def_point_lamp(BlenderRNA *brna)
|
||||
|
@ -710,7 +736,7 @@ static void rna_def_point_lamp(BlenderRNA *brna)
|
|||
RNA_def_struct_ui_icon(srna, ICON_LAMP_POINT);
|
||||
|
||||
rna_def_lamp_falloff(srna);
|
||||
rna_def_lamp_shadow(srna, 0, 0);
|
||||
rna_def_lamp_shadow(srna, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void rna_def_area_lamp(BlenderRNA *brna)
|
||||
|
@ -729,7 +755,7 @@ static void rna_def_area_lamp(BlenderRNA *brna)
|
|||
RNA_def_struct_ui_text(srna, "Area Lamp", "Directional area lamp");
|
||||
RNA_def_struct_ui_icon(srna, ICON_LAMP_AREA);
|
||||
|
||||
rna_def_lamp_shadow(srna, 0, 1);
|
||||
rna_def_lamp_shadow(srna, 0, 1, 0);
|
||||
rna_def_lamp_falloff(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "use_umbra", PROP_BOOLEAN, PROP_NONE);
|
||||
|
@ -786,7 +812,7 @@ static void rna_def_spot_lamp(BlenderRNA *brna)
|
|||
RNA_def_struct_ui_icon(srna, ICON_LAMP_SPOT);
|
||||
|
||||
rna_def_lamp_falloff(srna);
|
||||
rna_def_lamp_shadow(srna, 1, 0);
|
||||
rna_def_lamp_shadow(srna, 1, 0, 0);
|
||||
|
||||
prop = RNA_def_property(srna, "use_square", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SQUARE);
|
||||
|
@ -839,7 +865,7 @@ static void rna_def_sun_lamp(BlenderRNA *brna)
|
|||
RNA_def_struct_ui_text(srna, "Sun Lamp", "Constant direction parallel ray lamp");
|
||||
RNA_def_struct_ui_icon(srna, ICON_LAMP_SUN);
|
||||
|
||||
rna_def_lamp_shadow(srna, 0, 0);
|
||||
rna_def_lamp_shadow(srna, 0, 0, 1);
|
||||
|
||||
/* sky */
|
||||
prop = RNA_def_property(srna, "sky", PROP_POINTER, PROP_NONE);
|
||||
|
|
Loading…
Reference in New Issue