mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-30 21:09:19 +01:00
Adding back lightmaps pt1.
This commit is contained in:
parent
0c95ddb60d
commit
98cbf1026a
@ -64,10 +64,13 @@
|
|||||||
Will only show the shadows casted from this object.
|
Will only show the shadows casted from this object.
|
||||||
In other words, the actual mesh will not be visible, only the shadows casted from the mesh will be.
|
In other words, the actual mesh will not be visible, only the shadows casted from the mesh will be.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FLAG_DRAW_NEXT_FRAME_IF_VISIBLE" value="0" enum="Flags">
|
<constant name="FLAG_USE_BAKED_LIGHT" value="0" enum="Flags">
|
||||||
|
Will allow the GeometryInstance to be used when baking lights using a [GIProbe] or [BakedLightmap].
|
||||||
|
</constant>
|
||||||
|
<constant name="FLAG_DRAW_NEXT_FRAME_IF_VISIBLE" value="1" enum="Flags">
|
||||||
Unused in this class, exposed for consistency with [enum RenderingServer.InstanceFlags].
|
Unused in this class, exposed for consistency with [enum RenderingServer.InstanceFlags].
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FLAG_MAX" value="1" enum="Flags">
|
<constant name="FLAG_MAX" value="2" enum="Flags">
|
||||||
Represents the size of the [enum Flags] enum.
|
Represents the size of the [enum Flags] enum.
|
||||||
</constant>
|
</constant>
|
||||||
</constants>
|
</constants>
|
||||||
|
@ -3292,10 +3292,13 @@
|
|||||||
<constant name="INSTANCE_GEOMETRY_MASK" value="14" enum="InstanceType">
|
<constant name="INSTANCE_GEOMETRY_MASK" value="14" enum="InstanceType">
|
||||||
A combination of the flags of geometry instances (mesh, multimesh, immediate and particles).
|
A combination of the flags of geometry instances (mesh, multimesh, immediate and particles).
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE" value="0" enum="InstanceFlags">
|
<constant name="INSTANCE_FLAG_USE_BAKED_LIGHT" value="1" enum="InstanceFlags">
|
||||||
|
Allows the instance to be used in baked lighting.
|
||||||
|
</constant>
|
||||||
|
<constant name="INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE" value="2" enum="InstanceFlags">
|
||||||
When set, manually requests to draw geometry on next frame.
|
When set, manually requests to draw geometry on next frame.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="INSTANCE_FLAG_MAX" value="1" enum="InstanceFlags">
|
<constant name="INSTANCE_FLAG_MAX" value="2" enum="InstanceFlags">
|
||||||
Represents the size of the [enum InstanceFlags] enum.
|
Represents the size of the [enum InstanceFlags] enum.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum="ShadowCastingSetting">
|
<constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum="ShadowCastingSetting">
|
||||||
|
@ -551,6 +551,71 @@ public:
|
|||||||
void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
|
void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
|
||||||
void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
|
void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
|
||||||
|
|
||||||
|
/* LIGHTMAP CAPTURE */
|
||||||
|
struct Instantiable : public RID_Data {
|
||||||
|
SelfList<RasterizerScene::InstanceBase>::List instance_list;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void instance_change_notify(bool p_aabb = true, bool p_materials = true) {
|
||||||
|
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
|
||||||
|
while (instances) {
|
||||||
|
instances->self()->base_changed(p_aabb, p_materials);
|
||||||
|
instances = instances->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void instance_remove_deps() {
|
||||||
|
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
|
||||||
|
while (instances) {
|
||||||
|
SelfList<RasterizerScene::InstanceBase> *next = instances->next();
|
||||||
|
instances->self()->base_removed();
|
||||||
|
instances = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instantiable() {}
|
||||||
|
virtual ~Instantiable() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LightmapCapture : public Instantiable {
|
||||||
|
PoolVector<LightmapCaptureOctree> octree;
|
||||||
|
AABB bounds;
|
||||||
|
Transform cell_xform;
|
||||||
|
int cell_subdiv;
|
||||||
|
float energy;
|
||||||
|
LightmapCapture() {
|
||||||
|
energy = 1.0;
|
||||||
|
cell_subdiv = 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable RID_Owner<LightmapCapture> lightmap_capture_data_owner;
|
||||||
|
void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {}
|
||||||
|
AABB lightmap_capture_get_bounds(RID p_capture) const { return AABB(); }
|
||||||
|
void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) {}
|
||||||
|
RID lightmap_capture_create() {
|
||||||
|
LightmapCapture *capture = memnew(LightmapCapture);
|
||||||
|
return lightmap_capture_data_owner.make_rid(capture);
|
||||||
|
}
|
||||||
|
PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, PoolVector<uint8_t>());
|
||||||
|
return PoolVector<uint8_t>();
|
||||||
|
}
|
||||||
|
void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {}
|
||||||
|
Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const { return Transform(); }
|
||||||
|
void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {}
|
||||||
|
int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { return 0; }
|
||||||
|
void lightmap_capture_set_energy(RID p_capture, float p_energy) {}
|
||||||
|
float lightmap_capture_get_energy(RID p_capture) const { return 0.0; }
|
||||||
|
void lightmap_capture_set_interior(RID p_capture, bool p_interior) {}
|
||||||
|
bool lightmap_capture_is_interior(RID p_capture) const { return false; }
|
||||||
|
const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, NULL);
|
||||||
|
return &capture->octree;
|
||||||
|
}
|
||||||
|
|
||||||
/* RENDER TARGET */
|
/* RENDER TARGET */
|
||||||
|
|
||||||
RID render_target_create() { return RID(); }
|
RID render_target_create() { return RID(); }
|
||||||
@ -579,6 +644,8 @@ public:
|
|||||||
RS::InstanceType get_base_type(RID p_rid) const {
|
RS::InstanceType get_base_type(RID p_rid) const {
|
||||||
if (mesh_owner.owns(p_rid)) {
|
if (mesh_owner.owns(p_rid)) {
|
||||||
return RS::INSTANCE_MESH;
|
return RS::INSTANCE_MESH;
|
||||||
|
} else if (lightmap_capture_data_owner.owns(p_rid)) {
|
||||||
|
return RS::INSTANCE_LIGHTMAP_CAPTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RS::INSTANCE_NONE;
|
return RS::INSTANCE_NONE;
|
||||||
@ -595,6 +662,11 @@ public:
|
|||||||
DummyMesh *mesh = mesh_owner.getornull(p_rid);
|
DummyMesh *mesh = mesh_owner.getornull(p_rid);
|
||||||
mesh_owner.free(p_rid);
|
mesh_owner.free(p_rid);
|
||||||
memdelete(mesh);
|
memdelete(mesh);
|
||||||
|
} else if (lightmap_capture_data_owner.owns(p_rid)) {
|
||||||
|
// delete the lightmap
|
||||||
|
LightmapCapture *lightmap_capture = lightmap_capture_data_owner.getornull(p_rid);
|
||||||
|
lightmap_capture_data_owner.free(p_rid);
|
||||||
|
memdelete(lightmap_capture);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1209,7 +1209,13 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
|
|||||||
copy = true;
|
copy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->light_mode = LIGHTMODE_NORMAL;
|
if (e->instance->lightmap.is_valid()) {
|
||||||
|
e->light_mode = LIGHTMODE_LIGHTMAP;
|
||||||
|
} else if (!e->instance->lightmap_capture_data.empty()) {
|
||||||
|
e->light_mode = LIGHTMODE_LIGHTMAP_CAPTURE;
|
||||||
|
} else {
|
||||||
|
e->light_mode = LIGHTMODE_NORMAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2294,6 +2300,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
using_fog = true;
|
using_fog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RasterizerStorageGLES2::Texture *prev_lightmap = nullptr;
|
||||||
|
float lightmap_energy = 1.0;
|
||||||
|
bool prev_use_lightmap_capture = false;
|
||||||
|
|
||||||
storage->info.render.draw_call_count += p_element_count;
|
storage->info.render.draw_call_count += p_element_count;
|
||||||
|
|
||||||
for (int i = 0; i < p_element_count; i++) {
|
for (int i = 0; i < p_element_count; i++) {
|
||||||
@ -2307,8 +2317,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
LightInstance *light = nullptr;
|
LightInstance *light = nullptr;
|
||||||
ReflectionProbeInstance *refprobe_1 = nullptr;
|
ReflectionProbeInstance *refprobe_1 = nullptr;
|
||||||
ReflectionProbeInstance *refprobe_2 = nullptr;
|
ReflectionProbeInstance *refprobe_2 = nullptr;
|
||||||
|
RasterizerStorageGLES2::Texture *lightmap = nullptr;
|
||||||
|
bool use_lightmap_capture = false;
|
||||||
bool rebind_light = false;
|
bool rebind_light = false;
|
||||||
bool rebind_reflection = false;
|
bool rebind_reflection = false;
|
||||||
|
bool rebind_lightmap = false;
|
||||||
|
|
||||||
if (!p_shadow && material->shader) {
|
if (!p_shadow && material->shader) {
|
||||||
bool unshaded = material->shader->spatial.unshaded;
|
bool unshaded = material->shader->spatial.unshaded;
|
||||||
@ -2432,6 +2445,34 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
rebind = true;
|
rebind = true;
|
||||||
rebind_reflection = true;
|
rebind_reflection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use_lightmap_capture = !unshaded && !accum_pass && !e->instance->lightmap_capture_data.empty();
|
||||||
|
|
||||||
|
if (use_lightmap_capture != prev_use_lightmap_capture) {
|
||||||
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, use_lightmap_capture);
|
||||||
|
rebind = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unshaded && !accum_pass && e->instance->lightmap.is_valid()) {
|
||||||
|
lightmap = storage->texture_owner.getornull(e->instance->lightmap);
|
||||||
|
lightmap_energy = 1.0;
|
||||||
|
if (lightmap) {
|
||||||
|
RasterizerStorageGLES2::LightmapCapture *capture = storage->lightmap_capture_data_owner.getornull(e->instance->lightmap_capture->base);
|
||||||
|
if (capture) {
|
||||||
|
lightmap_energy = capture->energy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lightmap != prev_lightmap) {
|
||||||
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, lightmap != nullptr);
|
||||||
|
if (lightmap != nullptr) {
|
||||||
|
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, lightmap->tex_id);
|
||||||
|
}
|
||||||
|
rebind = true;
|
||||||
|
rebind_lightmap = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool depth_prepass = false;
|
bool depth_prepass = false;
|
||||||
@ -2533,6 +2574,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
//rebind all these
|
//rebind all these
|
||||||
rebind_light = true;
|
rebind_light = true;
|
||||||
rebind_reflection = true;
|
rebind_reflection = true;
|
||||||
|
rebind_lightmap = true;
|
||||||
|
|
||||||
if (using_fog) {
|
if (using_fog) {
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_COLOR_BASE, p_env->fog_color);
|
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_COLOR_BASE, p_env->fog_color);
|
||||||
@ -2579,8 +2621,19 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
_setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env);
|
_setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rebind_lightmap && lightmap) {
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_ENERGY, lightmap_energy);
|
||||||
|
if (storage->config.use_lightmap_filter_bicubic) {
|
||||||
|
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_TEXTURE_SIZE, Vector2(lightmap->width, lightmap->height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
|
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
|
||||||
|
|
||||||
|
if (use_lightmap_capture) { //this is per instance, must be set always if present
|
||||||
|
glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
_render_geometry(e);
|
_render_geometry(e);
|
||||||
|
|
||||||
prev_geometry = e->geometry;
|
prev_geometry = e->geometry;
|
||||||
@ -2592,6 +2645,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
prev_light = light;
|
prev_light = light;
|
||||||
prev_refprobe_1 = refprobe_1;
|
prev_refprobe_1 = refprobe_1;
|
||||||
prev_refprobe_2 = refprobe_2;
|
prev_refprobe_2 = refprobe_2;
|
||||||
|
prev_lightmap = lightmap;
|
||||||
|
prev_use_lightmap_capture = use_lightmap_capture;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setup_light_type(nullptr, nullptr); //clear light stuff
|
_setup_light_type(nullptr, nullptr); //clear light stuff
|
||||||
@ -2608,6 +2663,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false);
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, false);
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false);
|
||||||
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, false);
|
||||||
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false);
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false);
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false);
|
||||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, false);
|
state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, false);
|
||||||
@ -3967,6 +4024,10 @@ void RasterizerSceneGLES2::initialize() {
|
|||||||
|
|
||||||
directional_shadow_create();
|
directional_shadow_create();
|
||||||
|
|
||||||
|
if (storage->config.use_lightmap_filter_bicubic) {
|
||||||
|
state.scene_shader.add_custom_define("#define USE_LIGHTMAP_FILTER_BICUBIC\n");
|
||||||
|
}
|
||||||
|
|
||||||
shadow_filter_mode = SHADOW_FILTER_NEAREST;
|
shadow_filter_mode = SHADOW_FILTER_NEAREST;
|
||||||
|
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
|
@ -558,6 +558,8 @@ public:
|
|||||||
enum LightMode {
|
enum LightMode {
|
||||||
LIGHTMODE_NORMAL,
|
LIGHTMODE_NORMAL,
|
||||||
LIGHTMODE_UNSHADED,
|
LIGHTMODE_UNSHADED,
|
||||||
|
LIGHTMODE_LIGHTMAP,
|
||||||
|
LIGHTMODE_LIGHTMAP_CAPTURE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderList {
|
struct RenderList {
|
||||||
|
@ -4649,6 +4649,127 @@ int RasterizerStorageGLES2::reflection_probe_get_resolution(RID p_probe) const {
|
|||||||
return reflection_probe->resolution;
|
return reflection_probe->resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////
|
||||||
|
|
||||||
|
RID RasterizerStorageGLES2::lightmap_capture_create() {
|
||||||
|
LightmapCapture *capture = memnew(LightmapCapture);
|
||||||
|
return lightmap_capture_data_owner.make_rid(capture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {
|
||||||
|
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND(!capture);
|
||||||
|
capture->bounds = p_bounds;
|
||||||
|
capture->instance_change_notify(true, false);
|
||||||
|
}
|
||||||
|
AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, AABB());
|
||||||
|
return capture->bounds;
|
||||||
|
}
|
||||||
|
void RasterizerStorageGLES2::lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) {
|
||||||
|
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND(!capture);
|
||||||
|
|
||||||
|
ERR_FAIL_COND(p_octree.size() == 0 || (p_octree.size() % sizeof(LightmapCaptureOctree)) != 0);
|
||||||
|
|
||||||
|
capture->octree.resize(p_octree.size() / sizeof(LightmapCaptureOctree));
|
||||||
|
if (p_octree.size()) {
|
||||||
|
PoolVector<LightmapCaptureOctree>::Write w = capture->octree.write();
|
||||||
|
PoolVector<uint8_t>::Read r = p_octree.read();
|
||||||
|
memcpy(w.ptr(), r.ptr(), p_octree.size());
|
||||||
|
}
|
||||||
|
capture->instance_change_notify(true, false);
|
||||||
|
}
|
||||||
|
PoolVector<uint8_t> RasterizerStorageGLES2::lightmap_capture_get_octree(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, PoolVector<uint8_t>());
|
||||||
|
|
||||||
|
if (capture->octree.size() == 0) {
|
||||||
|
return PoolVector<uint8_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolVector<uint8_t> ret;
|
||||||
|
ret.resize(capture->octree.size() * sizeof(LightmapCaptureOctree));
|
||||||
|
{
|
||||||
|
PoolVector<LightmapCaptureOctree>::Read r = capture->octree.read();
|
||||||
|
PoolVector<uint8_t>::Write w = ret.write();
|
||||||
|
memcpy(w.ptr(), r.ptr(), ret.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {
|
||||||
|
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND(!capture);
|
||||||
|
capture->cell_xform = p_xform;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform RasterizerStorageGLES2::lightmap_capture_get_octree_cell_transform(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, Transform());
|
||||||
|
return capture->cell_xform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {
|
||||||
|
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND(!capture);
|
||||||
|
capture->cell_subdiv = p_subdiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RasterizerStorageGLES2::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, 0);
|
||||||
|
return capture->cell_subdiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::lightmap_capture_set_energy(RID p_capture, float p_energy) {
|
||||||
|
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND(!capture);
|
||||||
|
capture->energy = p_energy;
|
||||||
|
|
||||||
|
if (!capture->update_list.in_list()) {
|
||||||
|
capture_update_list.add(&capture->update_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, 0);
|
||||||
|
return capture->energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::lightmap_capture_set_interior(RID p_capture, bool p_interior) {
|
||||||
|
LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND(!capture);
|
||||||
|
capture->interior = p_interior;
|
||||||
|
|
||||||
|
if (!capture->update_list.in_list()) {
|
||||||
|
capture_update_list.add(&capture->update_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RasterizerStorageGLES2::lightmap_capture_is_interior(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, false);
|
||||||
|
return capture->interior;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::update_dirty_captures() {
|
||||||
|
while (capture_update_list.first()) {
|
||||||
|
LightmapCapture *capture = capture_update_list.first()->self();
|
||||||
|
capture->instance_change_notify(false, true);
|
||||||
|
capture_update_list.remove(capture_update_list.first());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const PoolVector<RasterizerStorage::LightmapCaptureOctree> *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const {
|
||||||
|
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
|
||||||
|
ERR_FAIL_COND_V(!capture, nullptr);
|
||||||
|
return &capture->octree;
|
||||||
|
}
|
||||||
|
|
||||||
////////
|
////////
|
||||||
|
|
||||||
void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
|
void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
|
||||||
@ -4688,6 +4809,10 @@ void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene
|
|||||||
inst = light_owner.getornull(p_base);
|
inst = light_owner.getornull(p_base);
|
||||||
ERR_FAIL_COND(!inst);
|
ERR_FAIL_COND(!inst);
|
||||||
} break;
|
} break;
|
||||||
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
inst = lightmap_capture_data_owner.getornull(p_base);
|
||||||
|
ERR_FAIL_COND(!inst);
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
ERR_FAIL();
|
ERR_FAIL();
|
||||||
}
|
}
|
||||||
@ -4720,6 +4845,10 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc
|
|||||||
inst = light_owner.getornull(p_base);
|
inst = light_owner.getornull(p_base);
|
||||||
ERR_FAIL_COND(!inst);
|
ERR_FAIL_COND(!inst);
|
||||||
} break;
|
} break;
|
||||||
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
inst = lightmap_capture_data_owner.getornull(p_base);
|
||||||
|
ERR_FAIL_COND(!inst);
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
ERR_FAIL();
|
ERR_FAIL();
|
||||||
}
|
}
|
||||||
@ -5626,6 +5755,8 @@ RS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
|
|||||||
return RS::INSTANCE_IMMEDIATE;
|
return RS::INSTANCE_IMMEDIATE;
|
||||||
} else if (reflection_probe_owner.owns(p_rid)) {
|
} else if (reflection_probe_owner.owns(p_rid)) {
|
||||||
return RS::INSTANCE_REFLECTION_PROBE;
|
return RS::INSTANCE_REFLECTION_PROBE;
|
||||||
|
} else if (lightmap_capture_data_owner.owns(p_rid)) {
|
||||||
|
return RS::INSTANCE_LIGHTMAP_CAPTURE;
|
||||||
} else {
|
} else {
|
||||||
return RS::INSTANCE_NONE;
|
return RS::INSTANCE_NONE;
|
||||||
}
|
}
|
||||||
@ -5816,6 +5947,15 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
|
|||||||
memdelete(reflection_probe);
|
memdelete(reflection_probe);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (lightmap_capture_data_owner.owns(p_rid)) {
|
||||||
|
// delete the texture
|
||||||
|
LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid);
|
||||||
|
lightmap_capture->instance_remove_deps();
|
||||||
|
|
||||||
|
lightmap_capture_data_owner.free(p_rid);
|
||||||
|
memdelete(lightmap_capture);
|
||||||
|
return true;
|
||||||
|
|
||||||
} else if (canvas_occluder_owner.owns(p_rid)) {
|
} else if (canvas_occluder_owner.owns(p_rid)) {
|
||||||
CanvasOccluder *co = canvas_occluder_owner.get(p_rid);
|
CanvasOccluder *co = canvas_occluder_owner.get(p_rid);
|
||||||
if (co->index_id) {
|
if (co->index_id) {
|
||||||
@ -6341,6 +6481,9 @@ void RasterizerStorageGLES2::initialize() {
|
|||||||
|
|
||||||
config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
|
config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
|
||||||
config.use_fast_texture_filter = GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
|
config.use_fast_texture_filter = GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
|
||||||
|
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling", true);
|
||||||
|
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling.mobile", false);
|
||||||
|
config.use_lightmap_filter_bicubic = GLOBAL_GET("rendering/quality/lightmapping/use_bicubic_sampling");
|
||||||
|
|
||||||
config.use_physical_light_attenuation = GLOBAL_GET("rendering/quality/shading/use_physical_light_attenuation");
|
config.use_physical_light_attenuation = GLOBAL_GET("rendering/quality/shading/use_physical_light_attenuation");
|
||||||
|
|
||||||
@ -6372,6 +6515,7 @@ void RasterizerStorageGLES2::update_dirty_resources() {
|
|||||||
update_dirty_blend_shapes();
|
update_dirty_blend_shapes();
|
||||||
update_dirty_skeletons();
|
update_dirty_skeletons();
|
||||||
update_dirty_multimeshes();
|
update_dirty_multimeshes();
|
||||||
|
update_dirty_captures();
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerStorageGLES2::RasterizerStorageGLES2() {
|
RasterizerStorageGLES2::RasterizerStorageGLES2() {
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
bool use_fast_texture_filter;
|
bool use_fast_texture_filter;
|
||||||
bool use_anisotropic_filter;
|
bool use_anisotropic_filter;
|
||||||
bool use_skeleton_software;
|
bool use_skeleton_software;
|
||||||
|
bool use_lightmap_filter_bicubic;
|
||||||
bool use_physical_light_attenuation;
|
bool use_physical_light_attenuation;
|
||||||
|
|
||||||
int max_vertex_texture_image_units;
|
int max_vertex_texture_image_units;
|
||||||
@ -1048,6 +1049,48 @@ public:
|
|||||||
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const;
|
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const;
|
||||||
virtual bool reflection_probe_renders_shadows(RID p_probe) const;
|
virtual bool reflection_probe_renders_shadows(RID p_probe) const;
|
||||||
|
|
||||||
|
/* LIGHTMAP */
|
||||||
|
|
||||||
|
struct LightmapCapture : public Instantiable {
|
||||||
|
PoolVector<LightmapCaptureOctree> octree;
|
||||||
|
AABB bounds;
|
||||||
|
Transform cell_xform;
|
||||||
|
int cell_subdiv;
|
||||||
|
float energy;
|
||||||
|
bool interior;
|
||||||
|
|
||||||
|
SelfList<LightmapCapture> update_list;
|
||||||
|
|
||||||
|
LightmapCapture() :
|
||||||
|
update_list(this) {
|
||||||
|
energy = 1.0;
|
||||||
|
cell_subdiv = 1;
|
||||||
|
interior = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SelfList<LightmapCapture>::List capture_update_list;
|
||||||
|
|
||||||
|
void update_dirty_captures();
|
||||||
|
|
||||||
|
mutable RID_Owner<LightmapCapture> lightmap_capture_data_owner;
|
||||||
|
|
||||||
|
virtual RID lightmap_capture_create();
|
||||||
|
virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds);
|
||||||
|
virtual AABB lightmap_capture_get_bounds(RID p_capture) const;
|
||||||
|
virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree);
|
||||||
|
virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const;
|
||||||
|
virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform);
|
||||||
|
virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const;
|
||||||
|
virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv);
|
||||||
|
virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const;
|
||||||
|
virtual void lightmap_capture_set_energy(RID p_capture, float p_energy);
|
||||||
|
virtual float lightmap_capture_get_energy(RID p_capture) const;
|
||||||
|
virtual void lightmap_capture_set_interior(RID p_capture, bool p_interior);
|
||||||
|
virtual bool lightmap_capture_is_interior(RID p_capture) const;
|
||||||
|
|
||||||
|
virtual const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const;
|
||||||
|
|
||||||
/* INSTANCE */
|
/* INSTANCE */
|
||||||
|
|
||||||
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
|
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
|
||||||
|
@ -53,7 +53,7 @@ attribute vec4 color_attrib; // attrib:3
|
|||||||
attribute vec2 uv_attrib; // attrib:4
|
attribute vec2 uv_attrib; // attrib:4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_UV2_INTERP)
|
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
|
||||||
attribute vec2 uv2_attrib; // attrib:5
|
attribute vec2 uv2_attrib; // attrib:5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ varying vec4 color_interp;
|
|||||||
varying vec2 uv_interp;
|
varying vec2 uv_interp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_UV2_INTERP)
|
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
|
||||||
varying vec2 uv2_interp;
|
varying vec2 uv2_interp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -305,7 +305,9 @@ uniform highp mat4 refprobe1_local_matrix;
|
|||||||
varying mediump vec4 refprobe1_reflection_normal_blend;
|
varying mediump vec4 refprobe1_reflection_normal_blend;
|
||||||
uniform highp vec3 refprobe1_box_extents;
|
uniform highp vec3 refprobe1_box_extents;
|
||||||
|
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
varying mediump vec3 refprobe1_ambient_normal;
|
varying mediump vec3 refprobe1_ambient_normal;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //reflection probe1
|
#endif //reflection probe1
|
||||||
|
|
||||||
@ -315,7 +317,9 @@ uniform highp mat4 refprobe2_local_matrix;
|
|||||||
varying mediump vec4 refprobe2_reflection_normal_blend;
|
varying mediump vec4 refprobe2_reflection_normal_blend;
|
||||||
uniform highp vec3 refprobe2_box_extents;
|
uniform highp vec3 refprobe2_box_extents;
|
||||||
|
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
varying mediump vec3 refprobe2_ambient_normal;
|
varying mediump vec3 refprobe2_ambient_normal;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //reflection probe2
|
#endif //reflection probe2
|
||||||
|
|
||||||
@ -392,7 +396,7 @@ void main() {
|
|||||||
uv_interp = uv_attrib;
|
uv_interp = uv_attrib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_UV2_INTERP)
|
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
|
||||||
uv2_interp = uv2_attrib;
|
uv2_interp = uv2_attrib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -678,7 +682,9 @@ VERTEX_SHADER_CODE
|
|||||||
refprobe1_reflection_normal_blend.a = blend;
|
refprobe1_reflection_normal_blend.a = blend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //USE_REFLECTION_PROBE1
|
#endif //USE_REFLECTION_PROBE1
|
||||||
@ -696,7 +702,9 @@ VERTEX_SHADER_CODE
|
|||||||
refprobe2_reflection_normal_blend.a = blend;
|
refprobe2_reflection_normal_blend.a = blend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //USE_REFLECTION_PROBE2
|
#endif //USE_REFLECTION_PROBE2
|
||||||
@ -819,8 +827,9 @@ uniform highp sampler2D depth_texture; //texunit:-4
|
|||||||
#ifdef USE_VERTEX_LIGHTING
|
#ifdef USE_VERTEX_LIGHTING
|
||||||
|
|
||||||
varying mediump vec4 refprobe1_reflection_normal_blend;
|
varying mediump vec4 refprobe1_reflection_normal_blend;
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
varying mediump vec3 refprobe1_ambient_normal;
|
varying mediump vec3 refprobe1_ambient_normal;
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -845,8 +854,9 @@ uniform vec4 refprobe1_ambient;
|
|||||||
#ifdef USE_VERTEX_LIGHTING
|
#ifdef USE_VERTEX_LIGHTING
|
||||||
|
|
||||||
varying mediump vec4 refprobe2_reflection_normal_blend;
|
varying mediump vec4 refprobe2_reflection_normal_blend;
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
varying mediump vec3 refprobe2_ambient_normal;
|
varying mediump vec3 refprobe2_ambient_normal;
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -873,7 +883,9 @@ uniform vec4 refprobe2_ambient;
|
|||||||
void reflection_process(samplerCube reflection_map,
|
void reflection_process(samplerCube reflection_map,
|
||||||
#ifdef USE_VERTEX_LIGHTING
|
#ifdef USE_VERTEX_LIGHTING
|
||||||
vec3 ref_normal,
|
vec3 ref_normal,
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
vec3 amb_normal,
|
vec3 amb_normal,
|
||||||
|
#endif
|
||||||
float ref_blend,
|
float ref_blend,
|
||||||
|
|
||||||
#else //no vertex lighting
|
#else //no vertex lighting
|
||||||
@ -936,6 +948,8 @@ void reflection_process(samplerCube reflection_map,
|
|||||||
|
|
||||||
reflection_accum += reflection;
|
reflection_accum += reflection;
|
||||||
|
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
|
|
||||||
vec4 ambient_out;
|
vec4 ambient_out;
|
||||||
#ifndef USE_VERTEX_LIGHTING
|
#ifndef USE_VERTEX_LIGHTING
|
||||||
|
|
||||||
@ -951,10 +965,84 @@ void reflection_process(samplerCube reflection_map,
|
|||||||
ambient_out.a = blend;
|
ambient_out.a = blend;
|
||||||
ambient_out.rgb *= blend;
|
ambient_out.rgb *= blend;
|
||||||
ambient_accum += ambient_out;
|
ambient_accum += ambient_out;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //use refprobe 1 or 2
|
#endif //use refprobe 1 or 2
|
||||||
|
|
||||||
|
#ifdef USE_LIGHTMAP
|
||||||
|
uniform mediump sampler2D lightmap; //texunit:-4
|
||||||
|
uniform mediump float lightmap_energy;
|
||||||
|
|
||||||
|
#if defined(USE_LIGHTMAP_FILTER_BICUBIC)
|
||||||
|
uniform mediump vec2 lightmap_texture_size;
|
||||||
|
|
||||||
|
// w0, w1, w2, and w3 are the four cubic B-spline basis functions
|
||||||
|
float w0(float a) {
|
||||||
|
return (1.0 / 6.0) * (a * (a * (-a + 3.0) - 3.0) + 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float w1(float a) {
|
||||||
|
return (1.0 / 6.0) * (a * a * (3.0 * a - 6.0) + 4.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float w2(float a) {
|
||||||
|
return (1.0 / 6.0) * (a * (a * (-3.0 * a + 3.0) + 3.0) + 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float w3(float a) {
|
||||||
|
return (1.0 / 6.0) * (a * a * a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// g0 and g1 are the two amplitude functions
|
||||||
|
float g0(float a) {
|
||||||
|
return w0(a) + w1(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
float g1(float a) {
|
||||||
|
return w2(a) + w3(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// h0 and h1 are the two offset functions
|
||||||
|
float h0(float a) {
|
||||||
|
return -1.0 + w1(a) / (w0(a) + w1(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
float h1(float a) {
|
||||||
|
return 1.0 + w3(a) / (w2(a) + w3(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 texture2D_bicubic(sampler2D tex, vec2 uv) {
|
||||||
|
vec2 texel_size = vec2(1.0) / lightmap_texture_size;
|
||||||
|
|
||||||
|
uv = uv * lightmap_texture_size + vec2(0.5);
|
||||||
|
|
||||||
|
vec2 iuv = floor(uv);
|
||||||
|
vec2 fuv = fract(uv);
|
||||||
|
|
||||||
|
float g0x = g0(fuv.x);
|
||||||
|
float g1x = g1(fuv.x);
|
||||||
|
float h0x = h0(fuv.x);
|
||||||
|
float h1x = h1(fuv.x);
|
||||||
|
float h0y = h0(fuv.y);
|
||||||
|
float h1y = h1(fuv.y);
|
||||||
|
|
||||||
|
vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5)) * texel_size;
|
||||||
|
vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5)) * texel_size;
|
||||||
|
vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5)) * texel_size;
|
||||||
|
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5)) * texel_size;
|
||||||
|
|
||||||
|
return (g0(fuv.y) * (g0x * texture2D(tex, p0) + g1x * texture2D(tex, p1))) +
|
||||||
|
(g1(fuv.y) * (g0x * texture2D(tex, p2) + g1x * texture2D(tex, p3)));
|
||||||
|
}
|
||||||
|
#endif //USE_LIGHTMAP_FILTER_BICUBIC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LIGHTMAP_CAPTURE
|
||||||
|
uniform mediump vec4 lightmap_captures[12];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_RADIANCE_MAP
|
#ifdef USE_RADIANCE_MAP
|
||||||
|
|
||||||
uniform samplerCube radiance_map; // texunit:-2
|
uniform samplerCube radiance_map; // texunit:-2
|
||||||
@ -1064,7 +1152,7 @@ varying vec4 color_interp;
|
|||||||
varying vec2 uv_interp;
|
varying vec2 uv_interp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_UV2_INTERP)
|
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
|
||||||
varying vec2 uv2_interp;
|
varying vec2 uv2_interp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1666,6 +1754,7 @@ FRAGMENT_SHADER_CODE
|
|||||||
|
|
||||||
specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
|
specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
|
||||||
specular_light *= horizon * horizon;
|
specular_light *= horizon * horizon;
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
{
|
{
|
||||||
vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
|
vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
|
||||||
vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy;
|
vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy;
|
||||||
@ -1673,6 +1762,7 @@ FRAGMENT_SHADER_CODE
|
|||||||
|
|
||||||
ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
|
ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -1693,7 +1783,9 @@ FRAGMENT_SHADER_CODE
|
|||||||
reflection_process(reflection_probe1,
|
reflection_process(reflection_probe1,
|
||||||
#ifdef USE_VERTEX_LIGHTING
|
#ifdef USE_VERTEX_LIGHTING
|
||||||
refprobe1_reflection_normal_blend.rgb,
|
refprobe1_reflection_normal_blend.rgb,
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
refprobe1_ambient_normal,
|
refprobe1_ambient_normal,
|
||||||
|
#endif
|
||||||
refprobe1_reflection_normal_blend.a,
|
refprobe1_reflection_normal_blend.a,
|
||||||
#else
|
#else
|
||||||
normal, vertex_interp, refprobe1_local_matrix,
|
normal, vertex_interp, refprobe1_local_matrix,
|
||||||
@ -1709,7 +1801,9 @@ FRAGMENT_SHADER_CODE
|
|||||||
reflection_process(reflection_probe2,
|
reflection_process(reflection_probe2,
|
||||||
#ifdef USE_VERTEX_LIGHTING
|
#ifdef USE_VERTEX_LIGHTING
|
||||||
refprobe2_reflection_normal_blend.rgb,
|
refprobe2_reflection_normal_blend.rgb,
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
refprobe2_ambient_normal,
|
refprobe2_ambient_normal,
|
||||||
|
#endif
|
||||||
refprobe2_reflection_normal_blend.a,
|
refprobe2_reflection_normal_blend.a,
|
||||||
#else
|
#else
|
||||||
normal, vertex_interp, refprobe2_local_matrix,
|
normal, vertex_interp, refprobe2_local_matrix,
|
||||||
@ -1724,9 +1818,11 @@ FRAGMENT_SHADER_CODE
|
|||||||
specular_light = reflection_accum.rgb / reflection_accum.a;
|
specular_light = reflection_accum.rgb / reflection_accum.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_LIGHTMAP
|
||||||
if (ambient_accum.a > 0.0) {
|
if (ambient_accum.a > 0.0) {
|
||||||
ambient_light = ambient_accum.rgb / ambient_accum.a;
|
ambient_light = ambient_accum.rgb / ambient_accum.a;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
|
#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
|
||||||
|
|
||||||
@ -1750,6 +1846,51 @@ FRAGMENT_SHADER_CODE
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_LIGHTMAP
|
||||||
|
//ambient light will come entirely from lightmap is lightmap is used
|
||||||
|
#if defined(USE_LIGHTMAP_FILTER_BICUBIC)
|
||||||
|
ambient_light = texture2D_bicubic(lightmap, uv2_interp).rgb * lightmap_energy;
|
||||||
|
#else
|
||||||
|
ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LIGHTMAP_CAPTURE
|
||||||
|
{
|
||||||
|
vec3 cone_dirs[12];
|
||||||
|
cone_dirs[0] = vec3(0.0, 0.0, 1.0);
|
||||||
|
cone_dirs[1] = vec3(0.866025, 0.0, 0.5);
|
||||||
|
cone_dirs[2] = vec3(0.267617, 0.823639, 0.5);
|
||||||
|
cone_dirs[3] = vec3(-0.700629, 0.509037, 0.5);
|
||||||
|
cone_dirs[4] = vec3(-0.700629, -0.509037, 0.5);
|
||||||
|
cone_dirs[5] = vec3(0.267617, -0.823639, 0.5);
|
||||||
|
cone_dirs[6] = vec3(0.0, 0.0, -1.0);
|
||||||
|
cone_dirs[7] = vec3(0.866025, 0.0, -0.5);
|
||||||
|
cone_dirs[8] = vec3(0.267617, 0.823639, -0.5);
|
||||||
|
cone_dirs[9] = vec3(-0.700629, 0.509037, -0.5);
|
||||||
|
cone_dirs[10] = vec3(-0.700629, -0.509037, -0.5);
|
||||||
|
cone_dirs[11] = vec3(0.267617, -0.823639, -0.5);
|
||||||
|
|
||||||
|
vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz;
|
||||||
|
vec4 captured = vec4(0.0);
|
||||||
|
float sum = 0.0;
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect
|
||||||
|
captured += lightmap_captures[i] * amount;
|
||||||
|
sum += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
captured /= sum;
|
||||||
|
|
||||||
|
// Alpha channel is used to indicate if dynamic objects keep the environment lighting
|
||||||
|
if (lightmap_captures[0].a > 0.5) {
|
||||||
|
ambient_light += captured.rgb;
|
||||||
|
} else {
|
||||||
|
ambient_light = captured.rgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //BASE PASS
|
#endif //BASE PASS
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -572,6 +572,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
|||||||
_initial_set("editors/3d/default_z_near", 0.05);
|
_initial_set("editors/3d/default_z_near", 0.05);
|
||||||
_initial_set("editors/3d/default_z_far", 500.0);
|
_initial_set("editors/3d/default_z_far", 500.0);
|
||||||
|
|
||||||
|
_initial_set("editors/3d/lightmap_baking_number_of_cpu_threads", 0);
|
||||||
|
hints["editors/3d/lightmap_baking_number_of_cpu_threads"] = PropertyInfo(Variant::INT, "editors/3d/lightmap_baking_number_of_cpu_threads", PROPERTY_HINT_RANGE, "-2,128,1", PROPERTY_USAGE_DEFAULT);
|
||||||
|
|
||||||
// 3D: Navigation
|
// 3D: Navigation
|
||||||
_initial_set("editors/3d/navigation/navigation_scheme", 0);
|
_initial_set("editors/3d/navigation/navigation_scheme", 0);
|
||||||
_initial_set("editors/3d/navigation/invert_y_axis", false);
|
_initial_set("editors/3d/navigation/invert_y_axis", false);
|
||||||
|
@ -204,6 +204,10 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,6 +285,23 @@ void MeshInstanceEditor::_menu_option(int p_option) {
|
|||||||
case MENU_OPTION_CREATE_OUTLINE_MESH: {
|
case MENU_OPTION_CREATE_OUTLINE_MESH: {
|
||||||
outline_dialog->popup_centered(Vector2(200, 90));
|
outline_dialog->popup_centered(Vector2(200, 90));
|
||||||
} break;
|
} break;
|
||||||
|
case MENU_OPTION_CREATE_UV2: {
|
||||||
|
Ref<ArrayMesh> mesh2 = node->get_mesh();
|
||||||
|
if (!mesh2.is_valid()) {
|
||||||
|
err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh."));
|
||||||
|
err_dialog->popup_centered_minsize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Error err = mesh2->lightmap_unwrap(node->get_global_transform());
|
||||||
|
if (err != OK) {
|
||||||
|
err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?"));
|
||||||
|
err_dialog->popup_centered_minsize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
} break;
|
||||||
case MENU_OPTION_DEBUG_UV1: {
|
case MENU_OPTION_DEBUG_UV1: {
|
||||||
Ref<Mesh> mesh2 = node->get_mesh();
|
Ref<Mesh> mesh2 = node->get_mesh();
|
||||||
if (!mesh2.is_valid()) {
|
if (!mesh2.is_valid()) {
|
||||||
@ -481,6 +498,7 @@ MeshInstanceEditor::MeshInstanceEditor() {
|
|||||||
options->get_popup()->add_separator();
|
options->get_popup()->add_separator();
|
||||||
options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1);
|
options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1);
|
||||||
options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2);
|
options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2);
|
||||||
|
options->get_popup()->add_item(TTR("Unwrap UV2 for Lightmap/AO"), MENU_OPTION_CREATE_UV2);
|
||||||
|
|
||||||
options->get_popup()->connect("id_pressed", this, "_menu_option");
|
options->get_popup()->connect("id_pressed", this, "_menu_option");
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ class MeshInstanceEditor : public Control {
|
|||||||
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
|
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
|
||||||
MENU_OPTION_CREATE_NAVMESH,
|
MENU_OPTION_CREATE_NAVMESH,
|
||||||
MENU_OPTION_CREATE_OUTLINE_MESH,
|
MENU_OPTION_CREATE_OUTLINE_MESH,
|
||||||
|
MENU_OPTION_CREATE_UV2,
|
||||||
MENU_OPTION_DEBUG_UV1,
|
MENU_OPTION_DEBUG_UV1,
|
||||||
MENU_OPTION_DEBUG_UV2,
|
MENU_OPTION_DEBUG_UV2,
|
||||||
};
|
};
|
||||||
|
@ -257,6 +257,23 @@ Ref<Material> GeometryInstance::get_material_overlay() const {
|
|||||||
return material_overlay;
|
return material_overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeometryInstance::set_generate_lightmap(bool p_enabled) {
|
||||||
|
generate_lightmap = p_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeometryInstance::get_generate_lightmap() {
|
||||||
|
return generate_lightmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeometryInstance::set_lightmap_scale(LightmapScale p_scale) {
|
||||||
|
ERR_FAIL_INDEX(p_scale, LIGHTMAP_SCALE_MAX);
|
||||||
|
lightmap_scale = p_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryInstance::LightmapScale GeometryInstance::get_lightmap_scale() const {
|
||||||
|
return lightmap_scale;
|
||||||
|
}
|
||||||
|
|
||||||
void GeometryInstance::_notification(int p_what) {
|
void GeometryInstance::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,6 +334,12 @@ void GeometryInstance::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting);
|
ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting);
|
||||||
ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting);
|
ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_generate_lightmap", "enabled"), &GeometryInstance::set_generate_lightmap);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_generate_lightmap"), &GeometryInstance::get_generate_lightmap);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_lightmap_scale", "scale"), &GeometryInstance::set_lightmap_scale);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_lightmap_scale"), &GeometryInstance::get_lightmap_scale);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance::set_extra_cull_margin);
|
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance::set_extra_cull_margin);
|
||||||
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
|
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
|
||||||
|
|
||||||
@ -330,13 +353,25 @@ void GeometryInstance::_bind_methods() {
|
|||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
|
ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
|
||||||
|
|
||||||
|
ADD_GROUP("Baked Light", "");
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT);
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_lightmap"), "set_generate_lightmap", "get_generate_lightmap");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "lightmap_scale", PROPERTY_HINT_ENUM, "1x,2x,4x,8x"), "set_lightmap_scale", "get_lightmap_scale");
|
||||||
|
|
||||||
//ADD_SIGNAL( MethodInfo("visibility_changed"));
|
//ADD_SIGNAL( MethodInfo("visibility_changed"));
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_1X);
|
||||||
|
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_2X);
|
||||||
|
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_4X);
|
||||||
|
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_8X);
|
||||||
|
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_MAX);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
|
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON);
|
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON);
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
|
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
|
||||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
|
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT);
|
||||||
BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
||||||
BIND_ENUM_CONSTANT(FLAG_MAX);
|
BIND_ENUM_CONSTANT(FLAG_MAX);
|
||||||
}
|
}
|
||||||
@ -348,4 +383,6 @@ GeometryInstance::GeometryInstance() {
|
|||||||
|
|
||||||
shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
|
shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
|
||||||
extra_cull_margin = 0;
|
extra_cull_margin = 0;
|
||||||
|
generate_lightmap = true;
|
||||||
|
lightmap_scale = LightmapScale::LIGHTMAP_SCALE_1X;
|
||||||
}
|
}
|
||||||
|
@ -98,10 +98,19 @@ class GeometryInstance : public VisualInstance {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Flags {
|
||||||
|
FLAG_USE_BAKED_LIGHT = RS::INSTANCE_FLAG_USE_BAKED_LIGHT,
|
||||||
FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
|
FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
|
||||||
FLAG_MAX = RS::INSTANCE_FLAG_MAX,
|
FLAG_MAX = RS::INSTANCE_FLAG_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LightmapScale {
|
||||||
|
LIGHTMAP_SCALE_1X,
|
||||||
|
LIGHTMAP_SCALE_2X,
|
||||||
|
LIGHTMAP_SCALE_4X,
|
||||||
|
LIGHTMAP_SCALE_8X,
|
||||||
|
LIGHTMAP_SCALE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
enum ShadowCastingSetting {
|
enum ShadowCastingSetting {
|
||||||
SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF,
|
SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF,
|
||||||
SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON,
|
SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON,
|
||||||
@ -111,6 +120,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool flags[FLAG_MAX];
|
bool flags[FLAG_MAX];
|
||||||
|
bool generate_lightmap;
|
||||||
|
LightmapScale lightmap_scale;
|
||||||
ShadowCastingSetting shadow_casting_setting;
|
ShadowCastingSetting shadow_casting_setting;
|
||||||
Ref<Material> material_override;
|
Ref<Material> material_override;
|
||||||
Ref<Material> material_overlay;
|
Ref<Material> material_overlay;
|
||||||
@ -128,6 +139,12 @@ public:
|
|||||||
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
|
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
|
||||||
ShadowCastingSetting get_cast_shadows_setting() const;
|
ShadowCastingSetting get_cast_shadows_setting() const;
|
||||||
|
|
||||||
|
void set_generate_lightmap(bool p_enabled);
|
||||||
|
bool get_generate_lightmap();
|
||||||
|
|
||||||
|
void set_lightmap_scale(LightmapScale p_scale);
|
||||||
|
LightmapScale get_lightmap_scale() const;
|
||||||
|
|
||||||
virtual void set_material_override(const Ref<Material> &p_material);
|
virtual void set_material_override(const Ref<Material> &p_material);
|
||||||
Ref<Material> get_material_override() const;
|
Ref<Material> get_material_override() const;
|
||||||
|
|
||||||
@ -143,6 +160,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(GeometryInstance::Flags);
|
VARIANT_ENUM_CAST(GeometryInstance::Flags);
|
||||||
|
VARIANT_ENUM_CAST(GeometryInstance::LightmapScale);
|
||||||
VARIANT_ENUM_CAST(GeometryInstance::ShadowCastingSetting);
|
VARIANT_ENUM_CAST(GeometryInstance::ShadowCastingSetting);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -594,9 +594,21 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
|
|||||||
return newmesh;
|
return newmesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::set_lightmap_size_hint(const Vector2i &p_size) {
|
||||||
|
lightmap_size_hint = p_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size2i Mesh::get_lightmap_size_hint() const {
|
||||||
|
return lightmap_size_hint;
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::_bind_methods() {
|
void Mesh::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_aabb"), &Mesh::get_aabb);
|
ClassDB::bind_method(D_METHOD("get_aabb"), &Mesh::get_aabb);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint);
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint");
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count);
|
ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count);
|
||||||
ClassDB::bind_method(D_METHOD("surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays);
|
ClassDB::bind_method(D_METHOD("surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays);
|
||||||
ClassDB::bind_method(D_METHOD("surface_get_blend_shape_arrays", "surf_idx"), &Mesh::surface_get_blend_shape_arrays);
|
ClassDB::bind_method(D_METHOD("surface_get_blend_shape_arrays", "surf_idx"), &Mesh::surface_get_blend_shape_arrays);
|
||||||
|
@ -46,6 +46,7 @@ class Mesh : public Resource {
|
|||||||
|
|
||||||
mutable Ref<TriangleMesh> triangle_mesh; //cached
|
mutable Ref<TriangleMesh> triangle_mesh; //cached
|
||||||
mutable Vector<Vector3> debug_lines;
|
mutable Vector<Vector3> debug_lines;
|
||||||
|
Size2i lightmap_size_hint;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
@ -169,6 +170,9 @@ public:
|
|||||||
virtual AABB get_aabb() const = 0;
|
virtual AABB get_aabb() const = 0;
|
||||||
virtual void set_storage_mode(StorageMode p_storage_mode);
|
virtual void set_storage_mode(StorageMode p_storage_mode);
|
||||||
|
|
||||||
|
void set_lightmap_size_hint(const Vector2i &p_size);
|
||||||
|
Size2i get_lightmap_size_hint() const;
|
||||||
|
|
||||||
void clear_cache() const;
|
void clear_cache() const;
|
||||||
|
|
||||||
typedef Vector<PoolVector<Vector3>> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, int p_max_convex_hulls, Vector<PoolVector<uint32_t>> *r_convex_indices);
|
typedef Vector<PoolVector<Vector3>> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, int p_max_convex_hulls, Vector<PoolVector<uint32_t>> *r_convex_indices);
|
||||||
|
@ -118,6 +118,7 @@ public:
|
|||||||
bool mirror : 1;
|
bool mirror : 1;
|
||||||
bool receive_shadows : 1;
|
bool receive_shadows : 1;
|
||||||
bool visible : 1;
|
bool visible : 1;
|
||||||
|
bool baked_light : 1; //this flag is only to know if it actually did use baked light
|
||||||
bool redraw_if_visible : 1;
|
bool redraw_if_visible : 1;
|
||||||
|
|
||||||
bool on_interpolate_list : 1;
|
bool on_interpolate_list : 1;
|
||||||
@ -134,6 +135,12 @@ public:
|
|||||||
|
|
||||||
SelfList<InstanceBase> dependency_item;
|
SelfList<InstanceBase> dependency_item;
|
||||||
|
|
||||||
|
InstanceBase *lightmap_capture;
|
||||||
|
RID lightmap;
|
||||||
|
Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader
|
||||||
|
int lightmap_slice;
|
||||||
|
Rect2 lightmap_uv_rect;
|
||||||
|
|
||||||
virtual void base_removed() = 0;
|
virtual void base_removed() = 0;
|
||||||
virtual void base_changed(bool p_aabb, bool p_materials) = 0;
|
virtual void base_changed(bool p_aabb, bool p_materials) = 0;
|
||||||
InstanceBase() :
|
InstanceBase() :
|
||||||
@ -144,7 +151,11 @@ public:
|
|||||||
visible = true;
|
visible = true;
|
||||||
depth_layer = 0;
|
depth_layer = 0;
|
||||||
layer_mask = 1;
|
layer_mask = 1;
|
||||||
|
baked_light = false;
|
||||||
redraw_if_visible = false;
|
redraw_if_visible = false;
|
||||||
|
lightmap_capture = nullptr;
|
||||||
|
lightmap_slice = -1;
|
||||||
|
lightmap_uv_rect = Rect2(0, 0, 1, 1);
|
||||||
on_interpolate_list = false;
|
on_interpolate_list = false;
|
||||||
on_interpolate_transform_list = false;
|
on_interpolate_transform_list = false;
|
||||||
interpolated = true;
|
interpolated = true;
|
||||||
@ -504,6 +515,33 @@ public:
|
|||||||
virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
||||||
virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
|
||||||
|
|
||||||
|
/* LIGHTMAP CAPTURE */
|
||||||
|
|
||||||
|
struct LightmapCaptureOctree {
|
||||||
|
enum {
|
||||||
|
CHILD_EMPTY = 0xFFFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t light[6][3]; //anisotropic light
|
||||||
|
float alpha;
|
||||||
|
uint32_t children[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual RID lightmap_capture_create() = 0;
|
||||||
|
virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0;
|
||||||
|
virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) = 0;
|
||||||
|
virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0;
|
||||||
|
virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0;
|
||||||
|
virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0;
|
||||||
|
virtual float lightmap_capture_get_energy(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_interior(RID p_capture, bool p_interior) = 0;
|
||||||
|
virtual bool lightmap_capture_is_interior(RID p_capture) const = 0;
|
||||||
|
virtual const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const = 0;
|
||||||
|
|
||||||
/* RENDER TARGET */
|
/* RENDER TARGET */
|
||||||
|
|
||||||
enum RenderTargetFlags {
|
enum RenderTargetFlags {
|
||||||
|
@ -359,6 +359,27 @@ public:
|
|||||||
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||||
BIND2(reflection_probe_set_resolution, RID, int)
|
BIND2(reflection_probe_set_resolution, RID, int)
|
||||||
|
|
||||||
|
/* LIGHTMAP CAPTURE */
|
||||||
|
|
||||||
|
BIND0R(RID, lightmap_capture_create)
|
||||||
|
|
||||||
|
BIND2(lightmap_capture_set_bounds, RID, const AABB &)
|
||||||
|
BIND1RC(AABB, lightmap_capture_get_bounds, RID)
|
||||||
|
|
||||||
|
BIND2(lightmap_capture_set_octree, RID, const PoolVector<uint8_t> &)
|
||||||
|
BIND1RC(PoolVector<uint8_t>, lightmap_capture_get_octree, RID)
|
||||||
|
|
||||||
|
BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &)
|
||||||
|
BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID)
|
||||||
|
BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int)
|
||||||
|
BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID)
|
||||||
|
|
||||||
|
BIND2(lightmap_capture_set_energy, RID, float)
|
||||||
|
BIND1RC(float, lightmap_capture_get_energy, RID)
|
||||||
|
|
||||||
|
BIND2(lightmap_capture_set_interior, RID, bool)
|
||||||
|
BIND1RC(bool, lightmap_capture_is_interior, RID)
|
||||||
|
|
||||||
#undef BINDBASE
|
#undef BINDBASE
|
||||||
//from now on, calls forwarded to this singleton
|
//from now on, calls forwarded to this singleton
|
||||||
#define BINDBASE RSG::scene
|
#define BINDBASE RSG::scene
|
||||||
@ -485,6 +506,7 @@ public:
|
|||||||
BIND3(instance_set_blend_shape_weight, RID, int, float)
|
BIND3(instance_set_blend_shape_weight, RID, int, float)
|
||||||
BIND3(instance_set_surface_material, RID, int, RID)
|
BIND3(instance_set_surface_material, RID, int, RID)
|
||||||
BIND2(instance_set_visible, RID, bool)
|
BIND2(instance_set_visible, RID, bool)
|
||||||
|
BIND5(instance_set_use_lightmap, RID, RID, RID, int, const Rect2 &)
|
||||||
|
|
||||||
BIND2(instance_set_custom_aabb, RID, AABB)
|
BIND2(instance_set_custom_aabb, RID, AABB)
|
||||||
|
|
||||||
|
@ -286,6 +286,18 @@ void *RenderingServerScene::_instance_pair(void *p_self, SpatialPartitionID, Ins
|
|||||||
}
|
}
|
||||||
geom->lighting_dirty = true;
|
geom->lighting_dirty = true;
|
||||||
|
|
||||||
|
return E; //this element should make freeing faster
|
||||||
|
} else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data);
|
||||||
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
|
||||||
|
|
||||||
|
InstanceLightmapCaptureData::PairInfo pinfo;
|
||||||
|
pinfo.geometry = A;
|
||||||
|
pinfo.L = geom->lightmap_captures.push_back(B);
|
||||||
|
|
||||||
|
List<InstanceLightmapCaptureData::PairInfo>::Element *E = lightmap_capture->geometries.push_back(pinfo);
|
||||||
|
((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
|
||||||
|
|
||||||
return E; //this element should make freeing faster
|
return E; //this element should make freeing faster
|
||||||
} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
|
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
|
||||||
@ -339,6 +351,16 @@ void RenderingServerScene::_instance_unpair(void *p_self, SpatialPartitionID, In
|
|||||||
reflection_probe->geometries.erase(E);
|
reflection_probe->geometries.erase(E);
|
||||||
|
|
||||||
geom->reflection_dirty = true;
|
geom->reflection_dirty = true;
|
||||||
|
} else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||||
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data);
|
||||||
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
|
||||||
|
|
||||||
|
List<InstanceLightmapCaptureData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapCaptureData::PairInfo>::Element *>(udata);
|
||||||
|
|
||||||
|
geom->lightmap_captures.erase(E->get().L);
|
||||||
|
lightmap_capture->geometries.erase(E);
|
||||||
|
((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +495,13 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
|
|||||||
reflection_probe_render_list.remove(&reflection_probe->update_list);
|
reflection_probe_render_list.remove(&reflection_probe->update_list);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(instance->base_data);
|
||||||
|
//erase dependencies, since no longer a lightmap
|
||||||
|
while (lightmap_capture->users.front()) {
|
||||||
|
instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID(), -1, Rect2(0, 0, 1, 1));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -527,6 +556,11 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
|
|||||||
|
|
||||||
reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base);
|
reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base);
|
||||||
} break;
|
} break;
|
||||||
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData);
|
||||||
|
instance->base_data = lightmap_capture;
|
||||||
|
//lightmap_capture->instance = RSG::scene_render->lightmap_capture_instance_create(p_base);
|
||||||
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
}
|
}
|
||||||
@ -961,6 +995,12 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible)
|
|||||||
instance->scenario->sps->set_pairable(instance, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
|
instance->scenario->sps->set_pairable(instance, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RS::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
if (instance->spatial_partition_id && instance->scenario) {
|
||||||
|
instance->scenario->sps->set_pairable(instance, p_visible, 1 << RS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
// if we haven't called set_pairable, we STILL need to do a collision check
|
// if we haven't called set_pairable, we STILL need to do a collision check
|
||||||
@ -975,6 +1015,36 @@ inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
|
|||||||
return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_IMMEDIATE;
|
return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_IMMEDIATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap, int p_lightmap_slice, const Rect2 &p_lightmap_uv_rect) {
|
||||||
|
Instance *instance = instance_owner.get(p_instance);
|
||||||
|
ERR_FAIL_COND(!instance);
|
||||||
|
|
||||||
|
instance->lightmap = RID();
|
||||||
|
instance->lightmap_slice = -1;
|
||||||
|
instance->lightmap_uv_rect = Rect2(0, 0, 1, 1);
|
||||||
|
instance->baked_light = false;
|
||||||
|
|
||||||
|
if (instance->lightmap_capture) {
|
||||||
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data);
|
||||||
|
lightmap_capture->users.erase(instance);
|
||||||
|
instance->lightmap_capture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_lightmap_instance.is_valid()) {
|
||||||
|
Instance *lightmap_instance = instance_owner.get(p_lightmap_instance);
|
||||||
|
ERR_FAIL_COND(!lightmap_instance);
|
||||||
|
ERR_FAIL_COND(lightmap_instance->base_type != RS::INSTANCE_LIGHTMAP_CAPTURE);
|
||||||
|
instance->lightmap_capture = lightmap_instance;
|
||||||
|
|
||||||
|
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data);
|
||||||
|
lightmap_capture->users.insert(instance);
|
||||||
|
instance->lightmap = p_lightmap;
|
||||||
|
instance->lightmap_slice = p_lightmap_slice;
|
||||||
|
instance->lightmap_uv_rect = p_lightmap_uv_rect;
|
||||||
|
instance->baked_light = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
|
void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
|
||||||
Instance *instance = instance_owner.get(p_instance);
|
Instance *instance = instance_owner.get(p_instance);
|
||||||
ERR_FAIL_COND(!instance);
|
ERR_FAIL_COND(!instance);
|
||||||
@ -1729,6 +1799,13 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
|
|||||||
reflection_probe->reflection_dirty = true;
|
reflection_probe->reflection_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) {
|
||||||
|
InstanceLightmapCaptureData *capture = static_cast<InstanceLightmapCaptureData *>(p_instance->base_data);
|
||||||
|
for (List<InstanceLightmapCaptureData::PairInfo>::Element *E = capture->geometries.front(); E; E = E->next()) {
|
||||||
|
_instance_queue_update(E->get().geometry, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p_instance->aabb.has_no_surface()) {
|
if (p_instance->aabb.has_no_surface()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1743,6 +1820,15 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
|
|||||||
light->make_shadow_dirty();
|
light->make_shadow_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!p_instance->lightmap_capture && geom->lightmap_captures.size()) {
|
||||||
|
//affected by lightmap captures, must update capture info!
|
||||||
|
_update_instance_lightmap_captures(p_instance);
|
||||||
|
} else {
|
||||||
|
if (!p_instance->lightmap_capture_data.empty()) {
|
||||||
|
p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p_instance->mirror = instance_xform->basis.determinant() < 0.0;
|
p_instance->mirror = instance_xform->basis.determinant() < 0.0;
|
||||||
@ -1762,7 +1848,7 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
|
|||||||
uint32_t pairable_mask = 0;
|
uint32_t pairable_mask = 0;
|
||||||
bool pairable = false;
|
bool pairable = false;
|
||||||
|
|
||||||
if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
|
if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) {
|
||||||
pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
|
pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
|
||||||
pairable = true;
|
pairable = true;
|
||||||
}
|
}
|
||||||
@ -1824,6 +1910,10 @@ void RenderingServerScene::_update_instance_aabb(Instance *p_instance) {
|
|||||||
case RenderingServer::INSTANCE_REFLECTION_PROBE: {
|
case RenderingServer::INSTANCE_REFLECTION_PROBE: {
|
||||||
new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
|
new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RenderingServer::INSTANCE_LIGHTMAP_CAPTURE: {
|
||||||
|
new_aabb = RSG::storage->lightmap_capture_get_bounds(p_instance->base);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
}
|
}
|
||||||
@ -1966,6 +2056,254 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
|
|||||||
p_instance->update_materials = false;
|
p_instance->update_materials = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) {
|
||||||
|
static const Vector3 aniso_normal[6] = {
|
||||||
|
Vector3(-1, 0, 0),
|
||||||
|
Vector3(1, 0, 0),
|
||||||
|
Vector3(0, -1, 0),
|
||||||
|
Vector3(0, 1, 0),
|
||||||
|
Vector3(0, 0, -1),
|
||||||
|
Vector3(0, 0, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
int size = 1 << (p_cell_subdiv - 1);
|
||||||
|
|
||||||
|
int clamp_v = size - 1;
|
||||||
|
//first of all, clamp
|
||||||
|
Vector3 pos;
|
||||||
|
pos.x = CLAMP(p_pos.x, 0, clamp_v);
|
||||||
|
pos.y = CLAMP(p_pos.y, 0, clamp_v);
|
||||||
|
pos.z = CLAMP(p_pos.z, 0, clamp_v);
|
||||||
|
|
||||||
|
float level = (p_cell_subdiv - 1) - p_level;
|
||||||
|
|
||||||
|
int target_level;
|
||||||
|
float level_filter;
|
||||||
|
if (level <= 0.0) {
|
||||||
|
level_filter = 0;
|
||||||
|
target_level = 0;
|
||||||
|
} else {
|
||||||
|
target_level = Math::ceil(level);
|
||||||
|
level_filter = target_level - level;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 color[2][8];
|
||||||
|
float alpha[2][8];
|
||||||
|
memset(alpha, 0, sizeof(float) * 2 * 8);
|
||||||
|
|
||||||
|
//find cell at given level first
|
||||||
|
|
||||||
|
for (int c = 0; c < 2; c++) {
|
||||||
|
int current_level = MAX(0, target_level - c);
|
||||||
|
int level_cell_size = (1 << (p_cell_subdiv - 1)) >> current_level;
|
||||||
|
|
||||||
|
for (int n = 0; n < 8; n++) {
|
||||||
|
int x = int(pos.x);
|
||||||
|
int y = int(pos.y);
|
||||||
|
int z = int(pos.z);
|
||||||
|
|
||||||
|
if (n & 1) {
|
||||||
|
x += level_cell_size;
|
||||||
|
}
|
||||||
|
if (n & 2) {
|
||||||
|
y += level_cell_size;
|
||||||
|
}
|
||||||
|
if (n & 4) {
|
||||||
|
z += level_cell_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ofs_x = 0;
|
||||||
|
int ofs_y = 0;
|
||||||
|
int ofs_z = 0;
|
||||||
|
|
||||||
|
x = CLAMP(x, 0, clamp_v);
|
||||||
|
y = CLAMP(y, 0, clamp_v);
|
||||||
|
z = CLAMP(z, 0, clamp_v);
|
||||||
|
|
||||||
|
int half = size / 2;
|
||||||
|
uint32_t cell = 0;
|
||||||
|
for (int i = 0; i < current_level; i++) {
|
||||||
|
const RasterizerStorage::LightmapCaptureOctree *bc = &p_octree[cell];
|
||||||
|
|
||||||
|
int child = 0;
|
||||||
|
if (x >= ofs_x + half) {
|
||||||
|
child |= 1;
|
||||||
|
ofs_x += half;
|
||||||
|
}
|
||||||
|
if (y >= ofs_y + half) {
|
||||||
|
child |= 2;
|
||||||
|
ofs_y += half;
|
||||||
|
}
|
||||||
|
if (z >= ofs_z + half) {
|
||||||
|
child |= 4;
|
||||||
|
ofs_z += half;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell = bc->children[child];
|
||||||
|
if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
half >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell != RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) {
|
||||||
|
alpha[c][n] = p_octree[cell].alpha;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
//anisotropic read light
|
||||||
|
float amount = p_dir.dot(aniso_normal[i]);
|
||||||
|
|
||||||
|
if (amount > 0) {
|
||||||
|
constexpr float ONE_1024TH = 1.0 / 1024.0;
|
||||||
|
color[c][n].x += p_octree[cell].light[i][0] * ONE_1024TH * amount;
|
||||||
|
color[c][n].y += p_octree[cell].light[i][1] * ONE_1024TH * amount;
|
||||||
|
color[c][n].z += p_octree[cell].light[i][2] * ONE_1024TH * amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//print_line("\tlev " + itos(c) + " - " + itos(n) + " alpha: " + rtos(cells[test_cell].alpha) + " col: " + color[c][n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float target_level_size = size >> target_level;
|
||||||
|
Vector3 pos_fract[2];
|
||||||
|
|
||||||
|
float target_level_size_inv = 1.0f / target_level_size;
|
||||||
|
real_t res;
|
||||||
|
res = pos.x * target_level_size_inv;
|
||||||
|
pos_fract[0].x = res - (int)res;
|
||||||
|
res = pos.y * target_level_size_inv;
|
||||||
|
pos_fract[0].y = res - (int)res;
|
||||||
|
res = pos.z * target_level_size_inv;
|
||||||
|
pos_fract[0].z = res - (int)res;
|
||||||
|
|
||||||
|
target_level_size = size >> MAX(0, target_level - 1);
|
||||||
|
|
||||||
|
target_level_size_inv = 1.0f / target_level_size;
|
||||||
|
res = pos.x * target_level_size_inv;
|
||||||
|
pos_fract[1].x = res - (int)res;
|
||||||
|
res = pos.y * target_level_size_inv;
|
||||||
|
pos_fract[1].y = res - (int)res;
|
||||||
|
res = pos.z * target_level_size_inv;
|
||||||
|
pos_fract[1].z = res - (int)res;
|
||||||
|
|
||||||
|
float alpha_interp[2];
|
||||||
|
Vector3 color_interp[2];
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
Vector3 color_x00 = color[i][0].linear_interpolate(color[i][1], pos_fract[i].x);
|
||||||
|
Vector3 color_xy0 = color[i][2].linear_interpolate(color[i][3], pos_fract[i].x);
|
||||||
|
Vector3 blend_z0 = color_x00.linear_interpolate(color_xy0, pos_fract[i].y);
|
||||||
|
|
||||||
|
Vector3 color_x0z = color[i][4].linear_interpolate(color[i][5], pos_fract[i].x);
|
||||||
|
Vector3 color_xyz = color[i][6].linear_interpolate(color[i][7], pos_fract[i].x);
|
||||||
|
Vector3 blend_z1 = color_x0z.linear_interpolate(color_xyz, pos_fract[i].y);
|
||||||
|
|
||||||
|
color_interp[i] = blend_z0.linear_interpolate(blend_z1, pos_fract[i].z);
|
||||||
|
|
||||||
|
float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x);
|
||||||
|
float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x);
|
||||||
|
float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y);
|
||||||
|
|
||||||
|
float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x);
|
||||||
|
float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x);
|
||||||
|
float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y);
|
||||||
|
|
||||||
|
alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z);
|
||||||
|
}
|
||||||
|
|
||||||
|
r_color = color_interp[0].linear_interpolate(color_interp[1], level_filter);
|
||||||
|
r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter);
|
||||||
|
|
||||||
|
//print_line("pos: " + p_posf + " level " + rtos(p_level) + " down to " + itos(target_level) + "." + rtos(level_filter) + " color " + r_color + " alpha " + rtos(r_alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ static Color _light_capture_voxel_cone_trace(const RasterizerStorage::LightmapCaptureOctree *p_octree, const Vector3 &p_pos, const Vector3 &p_dir, float p_aperture, int p_cell_subdiv) {
|
||||||
|
float bias = 0.0; //no need for bias here
|
||||||
|
float max_distance = (Vector3(1, 1, 1) * (1 << (p_cell_subdiv - 1))).length();
|
||||||
|
|
||||||
|
float dist = bias;
|
||||||
|
float alpha = 0.0;
|
||||||
|
Vector3 color;
|
||||||
|
|
||||||
|
Vector3 scolor;
|
||||||
|
float salpha;
|
||||||
|
|
||||||
|
while (dist < max_distance && alpha < 0.95) {
|
||||||
|
float diameter = MAX(1.0, 2.0 * p_aperture * dist);
|
||||||
|
_light_capture_sample_octree(p_octree, p_cell_subdiv, p_pos + dist * p_dir, p_dir, log2(diameter), scolor, salpha);
|
||||||
|
float a = (1.0 - alpha);
|
||||||
|
color += scolor * a;
|
||||||
|
alpha += a * salpha;
|
||||||
|
dist += diameter * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Color(color.x, color.y, color.z, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) {
|
||||||
|
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
|
||||||
|
|
||||||
|
static const Vector3 cone_traces[12] = {
|
||||||
|
Vector3(0, 0, 1),
|
||||||
|
Vector3(0.866025, 0, 0.5),
|
||||||
|
Vector3(0.267617, 0.823639, 0.5),
|
||||||
|
Vector3(-0.700629, 0.509037, 0.5),
|
||||||
|
Vector3(-0.700629, -0.509037, 0.5),
|
||||||
|
Vector3(0.267617, -0.823639, 0.5),
|
||||||
|
Vector3(0, 0, -1),
|
||||||
|
Vector3(0.866025, 0, -0.5),
|
||||||
|
Vector3(0.267617, 0.823639, -0.5),
|
||||||
|
Vector3(-0.700629, 0.509037, -0.5),
|
||||||
|
Vector3(-0.700629, -0.509037, -0.5),
|
||||||
|
Vector3(0.267617, -0.823639, -0.5)
|
||||||
|
};
|
||||||
|
|
||||||
|
float cone_aperture = 0.577; // tan(angle) 60 degrees
|
||||||
|
|
||||||
|
if (p_instance->lightmap_capture_data.empty()) {
|
||||||
|
p_instance->lightmap_capture_data.resize(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
//print_line("update captures for pos: " + p_instance->transform.origin);
|
||||||
|
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
new (&p_instance->lightmap_capture_data.ptrw()[i]) Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool interior = true;
|
||||||
|
//this could use some sort of blending..
|
||||||
|
for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
|
||||||
|
const PoolVector<RasterizerStorage::LightmapCaptureOctree> *octree = RSG::storage->lightmap_capture_get_octree_ptr(E->get()->base);
|
||||||
|
//print_line("octree size: " + itos(octree->size()));
|
||||||
|
if (octree->size() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Transform to_cell_xform = RSG::storage->lightmap_capture_get_octree_cell_transform(E->get()->base);
|
||||||
|
int cell_subdiv = RSG::storage->lightmap_capture_get_octree_cell_subdiv(E->get()->base);
|
||||||
|
to_cell_xform = to_cell_xform * E->get()->transform.affine_inverse();
|
||||||
|
|
||||||
|
PoolVector<RasterizerStorage::LightmapCaptureOctree>::Read octree_r = octree->read();
|
||||||
|
|
||||||
|
Vector3 pos = to_cell_xform.xform(p_instance->transform.origin);
|
||||||
|
|
||||||
|
const float capture_energy = RSG::storage->lightmap_capture_get_energy(E->get()->base);
|
||||||
|
interior = interior && RSG::storage->lightmap_capture_is_interior(E->get()->base);
|
||||||
|
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized();
|
||||||
|
Color capture = _light_capture_voxel_cone_trace(octree_r.ptr(), pos, dir, cone_aperture, cell_subdiv);
|
||||||
|
capture.r *= capture_energy;
|
||||||
|
capture.g *= capture_energy;
|
||||||
|
capture.b *= capture_energy;
|
||||||
|
p_instance->lightmap_capture_data.write[i] += capture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p_instance->lightmap_capture_data.write[0].a = interior ? 0.0f : 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers) {
|
bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers) {
|
||||||
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
|
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
|
||||||
|
|
||||||
@ -2846,6 +3184,7 @@ bool RenderingServerScene::free(RID p_rid) {
|
|||||||
|
|
||||||
_interpolation_data.notify_free_instance(p_rid, *instance);
|
_interpolation_data.notify_free_instance(p_rid, *instance);
|
||||||
|
|
||||||
|
instance_set_use_lightmap(p_rid, RID(), RID(), -1, Rect2(0, 0, 1, 1));
|
||||||
instance_set_scenario(p_rid, RID());
|
instance_set_scenario(p_rid, RID());
|
||||||
instance_set_base(p_rid, RID());
|
instance_set_base(p_rid, RID());
|
||||||
instance_geometry_set_material_override(p_rid, RID());
|
instance_geometry_set_material_override(p_rid, RID());
|
||||||
|
@ -418,6 +418,8 @@ public:
|
|||||||
List<Instance *> reflection_probes;
|
List<Instance *> reflection_probes;
|
||||||
bool reflection_dirty;
|
bool reflection_dirty;
|
||||||
|
|
||||||
|
List<Instance *> lightmap_captures;
|
||||||
|
|
||||||
InstanceGeometryData() {
|
InstanceGeometryData() {
|
||||||
lighting_dirty = true;
|
lighting_dirty = true;
|
||||||
reflection_dirty = true;
|
reflection_dirty = true;
|
||||||
@ -521,6 +523,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InstanceLightmapCaptureData : public InstanceBaseData {
|
||||||
|
struct PairInfo {
|
||||||
|
List<Instance *>::Element *L; //iterator in geometry
|
||||||
|
Instance *geometry;
|
||||||
|
};
|
||||||
|
List<PairInfo> geometries;
|
||||||
|
|
||||||
|
RBSet<Instance *> users;
|
||||||
|
|
||||||
|
InstanceLightmapCaptureData() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
int instance_cull_count;
|
int instance_cull_count;
|
||||||
Instance *instance_cull_result[MAX_INSTANCE_CULL];
|
Instance *instance_cull_result[MAX_INSTANCE_CULL];
|
||||||
Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
|
Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
|
||||||
@ -547,6 +562,7 @@ public:
|
|||||||
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
|
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
|
||||||
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
|
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
|
||||||
virtual void instance_set_visible(RID p_instance, bool p_visible);
|
virtual void instance_set_visible(RID p_instance, bool p_visible);
|
||||||
|
virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap, int p_lightmap_slice, const Rect2 &p_lightmap_uv_rect);
|
||||||
|
|
||||||
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
|
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
|
||||||
|
|
||||||
@ -753,6 +769,7 @@ public:
|
|||||||
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
|
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
|
||||||
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
||||||
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
||||||
|
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
|
||||||
|
|
||||||
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers = 0xFFFFFF);
|
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers = 0xFFFFFF);
|
||||||
|
|
||||||
|
@ -153,6 +153,7 @@ void RenderingServerWrapMT::finish() {
|
|||||||
omni_light_free_cached_ids();
|
omni_light_free_cached_ids();
|
||||||
spot_light_free_cached_ids();
|
spot_light_free_cached_ids();
|
||||||
reflection_probe_free_cached_ids();
|
reflection_probe_free_cached_ids();
|
||||||
|
lightmap_capture_free_cached_ids();
|
||||||
camera_free_cached_ids();
|
camera_free_cached_ids();
|
||||||
viewport_free_cached_ids();
|
viewport_free_cached_ids();
|
||||||
environment_free_cached_ids();
|
environment_free_cached_ids();
|
||||||
|
@ -283,6 +283,24 @@ public:
|
|||||||
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||||
FUNC2(reflection_probe_set_resolution, RID, int)
|
FUNC2(reflection_probe_set_resolution, RID, int)
|
||||||
|
|
||||||
|
/* LIGHTMAP CAPTURE */
|
||||||
|
|
||||||
|
FUNCRID(lightmap_capture)
|
||||||
|
|
||||||
|
FUNC2(lightmap_capture_set_bounds, RID, const AABB &)
|
||||||
|
FUNC1RC(AABB, lightmap_capture_get_bounds, RID)
|
||||||
|
|
||||||
|
FUNC2(lightmap_capture_set_octree, RID, const PoolVector<uint8_t> &)
|
||||||
|
FUNC1RC(PoolVector<uint8_t>, lightmap_capture_get_octree, RID)
|
||||||
|
FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &)
|
||||||
|
FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID)
|
||||||
|
FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int)
|
||||||
|
FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID)
|
||||||
|
FUNC2(lightmap_capture_set_energy, RID, float)
|
||||||
|
FUNC1RC(float, lightmap_capture_get_energy, RID)
|
||||||
|
FUNC2(lightmap_capture_set_interior, RID, bool)
|
||||||
|
FUNC1RC(bool, lightmap_capture_is_interior, RID)
|
||||||
|
|
||||||
/* CAMERA API */
|
/* CAMERA API */
|
||||||
|
|
||||||
FUNCRID(camera)
|
FUNCRID(camera)
|
||||||
@ -397,6 +415,7 @@ public:
|
|||||||
FUNC3(instance_set_blend_shape_weight, RID, int, float)
|
FUNC3(instance_set_blend_shape_weight, RID, int, float)
|
||||||
FUNC3(instance_set_surface_material, RID, int, RID)
|
FUNC3(instance_set_surface_material, RID, int, RID)
|
||||||
FUNC2(instance_set_visible, RID, bool)
|
FUNC2(instance_set_visible, RID, bool)
|
||||||
|
FUNC5(instance_set_use_lightmap, RID, RID, RID, int, const Rect2 &)
|
||||||
|
|
||||||
FUNC2(instance_set_custom_aabb, RID, AABB)
|
FUNC2(instance_set_custom_aabb, RID, AABB)
|
||||||
|
|
||||||
|
@ -2023,6 +2023,19 @@ void RenderingServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_shadows);
|
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_shadows);
|
||||||
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
|
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &RenderingServer::lightmap_capture_create);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &RenderingServer::lightmap_capture_set_bounds);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &RenderingServer::lightmap_capture_get_bounds);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree", "capture", "octree"), &RenderingServer::lightmap_capture_set_octree);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_transform", "capture", "xform"), &RenderingServer::lightmap_capture_set_octree_cell_transform);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_transform", "capture"), &RenderingServer::lightmap_capture_get_octree_cell_transform);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_subdiv", "capture", "subdiv"), &RenderingServer::lightmap_capture_set_octree_cell_subdiv);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_subdiv", "capture"), &RenderingServer::lightmap_capture_get_octree_cell_subdiv);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree", "capture"), &RenderingServer::lightmap_capture_get_octree);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_set_energy", "capture", "energy"), &RenderingServer::lightmap_capture_set_energy);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_get_energy", "capture"), &RenderingServer::lightmap_capture_get_energy);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_set_interior", "capture", "interior"), &RenderingServer::lightmap_capture_set_interior);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmap_capture_is_interior", "capture"), &RenderingServer::lightmap_capture_is_interior);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("camera_create"), &RenderingServer::camera_create);
|
ClassDB::bind_method(D_METHOD("camera_create"), &RenderingServer::camera_create);
|
||||||
@ -2111,6 +2124,7 @@ void RenderingServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight);
|
ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight);
|
||||||
ClassDB::bind_method(D_METHOD("instance_set_surface_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_material);
|
ClassDB::bind_method(D_METHOD("instance_set_surface_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_material);
|
||||||
ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible);
|
ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible);
|
||||||
|
ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap", "lightmap_slice", "lightmap_uv_rect"), &RenderingServer::instance_set_use_lightmap, DEFVAL(-1), DEFVAL(Rect2(0, 0, 1, 1)));
|
||||||
ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb);
|
ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb);
|
||||||
ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton);
|
ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton);
|
||||||
ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior);
|
ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior);
|
||||||
@ -2403,9 +2417,11 @@ void RenderingServer::_bind_methods() {
|
|||||||
BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE);
|
BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
|
BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE);
|
BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE);
|
||||||
|
BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP_CAPTURE);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_MAX);
|
BIND_ENUM_CONSTANT(INSTANCE_MAX);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
|
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_BAKED_LIGHT);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
||||||
BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX);
|
BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX);
|
||||||
|
|
||||||
|
@ -526,6 +526,22 @@ public:
|
|||||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
||||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||||
|
|
||||||
|
/* LIGHTMAP CAPTURE */
|
||||||
|
|
||||||
|
virtual RID lightmap_capture_create() = 0;
|
||||||
|
virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0;
|
||||||
|
virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) = 0;
|
||||||
|
virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0;
|
||||||
|
virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0;
|
||||||
|
virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0;
|
||||||
|
virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0;
|
||||||
|
virtual float lightmap_capture_get_energy(RID p_capture) const = 0;
|
||||||
|
virtual void lightmap_capture_set_interior(RID p_capture, bool p_interior) = 0;
|
||||||
|
virtual bool lightmap_capture_is_interior(RID p_capture) const = 0;
|
||||||
|
|
||||||
/* CAMERA API */
|
/* CAMERA API */
|
||||||
|
|
||||||
virtual RID camera_create() = 0;
|
virtual RID camera_create() = 0;
|
||||||
@ -757,6 +773,7 @@ public:
|
|||||||
INSTANCE_IMMEDIATE,
|
INSTANCE_IMMEDIATE,
|
||||||
INSTANCE_LIGHT,
|
INSTANCE_LIGHT,
|
||||||
INSTANCE_REFLECTION_PROBE,
|
INSTANCE_REFLECTION_PROBE,
|
||||||
|
INSTANCE_LIGHTMAP_CAPTURE,
|
||||||
INSTANCE_MAX,
|
INSTANCE_MAX,
|
||||||
|
|
||||||
INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE)
|
INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE)
|
||||||
@ -778,6 +795,8 @@ public:
|
|||||||
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0;
|
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0;
|
||||||
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
|
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
|
||||||
|
|
||||||
|
virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap, int p_lightmap_slice, const Rect2 &p_lightmap_uv_rect) = 0;
|
||||||
|
|
||||||
virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0;
|
virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0;
|
||||||
|
|
||||||
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
|
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
|
||||||
@ -874,7 +893,8 @@ public:
|
|||||||
Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const;
|
Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const;
|
||||||
|
|
||||||
enum InstanceFlags {
|
enum InstanceFlags {
|
||||||
INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
|
INSTANCE_FLAG_USE_BAKED_LIGHT,
|
||||||
|
INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
|
||||||
INSTANCE_FLAG_MAX
|
INSTANCE_FLAG_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user