Merge pull request #50184 from JFonS/cpu_lightmapper_soft_shadows
[3.x] Add soft shadows to the CPU lightmapper
This commit is contained in:
commit
aa3a5c9f6a
12 changed files with 187 additions and 119 deletions
|
@ -54,6 +54,9 @@
|
|||
<member name="light_negative" type="bool" setter="set_negative" getter="is_negative" default="false">
|
||||
If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows.
|
||||
</member>
|
||||
<member name="light_size" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
The size of the light in Godot units. Only considered in baked lightmaps and only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing this value will make the shadows appear blurrier. This can be used to simulate area lights to an extent.
|
||||
</member>
|
||||
<member name="light_specular" type="float" setter="set_param" getter="get_param" default="0.5">
|
||||
The intensity of the specular blob in objects affected by the light. At [code]0[/code], the light becomes a pure diffuse light. When not baking emission, this can be used to avoid unrealistic reflections when placing lights above an emissive surface.
|
||||
</member>
|
||||
|
@ -80,46 +83,49 @@
|
|||
<constant name="PARAM_INDIRECT_ENERGY" value="1" enum="Param">
|
||||
Constant for accessing [member light_indirect_energy].
|
||||
</constant>
|
||||
<constant name="PARAM_SPECULAR" value="2" enum="Param">
|
||||
<constant name="PARAM_SIZE" value="2" enum="Param">
|
||||
Constant for accessing [member light_size].
|
||||
</constant>
|
||||
<constant name="PARAM_SPECULAR" value="3" enum="Param">
|
||||
Constant for accessing [member light_specular].
|
||||
</constant>
|
||||
<constant name="PARAM_RANGE" value="3" enum="Param">
|
||||
<constant name="PARAM_RANGE" value="4" enum="Param">
|
||||
Constant for accessing [member OmniLight.omni_range] or [member SpotLight.spot_range].
|
||||
</constant>
|
||||
<constant name="PARAM_ATTENUATION" value="4" enum="Param">
|
||||
<constant name="PARAM_ATTENUATION" value="5" enum="Param">
|
||||
Constant for accessing [member OmniLight.omni_attenuation] or [member SpotLight.spot_attenuation].
|
||||
</constant>
|
||||
<constant name="PARAM_SPOT_ANGLE" value="5" enum="Param">
|
||||
<constant name="PARAM_SPOT_ANGLE" value="6" enum="Param">
|
||||
Constant for accessing [member SpotLight.spot_angle].
|
||||
</constant>
|
||||
<constant name="PARAM_SPOT_ATTENUATION" value="6" enum="Param">
|
||||
<constant name="PARAM_SPOT_ATTENUATION" value="7" enum="Param">
|
||||
Constant for accessing [member SpotLight.spot_angle_attenuation].
|
||||
</constant>
|
||||
<constant name="PARAM_CONTACT_SHADOW_SIZE" value="7" enum="Param">
|
||||
<constant name="PARAM_CONTACT_SHADOW_SIZE" value="8" enum="Param">
|
||||
Constant for accessing [member shadow_contact].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_MAX_DISTANCE" value="8" enum="Param">
|
||||
<constant name="PARAM_SHADOW_MAX_DISTANCE" value="9" enum="Param">
|
||||
Constant for accessing [member DirectionalLight.directional_shadow_max_distance].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_SPLIT_1_OFFSET" value="9" enum="Param">
|
||||
<constant name="PARAM_SHADOW_SPLIT_1_OFFSET" value="10" enum="Param">
|
||||
Constant for accessing [member DirectionalLight.directional_shadow_split_1].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_SPLIT_2_OFFSET" value="10" enum="Param">
|
||||
<constant name="PARAM_SHADOW_SPLIT_2_OFFSET" value="11" enum="Param">
|
||||
Constant for accessing [member DirectionalLight.directional_shadow_split_2].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_SPLIT_3_OFFSET" value="11" enum="Param">
|
||||
<constant name="PARAM_SHADOW_SPLIT_3_OFFSET" value="12" enum="Param">
|
||||
Constant for accessing [member DirectionalLight.directional_shadow_split_3].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_NORMAL_BIAS" value="12" enum="Param">
|
||||
<constant name="PARAM_SHADOW_NORMAL_BIAS" value="13" enum="Param">
|
||||
Constant for accessing [member DirectionalLight.directional_shadow_normal_bias].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_BIAS" value="13" enum="Param">
|
||||
<constant name="PARAM_SHADOW_BIAS" value="14" enum="Param">
|
||||
Constant for accessing [member shadow_bias].
|
||||
</constant>
|
||||
<constant name="PARAM_SHADOW_BIAS_SPLIT_SCALE" value="14" enum="Param">
|
||||
<constant name="PARAM_SHADOW_BIAS_SPLIT_SCALE" value="15" enum="Param">
|
||||
Constant for accessing [member DirectionalLight.directional_shadow_bias_split_scale].
|
||||
</constant>
|
||||
<constant name="PARAM_MAX" value="15" enum="Param">
|
||||
<constant name="PARAM_MAX" value="16" enum="Param">
|
||||
Represents the size of the [enum Param] enum.
|
||||
</constant>
|
||||
<constant name="BAKE_DISABLED" value="0" enum="BakeMode">
|
||||
|
|
|
@ -4534,46 +4534,52 @@
|
|||
<constant name="LIGHT_PARAM_ENERGY" value="0" enum="LightParam">
|
||||
The light's energy.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_INDIRECT_ENERGY" value="1" enum="LightParam">
|
||||
Secondary multiplier used with indirect light (light bounces).
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SIZE" value="2" enum="LightParam">
|
||||
The light's size, currently only used for soft shadows in baked lightmaps.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SPECULAR" value="3" enum="LightParam">
|
||||
The light's influence on specularity.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_RANGE" value="3" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_RANGE" value="4" enum="LightParam">
|
||||
The light's range.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_ATTENUATION" value="4" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_ATTENUATION" value="5" enum="LightParam">
|
||||
The light's attenuation.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SPOT_ANGLE" value="5" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SPOT_ANGLE" value="6" enum="LightParam">
|
||||
The spotlight's angle.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="6" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="7" enum="LightParam">
|
||||
The spotlight's attenuation.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_CONTACT_SHADOW_SIZE" value="7" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_CONTACT_SHADOW_SIZE" value="8" enum="LightParam">
|
||||
Scales the shadow color.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="8" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="9" enum="LightParam">
|
||||
Max distance that shadows will be rendered.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET" value="9" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET" value="10" enum="LightParam">
|
||||
Proportion of shadow atlas occupied by the first split.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET" value="10" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET" value="11" enum="LightParam">
|
||||
Proportion of shadow atlas occupied by the second split.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET" value="11" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET" value="12" enum="LightParam">
|
||||
Proportion of shadow atlas occupied by the third split. The fourth split occupies the rest.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_NORMAL_BIAS" value="12" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_NORMAL_BIAS" value="13" enum="LightParam">
|
||||
Normal bias used to offset shadow lookup by object normal. Can be used to fix self-shadowing artifacts.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_BIAS" value="13" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_BIAS" value="14" enum="LightParam">
|
||||
Bias the shadow lookup to fix self-shadowing artifacts.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE" value="14" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE" value="15" enum="LightParam">
|
||||
Increases bias on further splits to fix self-shadowing that only occurs far away from the camera.
|
||||
</constant>
|
||||
<constant name="LIGHT_PARAM_MAX" value="15" enum="LightParam">
|
||||
<constant name="LIGHT_PARAM_MAX" value="16" enum="LightParam">
|
||||
Represents the size of the [enum LightParam] enum.
|
||||
</constant>
|
||||
<constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode">
|
||||
|
|
|
@ -3756,6 +3756,7 @@ RID RasterizerStorageGLES2::light_create(VS::LightType p_type) {
|
|||
|
||||
light->param[VS::LIGHT_PARAM_ENERGY] = 1.0;
|
||||
light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
|
||||
light->param[VS::LIGHT_PARAM_SIZE] = 0.0;
|
||||
light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
|
||||
light->param[VS::LIGHT_PARAM_RANGE] = 1.0;
|
||||
light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
|
||||
|
|
|
@ -5261,6 +5261,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) {
|
|||
|
||||
light->param[VS::LIGHT_PARAM_ENERGY] = 1.0;
|
||||
light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
|
||||
light->param[VS::LIGHT_PARAM_SIZE] = 0.0;
|
||||
light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
|
||||
light->param[VS::LIGHT_PARAM_RANGE] = 1.0;
|
||||
light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
|
||||
|
|
|
@ -685,85 +685,6 @@ void LightmapperCPU::_plot_triangle(const Vector2 *p_vertices, const Vector3 *p_
|
|||
}
|
||||
}
|
||||
|
||||
void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
|
||||
LightmapTexel *lightmap = (LightmapTexel *)r_lightmap;
|
||||
for (unsigned int i = 0; i < lights.size(); ++i) {
|
||||
const Light &light = lights[i];
|
||||
Vector3 normal = lightmap[p_idx].normal;
|
||||
Vector3 position = lightmap[p_idx].pos;
|
||||
Vector3 final_energy;
|
||||
Color c = light.color;
|
||||
Vector3 light_energy = Vector3(c.r, c.g, c.b) * light.energy;
|
||||
|
||||
if (light.type == LIGHT_TYPE_OMNI) {
|
||||
Vector3 light_direction = (position - light.position).normalized();
|
||||
if (normal.dot(light_direction) >= 0.0) {
|
||||
continue;
|
||||
}
|
||||
float dist = position.distance_to(light.position);
|
||||
|
||||
if (dist <= light.range) {
|
||||
LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_direction, parameters.bias, dist - parameters.bias);
|
||||
if (raycaster->intersect(ray)) {
|
||||
continue;
|
||||
}
|
||||
float att = powf(1.0 - dist / light.range, light.attenuation);
|
||||
final_energy = light_energy * att * MAX(0, normal.dot(-light_direction));
|
||||
}
|
||||
}
|
||||
|
||||
if (light.type == LIGHT_TYPE_SPOT) {
|
||||
Vector3 light_direction = (position - light.position).normalized();
|
||||
if (normal.dot(light_direction) >= 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float angle = Math::acos(light.direction.dot(light_direction));
|
||||
|
||||
if (angle > light.spot_angle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float dist = position.distance_to(light.position);
|
||||
if (dist > light.range) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_direction, parameters.bias, dist);
|
||||
if (raycaster->intersect(ray)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float normalized_dist = dist * (1.0f / MAX(0.001f, light.range));
|
||||
float norm_light_attenuation = Math::pow(MAX(1.0f - normalized_dist, 0.001f), light.attenuation);
|
||||
|
||||
float spot_cutoff = Math::cos(light.spot_angle);
|
||||
float scos = MAX(light_direction.dot(light.direction), spot_cutoff);
|
||||
float spot_rim = (1.0f - scos) / (1.0f - spot_cutoff);
|
||||
norm_light_attenuation *= 1.0f - pow(MAX(spot_rim, 0.001f), light.spot_attenuation);
|
||||
final_energy = light_energy * norm_light_attenuation * MAX(0, normal.dot(-light_direction));
|
||||
}
|
||||
|
||||
if (light.type == LIGHT_TYPE_DIRECTIONAL) {
|
||||
if (normal.dot(light.direction) >= 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position + normal * parameters.bias, -light.direction, parameters.bias);
|
||||
if (raycaster->intersect(ray)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final_energy = light_energy * MAX(0, normal.dot(-light.direction));
|
||||
}
|
||||
|
||||
lightmap[p_idx].direct_light += final_energy * light.indirect_multiplier;
|
||||
if (light.bake_direct) {
|
||||
lightmap[p_idx].output_light += final_energy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ float uniform_rand() {
|
||||
/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
|
||||
static thread_local uint32_t state = Math::rand();
|
||||
|
@ -774,6 +695,123 @@ _ALWAYS_INLINE_ float uniform_rand() {
|
|||
return float(state) / float(UINT32_MAX);
|
||||
}
|
||||
|
||||
void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
|
||||
LightmapTexel *lightmap = (LightmapTexel *)r_lightmap;
|
||||
for (unsigned int i = 0; i < lights.size(); ++i) {
|
||||
const Light &light = lights[i];
|
||||
Vector3 normal = lightmap[p_idx].normal;
|
||||
Vector3 position = lightmap[p_idx].pos;
|
||||
Color c = light.color;
|
||||
Vector3 light_energy = Vector3(c.r, c.g, c.b) * light.energy;
|
||||
|
||||
Vector3 light_to_point = light.direction;
|
||||
if (light.type == LIGHT_TYPE_OMNI || light.type == LIGHT_TYPE_SPOT) {
|
||||
light_to_point = (position - light.position).normalized();
|
||||
}
|
||||
|
||||
if (normal.dot(light_to_point) >= 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float dist;
|
||||
float attenuation;
|
||||
float soft_shadowing_disk_size;
|
||||
|
||||
if (light.type == LIGHT_TYPE_OMNI || light.type == LIGHT_TYPE_SPOT) {
|
||||
dist = position.distance_to(light.position);
|
||||
if (dist > light.range) {
|
||||
continue;
|
||||
}
|
||||
soft_shadowing_disk_size = light.size / dist;
|
||||
|
||||
if (light.type == LIGHT_TYPE_OMNI) {
|
||||
attenuation = powf(1.0 - dist / light.range, light.attenuation);
|
||||
} else /* (light.type == LIGHT_TYPE_SPOT) */ {
|
||||
float angle = Math::acos(light.direction.dot(light_to_point));
|
||||
|
||||
if (angle > light.spot_angle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float normalized_dist = dist * (1.0f / MAX(0.001f, light.range));
|
||||
float norm_light_attenuation = Math::pow(MAX(1.0f - normalized_dist, 0.001f), light.attenuation);
|
||||
|
||||
float spot_cutoff = Math::cos(light.spot_angle);
|
||||
float scos = MAX(light_to_point.dot(light.direction), spot_cutoff);
|
||||
float spot_rim = (1.0f - scos) / (1.0f - spot_cutoff);
|
||||
attenuation = norm_light_attenuation * (1.0f - pow(MAX(spot_rim, 0.001f), light.spot_attenuation));
|
||||
}
|
||||
} else /*if (light.type == LIGHT_TYPE_DIRECTIONAL)*/ {
|
||||
dist = INFINITY;
|
||||
attenuation = 1.0f;
|
||||
soft_shadowing_disk_size = light.size;
|
||||
}
|
||||
|
||||
float penumbra = 0.0f;
|
||||
if (light.size > 0.0) {
|
||||
Vector3 light_to_point_tan;
|
||||
Vector3 light_to_point_bitan;
|
||||
|
||||
if (light.type == LIGHT_TYPE_OMNI || light.type == LIGHT_TYPE_SPOT) {
|
||||
light_to_point = (position - light.position).normalized();
|
||||
Vector3 aux = light_to_point.y < 0.777 ? Vector3(0, 1, 0) : Vector3(1, 0, 0);
|
||||
light_to_point_tan = light_to_point.cross(aux).normalized();
|
||||
light_to_point_bitan = light_to_point.cross(light_to_point_tan).normalized();
|
||||
} else /*if (light.type == LIGHT_TYPE_DIRECTIONAL)*/ {
|
||||
Vector3 aux = light_to_point.y < 0.777 ? Vector3(0, 1, 0) : Vector3(1, 0, 0);
|
||||
light_to_point_tan = light_to_point.cross(aux).normalized();
|
||||
light_to_point_bitan = light_to_point.cross(light_to_point_tan).normalized();
|
||||
}
|
||||
|
||||
const static int shadowing_rays_check_penumbra_denom = 2;
|
||||
int shadowing_ray_count = parameters.samples;
|
||||
|
||||
int hits = 0;
|
||||
Vector3 light_disk_to_point = light_to_point;
|
||||
for (int j = 0; j < shadowing_ray_count; j++) {
|
||||
// Optimization:
|
||||
// Once already casted an important proportion of rays, if all are hits or misses,
|
||||
// assume we're not in the penumbra so we can infer the rest would have the same result
|
||||
if (j == shadowing_ray_count / shadowing_rays_check_penumbra_denom) {
|
||||
if (hits == j) {
|
||||
// Assume totally lit
|
||||
hits = shadowing_ray_count;
|
||||
break;
|
||||
} else if (hits == 0) {
|
||||
// Assume totally dark
|
||||
hits = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float r = uniform_rand();
|
||||
float a = uniform_rand() * Math_TAU;
|
||||
Vector2 disk_sample = (r * Vector2(Math::cos(a), Math::sin(a))) * soft_shadowing_disk_size;
|
||||
light_disk_to_point = (light_to_point + disk_sample.x * light_to_point_tan + disk_sample.y * light_to_point_bitan).normalized();
|
||||
|
||||
LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_disk_to_point, parameters.bias, dist);
|
||||
if (raycaster->intersect(ray)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hits++;
|
||||
}
|
||||
penumbra = (float)hits / shadowing_ray_count;
|
||||
} else {
|
||||
LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_to_point, parameters.bias, dist);
|
||||
if (!raycaster->intersect(ray)) {
|
||||
penumbra = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 final_energy = attenuation * penumbra * light_energy * MAX(0, normal.dot(-light_to_point));
|
||||
lightmap[p_idx].direct_light += final_energy * light.indirect_multiplier;
|
||||
if (light.bake_direct) {
|
||||
lightmap[p_idx].output_light += final_energy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LightmapperCPU::_compute_indirect_light(uint32_t p_idx, void *r_lightmap) {
|
||||
LightmapTexel *lightmap = (LightmapTexel *)r_lightmap;
|
||||
LightmapTexel &texel = lightmap[p_idx];
|
||||
|
@ -1583,7 +1621,7 @@ void LightmapperCPU::add_mesh(const MeshData &p_mesh, Vector2i p_size) {
|
|||
mesh_instances.push_back(mi);
|
||||
}
|
||||
|
||||
void LightmapperCPU::add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier) {
|
||||
void LightmapperCPU::add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size) {
|
||||
Light l;
|
||||
l.type = LIGHT_TYPE_DIRECTIONAL;
|
||||
l.direction = p_direction;
|
||||
|
@ -1591,10 +1629,11 @@ void LightmapperCPU::add_directional_light(bool p_bake_direct, const Vector3 &p_
|
|||
l.energy = p_energy;
|
||||
l.indirect_multiplier = p_indirect_multiplier;
|
||||
l.bake_direct = p_bake_direct;
|
||||
l.size = p_size;
|
||||
lights.push_back(l);
|
||||
}
|
||||
|
||||
void LightmapperCPU::add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation) {
|
||||
void LightmapperCPU::add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size) {
|
||||
Light l;
|
||||
l.type = LIGHT_TYPE_OMNI;
|
||||
l.position = p_position;
|
||||
|
@ -1604,10 +1643,11 @@ void LightmapperCPU::add_omni_light(bool p_bake_direct, const Vector3 &p_positio
|
|||
l.energy = p_energy;
|
||||
l.indirect_multiplier = p_indirect_multiplier;
|
||||
l.bake_direct = p_bake_direct;
|
||||
l.size = p_size;
|
||||
lights.push_back(l);
|
||||
}
|
||||
|
||||
void LightmapperCPU::add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation) {
|
||||
void LightmapperCPU::add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) {
|
||||
Light l;
|
||||
l.type = LIGHT_TYPE_SPOT;
|
||||
l.position = p_position;
|
||||
|
@ -1620,6 +1660,7 @@ void LightmapperCPU::add_spot_light(bool p_bake_direct, const Vector3 &p_positio
|
|||
l.energy = p_energy;
|
||||
l.indirect_multiplier = p_indirect_multiplier;
|
||||
l.bake_direct = p_bake_direct;
|
||||
l.size = p_size;
|
||||
lights.push_back(l);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ class LightmapperCPU : public Lightmapper {
|
|||
float attenuation;
|
||||
float spot_angle;
|
||||
float spot_attenuation;
|
||||
float size;
|
||||
bool bake_direct;
|
||||
};
|
||||
|
||||
|
@ -165,9 +166,9 @@ public:
|
|||
virtual void add_albedo_texture(Ref<Texture> p_texture);
|
||||
virtual void add_emission_texture(Ref<Texture> p_texture);
|
||||
virtual void add_mesh(const MeshData &p_mesh, Vector2i p_size);
|
||||
virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier);
|
||||
virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation);
|
||||
virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation);
|
||||
virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size);
|
||||
virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size);
|
||||
virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size);
|
||||
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, BakeStepFunc p_substep_function = nullptr);
|
||||
|
||||
int get_bake_texture_count() const;
|
||||
|
|
|
@ -746,13 +746,13 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_sa
|
|||
|
||||
if (Object::cast_to<DirectionalLight>(light)) {
|
||||
DirectionalLight *l = Object::cast_to<DirectionalLight>(light);
|
||||
lightmapper->add_directional_light(light->get_bake_mode() == Light::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY));
|
||||
lightmapper->add_directional_light(light->get_bake_mode() == Light::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_SIZE));
|
||||
} else if (Object::cast_to<OmniLight>(light)) {
|
||||
OmniLight *l = Object::cast_to<OmniLight>(light);
|
||||
lightmapper->add_omni_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION));
|
||||
lightmapper->add_omni_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SIZE));
|
||||
} else if (Object::cast_to<SpotLight>(light)) {
|
||||
SpotLight *l = Object::cast_to<SpotLight>(light);
|
||||
lightmapper->add_spot_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SPOT_ANGLE), l->get_param(Light::PARAM_SPOT_ATTENUATION));
|
||||
lightmapper->add_spot_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SPOT_ANGLE), l->get_param(Light::PARAM_SPOT_ATTENUATION), l->get_param(Light::PARAM_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ PoolVector<Face3> Light::get_faces(uint32_t p_usage_flags) const {
|
|||
void Light::set_bake_mode(BakeMode p_mode) {
|
||||
bake_mode = p_mode;
|
||||
VS::get_singleton()->light_set_bake_mode(light, VS::LightBakeMode(bake_mode));
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
Light::BakeMode Light::get_bake_mode() const {
|
||||
|
@ -196,6 +197,10 @@ void Light::_validate_property(PropertyInfo &property) const {
|
|||
if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") {
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
|
||||
}
|
||||
|
||||
if (bake_mode != BAKE_ALL && property.name == "light_size") {
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
void Light::_bind_methods() {
|
||||
|
@ -230,6 +235,7 @@ void Light::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_size", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_param", "get_param", PARAM_SIZE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode");
|
||||
|
@ -246,6 +252,7 @@ void Light::_bind_methods() {
|
|||
|
||||
BIND_ENUM_CONSTANT(PARAM_ENERGY);
|
||||
BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY);
|
||||
BIND_ENUM_CONSTANT(PARAM_SIZE);
|
||||
BIND_ENUM_CONSTANT(PARAM_SPECULAR);
|
||||
BIND_ENUM_CONSTANT(PARAM_RANGE);
|
||||
BIND_ENUM_CONSTANT(PARAM_ATTENUATION);
|
||||
|
@ -295,6 +302,7 @@ Light::Light(VisualServer::LightType p_type) {
|
|||
|
||||
set_param(PARAM_ENERGY, 1);
|
||||
set_param(PARAM_INDIRECT_ENERGY, 1);
|
||||
set_param(PARAM_SIZE, 0);
|
||||
set_param(PARAM_SPECULAR, 0.5);
|
||||
set_param(PARAM_RANGE, 5);
|
||||
set_param(PARAM_ATTENUATION, 1);
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
enum Param {
|
||||
PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY,
|
||||
PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY,
|
||||
PARAM_SIZE = VS::LIGHT_PARAM_SIZE,
|
||||
PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR,
|
||||
PARAM_RANGE = VS::LIGHT_PARAM_RANGE,
|
||||
PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION,
|
||||
|
|
|
@ -176,9 +176,9 @@ public:
|
|||
virtual void add_albedo_texture(Ref<Texture> p_texture) = 0;
|
||||
virtual void add_emission_texture(Ref<Texture> p_texture) = 0;
|
||||
virtual void add_mesh(const MeshData &p_mesh, Vector2i p_size) = 0;
|
||||
virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier) = 0;
|
||||
virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation) = 0;
|
||||
virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation) = 0;
|
||||
virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size) = 0;
|
||||
virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size) = 0;
|
||||
virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) = 0;
|
||||
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, BakeStepFunc p_substep_function = nullptr) = 0;
|
||||
|
||||
virtual int get_bake_texture_count() const = 0;
|
||||
|
|
|
@ -2002,6 +2002,8 @@ void VisualServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(LIGHT_SPOT);
|
||||
|
||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
|
||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
|
||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
|
||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
|
||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
|
||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
|
||||
|
|
|
@ -411,6 +411,7 @@ public:
|
|||
|
||||
LIGHT_PARAM_ENERGY,
|
||||
LIGHT_PARAM_INDIRECT_ENERGY,
|
||||
LIGHT_PARAM_SIZE,
|
||||
LIGHT_PARAM_SPECULAR,
|
||||
LIGHT_PARAM_RANGE,
|
||||
LIGHT_PARAM_ATTENUATION,
|
||||
|
|
Loading…
Reference in a new issue