-Lightmap and lightmap capture support for GLES2

-Added hint to not show some properties when running on low end gfx
This commit is contained in:
Juan Linietsky 2018-09-28 20:32:40 -03:00
parent 4db2db2d6b
commit c83742ba86
19 changed files with 295 additions and 59 deletions

View file

@ -116,6 +116,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19, PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19,
PROPERTY_USAGE_INTERNAL = 1 << 20, PROPERTY_USAGE_INTERNAL = 1 << 20,
PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated
PROPERTY_USAGE_HIGH_END_GFX = 1 << 22,
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,

View file

@ -803,6 +803,8 @@ public:
_create_func = _create_current; _create_func = _create_current;
} }
virtual bool is_low_end() const { return true; }
RasterizerDummy() {} RasterizerDummy() {}
~RasterizerDummy() {} ~RasterizerDummy() {}
}; };

View file

@ -66,6 +66,8 @@ public:
static void make_current(); static void make_current();
static void register_config(); static void register_config();
virtual bool is_low_end() const { return true; }
RasterizerGLES2(); RasterizerGLES2();
~RasterizerGLES2(); ~RasterizerGLES2();
}; };

View file

@ -2028,6 +2028,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
RasterizerStorageGLES2::Texture *prev_lightmap = NULL;
float lightmap_energy = 1.0;
bool prev_use_lightmap_capture = false;
for (int i = 0; i < p_element_count; i++) { for (int i = 0; i < p_element_count; i++) {
RenderList::Element *e = p_elements[i]; RenderList::Element *e = p_elements[i];
@ -2039,6 +2043,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
LightInstance *light = NULL; LightInstance *light = NULL;
ReflectionProbeInstance *refprobe_1 = NULL; ReflectionProbeInstance *refprobe_1 = NULL;
ReflectionProbeInstance *refprobe_2 = NULL; ReflectionProbeInstance *refprobe_2 = NULL;
RasterizerStorageGLES2::Texture *lightmap = NULL;
bool use_lightmap_capture = false;
if (!p_shadow) { if (!p_shadow) {
@ -2147,15 +2153,44 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != NULL); state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != NULL);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != NULL); state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != NULL);
if (refprobe_1 != NULL && refprobe_1 != prev_refprobe_1) { if (refprobe_1 != NULL && refprobe_1 != prev_refprobe_1) {
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap);
} }
if (refprobe_2 != NULL && refprobe_2 != prev_refprobe_2) { if (refprobe_2 != NULL && refprobe_2 != prev_refprobe_2) {
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap);
} }
rebind = true; rebind = 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 != NULL);
if (lightmap != NULL) {
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
glBindTexture(GL_TEXTURE_2D, lightmap->tex_id);
}
rebind = true;
}
} }
bool instancing = e->instancing; bool instancing = e->instancing;
@ -2224,6 +2259,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
if (refprobe_1 || refprobe_2) { if (refprobe_1 || refprobe_2) {
_setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env); _setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env);
} }
if (lightmap) {
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_ENERGY, lightmap_energy);
}
} }
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, view_transform_inverse); state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, view_transform_inverse);
@ -2239,6 +2278,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
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());
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false);
}
_render_geometry(e); _render_geometry(e);
prev_geometry = e->geometry; prev_geometry = e->geometry;
@ -2248,6 +2292,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(NULL, NULL); //clear light stuff _setup_light_type(NULL, NULL); //clear light stuff
@ -2260,6 +2306,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);
} }
void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) { void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) {
@ -2818,6 +2866,44 @@ void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
} }
bool RasterizerSceneGLES2::free(RID p_rid) { bool RasterizerSceneGLES2::free(RID p_rid) {
if (light_instance_owner.owns(p_rid)) {
LightInstance *light_instance = light_instance_owner.getptr(p_rid);
//remove from shadow atlases..
for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(E->get());
ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
uint32_t key = shadow_atlas->shadow_owners[p_rid];
uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
shadow_atlas->shadow_owners.erase(p_rid);
}
light_instance_owner.free(p_rid);
memdelete(light_instance);
} else if (shadow_atlas_owner.owns(p_rid)) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid);
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);
memdelete(shadow_atlas);
} else if (reflection_probe_instance_owner.owns(p_rid)) {
ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
memdelete(reflection_instance);
} else {
return false;
}
return true; return true;
} }

View file

@ -496,22 +496,6 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} }
//set swizle for older format compatibility
#ifdef GLES_OVER_GL
switch (texture->format) {
case Image::FORMAT_L8: {
} break;
case Image::FORMAT_LA8: {
} break;
default: {
} break;
}
#endif
int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1;
int w = img->get_width(); int w = img->get_width();
@ -591,7 +575,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0); int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
PoolVector<uint8_t>::Write wb = data.write(); PoolVector<uint8_t>::Write wb = data.write();
@ -3595,46 +3579,100 @@ void RasterizerStorageGLES2::gi_probe_dynamic_data_update(RID p_gi_probe_data, i
/////// ///////
RID RasterizerStorageGLES2::lightmap_capture_create() { RID RasterizerStorageGLES2::lightmap_capture_create() {
return RID();
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) { 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();
}
AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const { AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const {
return AABB();
}
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) { 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();
copymem(w.ptr(), r.ptr(), p_octree.size());
}
capture->instance_change_notify();
}
PoolVector<uint8_t> RasterizerStorageGLES2::lightmap_capture_get_octree(RID p_capture) const { PoolVector<uint8_t> RasterizerStorageGLES2::lightmap_capture_get_octree(RID p_capture) const {
return PoolVector<uint8_t>();
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();
copymem(w.ptr(), r.ptr(), ret.size());
}
return ret;
} }
void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) { 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 { Transform RasterizerStorageGLES2::lightmap_capture_get_octree_cell_transform(RID p_capture) const {
return Transform(); 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) { 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 { int RasterizerStorageGLES2::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const {
return 0; 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) { 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;
} }
float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const { float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const {
return 0.0;
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, 0);
return capture->energy;
} }
const PoolVector<RasterizerStorage::LightmapCaptureOctree> *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const { const PoolVector<RasterizerStorage::LightmapCaptureOctree> *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const {
return NULL; const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, NULL);
return &capture->octree;
} }
/////// ///////
@ -3773,10 +3811,10 @@ void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene
inst = gi_probe_owner.getornull(p_base); inst = gi_probe_owner.getornull(p_base);
ERR_FAIL_COND(!inst); ERR_FAIL_COND(!inst);
} break;*/ } break;*/
/*case VS::INSTANCE_LIGHTMAP_CAPTURE: { case VS::INSTANCE_LIGHTMAP_CAPTURE: {
inst = lightmap_capture_data_owner.getornull(p_base); inst = lightmap_capture_data_owner.getornull(p_base);
ERR_FAIL_COND(!inst); ERR_FAIL_COND(!inst);
} break;*/ } break;
default: { default: {
if (!inst) { if (!inst) {
ERR_FAIL(); ERR_FAIL();
@ -3819,11 +3857,11 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc
/*case VS::INSTANCE_GI_PROBE: { /*case VS::INSTANCE_GI_PROBE: {
inst = gi_probe_owner.getornull(p_base); inst = gi_probe_owner.getornull(p_base);
ERR_FAIL_COND(!inst); ERR_FAIL_COND(!inst);
} break; } break; */
case VS::INSTANCE_LIGHTMAP_CAPTURE: { case VS::INSTANCE_LIGHTMAP_CAPTURE: {
inst = lightmap_capture_data_owner.getornull(p_base); inst = lightmap_capture_data_owner.getornull(p_base);
ERR_FAIL_COND(!inst); ERR_FAIL_COND(!inst);
} break;*/ } break;
default: { default: {
if (!inst) { if (!inst) {
@ -4094,6 +4132,8 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
return VS::INSTANCE_IMMEDIATE; return VS::INSTANCE_IMMEDIATE;
} else if (reflection_probe_owner.owns(p_rid)) { } else if (reflection_probe_owner.owns(p_rid)) {
return VS::INSTANCE_REFLECTION_PROBE; return VS::INSTANCE_REFLECTION_PROBE;
} else if (lightmap_capture_data_owner.owns(p_rid)) {
return VS::INSTANCE_LIGHTMAP_CAPTURE;
} else { } else {
return VS::INSTANCE_NONE; return VS::INSTANCE_NONE;
} }
@ -4281,7 +4321,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 { } else {
return false; return false;
} }

View file

@ -1046,6 +1046,21 @@ public:
/* LIGHTMAP */ /* LIGHTMAP */
struct LightmapCapture : public Instanciable {
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;
virtual RID lightmap_capture_create(); virtual RID lightmap_capture_create();
virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds); virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds);
virtual AABB lightmap_capture_get_bounds(RID p_capture) const; virtual AABB lightmap_capture_get_bounds(RID p_capture) const;

View file

@ -27,15 +27,15 @@ attribute vec3 normal_attrib; // attrib:1
attribute vec4 tangent_attrib; // attrib:2 attribute vec4 tangent_attrib; // attrib:2
#endif #endif
#ifdef ENABLE_COLOR_INTERP #if defined(ENABLE_COLOR_INTERP)
attribute vec4 color_attrib; // attrib:3 attribute vec4 color_attrib; // attrib:3
#endif #endif
#ifdef ENABLE_UV_INTERP #if defined(ENABLE_UV_INTERP)
attribute vec2 uv_attrib; // attrib:4 attribute vec2 uv_attrib; // attrib:4
#endif #endif
#ifdef 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
@ -102,15 +102,15 @@ varying vec3 tangent_interp;
varying vec3 binormal_interp; varying vec3 binormal_interp;
#endif #endif
#ifdef ENABLE_COLOR_INTERP #if defined(ENABLE_COLOR_INTERP)
varying vec4 color_interp; varying vec4 color_interp;
#endif #endif
#ifdef ENABLE_UV_INTERP #if defined(ENABLE_UV_INTERP)
varying vec2 uv_interp; varying vec2 uv_interp;
#endif #endif
#ifdef ENABLE_UV2_INTERP #if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
varying vec2 uv2_interp; varying vec2 uv2_interp;
#endif #endif
@ -317,18 +317,18 @@ void main() {
vec3 binormal = normalize(cross(normal, tangent) * binormalf); vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif #endif
#ifdef ENABLE_COLOR_INTERP #if defined(ENABLE_COLOR_INTERP)
color_interp = color_attrib; color_interp = color_attrib;
#ifdef USE_INSTANCING #ifdef USE_INSTANCING
color_interp *= instance_color; color_interp *= instance_color;
#endif #endif
#endif #endif
#ifdef ENABLE_UV_INTERP #if defined(ENABLE_UV_INTERP)
uv_interp = uv_attrib; uv_interp = uv_attrib;
#endif #endif
#ifdef ENABLE_UV2_INTERP #if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib; uv2_interp = uv2_attrib;
#endif #endif
@ -521,7 +521,7 @@ VERTEX_SHADER_CODE
#if defined(LIGHT_USE_PSSM4) #if defined(LIGHT_USE_PSSM4)
shadow_coord3 = light_shadow_matrix3 * vi4; shadow_coord3 = light_shadow_matrix3 * vi4;
shadow_coord3 = light_shadow_matrix3 * vi4; shadow_coord4 = light_shadow_matrix4 * vi4;
#endif #endif
@ -612,7 +612,7 @@ uniform mat4 world_transform;
uniform highp float time; uniform highp float time;
#ifdef SCREEN_UV_USED #if defined(SCREEN_UV_USED)
uniform vec2 screen_pixel_size; uniform vec2 screen_pixel_size;
#endif #endif
@ -643,7 +643,7 @@ uniform mat4 refprobe1_local_matrix;
uniform bool refprobe1_exterior; uniform bool refprobe1_exterior;
uniform highp samplerCube reflection_probe1; //texunit:-4 uniform highp samplerCube reflection_probe1; //texunit:-5
uniform float refprobe1_intensity; uniform float refprobe1_intensity;
uniform vec4 refprobe1_ambient; uniform vec4 refprobe1_ambient;
@ -670,7 +670,7 @@ uniform mat4 refprobe2_local_matrix;
uniform bool refprobe2_exterior; uniform bool refprobe2_exterior;
uniform highp samplerCube reflection_probe2; //texunit:-5 uniform highp samplerCube reflection_probe2; //texunit:-6
uniform float refprobe2_intensity; uniform float refprobe2_intensity;
uniform vec4 refprobe2_ambient; uniform vec4 refprobe2_ambient;
@ -773,7 +773,16 @@ void reflection_process(samplerCube reflection_map,
#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;
#endif
#ifdef USE_LIGHTMAP_CAPTURE
uniform mediump vec4[12] lightmap_captures;
uniform bool lightmap_capture_sky;
#endif
#ifdef USE_RADIANCE_MAP #ifdef USE_RADIANCE_MAP
@ -866,15 +875,15 @@ varying vec3 tangent_interp;
varying vec3 binormal_interp; varying vec3 binormal_interp;
#endif #endif
#ifdef ENABLE_COLOR_INTERP #if defined(ENABLE_COLOR_INTERP)
varying vec4 color_interp; varying vec4 color_interp;
#endif #endif
#ifdef ENABLE_UV_INTERP #if defined(ENABLE_UV_INTERP)
varying vec2 uv_interp; varying vec2 uv_interp;
#endif #endif
#ifdef ENABLE_UV2_INTERP #if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
varying vec2 uv2_interp; varying vec2 uv2_interp;
#endif #endif
@ -1285,11 +1294,11 @@ void main() {
#endif #endif
float normaldepth = 1.0; float normaldepth = 1.0;
#ifdef ALPHA_SCISSOR_USED #if defined(ALPHA_SCISSOR_USED)
float alpha_scissor = 0.5; float alpha_scissor = 0.5;
#endif #endif
#ifdef SCREEN_UV_USED #if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
#endif #endif
@ -1319,7 +1328,7 @@ FRAGMENT_SHADER_CODE
vec3 eye_position = -normalize(vertex_interp); vec3 eye_position = -normalize(vertex_interp);
#ifdef ALPHA_SCISSOR_USED #if defined(ALPHA_SCISSOR_USED)
if (alpha < alpha_scissor) { if (alpha < alpha_scissor) {
discard; discard;
} }
@ -1404,6 +1413,47 @@ FRAGMENT_SHADER_CODE
#endif //use reflection probe 1 #endif //use reflection probe 1
#ifdef USE_LIGHTMAP
//ambient light will come entirely from lightmap is lightmap is used
ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy;
#endif
#ifdef USE_LIGHTMAP_CAPTURE
{
vec3 cone_dirs[12] = vec3[](
vec3(0, 0, 1),
vec3(0.866025, 0, 0.5),
vec3(0.267617, 0.823639, 0.5),
vec3(-0.700629, 0.509037, 0.5),
vec3(-0.700629, -0.509037, 0.5),
vec3(0.267617, -0.823639, 0.5),
vec3(0, 0, -1),
vec3(0.866025, 0, -0.5),
vec3(0.267617, 0.823639, -0.5),
vec3(-0.700629, 0.509037, -0.5),
vec3(-0.700629, -0.509037, -0.5),
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;
if (lightmap_capture_sky) {
ambient_light = mix(ambient_light, captured.rgb, captured.a);
} else {
ambient_light = captured.rgb;
}
}
#endif
#endif //BASE PASS #endif //BASE PASS
// //

View file

@ -66,6 +66,8 @@ public:
static void make_current(); static void make_current();
static void register_config(); static void register_config();
virtual bool is_low_end() const { return false; }
RasterizerGLES3(); RasterizerGLES3();
~RasterizerGLES3(); ~RasterizerGLES3();
}; };

View file

@ -1029,7 +1029,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0); int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
PoolVector<uint8_t>::Write wb = data.write(); PoolVector<uint8_t>::Write wb = data.write();
@ -7364,7 +7364,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid); GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid);
glDeleteTextures(1, &gi_probe_data->tex_id); glDeleteTextures(1, &gi_probe_data->tex_id);
gi_probe_owner.free(p_rid); gi_probe_data_owner.free(p_rid);
memdelete(gi_probe_data); memdelete(gi_probe_data);
} else if (lightmap_capture_data_owner.owns(p_rid)) { } else if (lightmap_capture_data_owner.owns(p_rid)) {
@ -7372,7 +7372,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid); LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid);
lightmap_capture->instance_remove_deps(); lightmap_capture->instance_remove_deps();
gi_probe_owner.free(p_rid); lightmap_capture_data_owner.free(p_rid);
memdelete(lightmap_capture); memdelete(lightmap_capture);
} else if (canvas_occluder_owner.owns(p_rid)) { } else if (canvas_occluder_owner.owns(p_rid)) {

View file

@ -1449,6 +1449,9 @@ void EditorInspector::update_tree() {
} else if (!(p.usage & PROPERTY_USAGE_EDITOR)) } else if (!(p.usage & PROPERTY_USAGE_EDITOR))
continue; continue;
if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && VS::get_singleton()->is_low_end())
continue; //do not show this property in low end gfx
if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) { if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) {
continue; continue;
} }

View file

@ -68,12 +68,9 @@ def include_file_in_legacygl_header(filename, header_data, depth):
line = fs.readline() line = fs.readline()
if line.find("#ifdef ") != -1 or line.find("#elif defined(") != -1: if line.find("#ifdef ") != -1:
if line.find("#ifdef ") != -1: if line.find("#ifdef ") != -1:
ifdefline = line.replace("#ifdef ", "").strip() ifdefline = line.replace("#ifdef ", "").strip()
else:
ifdefline = line.replace("#elif defined(", "").strip()
ifdefline = ifdefline.replace(")", "").strip()
if line.find("_EN_") != -1: if line.find("_EN_") != -1:
enumbase = ifdefline[:ifdefline.find("_EN_")] enumbase = ifdefline[:ifdefline.find("_EN_")]

View file

@ -1369,6 +1369,12 @@ void SpatialMaterial::_validate_feature(const String &text, Feature feature, Pro
} }
} }
void SpatialMaterial::_validate_high_end(const String &text, PropertyInfo &property) const {
if (property.name.begins_with(text)) {
property.usage |= PROPERTY_USAGE_HIGH_END_GFX;
}
}
void SpatialMaterial::_validate_property(PropertyInfo &property) const { void SpatialMaterial::_validate_property(PropertyInfo &property) const {
_validate_feature("normal", FEATURE_NORMAL_MAPPING, property); _validate_feature("normal", FEATURE_NORMAL_MAPPING, property);
_validate_feature("emission", FEATURE_EMISSION, property); _validate_feature("emission", FEATURE_EMISSION, property);
@ -1382,6 +1388,12 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const {
_validate_feature("refraction", FEATURE_REFRACTION, property); _validate_feature("refraction", FEATURE_REFRACTION, property);
_validate_feature("detail", FEATURE_DETAIL, property); _validate_feature("detail", FEATURE_DETAIL, property);
_validate_high_end("refraction", property);
_validate_high_end("subsurf_scatter", property);
_validate_high_end("anisotropy", property);
_validate_high_end("clearcoat", property);
_validate_high_end("depth", property);
if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) {
property.usage = 0; property.usage = 0;
} }

View file

@ -442,6 +442,8 @@ private:
static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff
void _validate_high_end(const String &text, PropertyInfo &property) const;
protected: protected:
static void _bind_methods(); static void _bind_methods();
void _validate_property(PropertyInfo &property) const; void _validate_property(PropertyInfo &property) const;

View file

@ -207,6 +207,9 @@ void ImageTexture::set_flags(uint32_t p_flags) {
flags=p_flags|cube; */ flags=p_flags|cube; */
flags = p_flags; flags = p_flags;
if (w == 0 || h == 0) {
return; //uninitialized, do not set to texture
}
VisualServer::get_singleton()->texture_set_flags(texture, p_flags); VisualServer::get_singleton()->texture_set_flags(texture, p_flags);
} }

View file

@ -1107,6 +1107,8 @@ public:
virtual void end_frame(bool p_swap_buffers) = 0; virtual void end_frame(bool p_swap_buffers) = 0;
virtual void finalize() = 0; virtual void finalize() = 0;
virtual bool is_low_end() const = 0;
virtual ~Rasterizer() {} virtual ~Rasterizer() {}
}; };

View file

@ -189,6 +189,9 @@ void VisualServerRaster::call_set_use_vsync(bool p_enable) {
OS::get_singleton()->_set_use_vsync(p_enable); OS::get_singleton()->_set_use_vsync(p_enable);
} }
bool VisualServerRaster::is_low_end() const {
return VSG::rasterizer->is_low_end();
}
VisualServerRaster::VisualServerRaster() { VisualServerRaster::VisualServerRaster() {
VSG::canvas = memnew(VisualServerCanvas); VSG::canvas = memnew(VisualServerCanvas);

View file

@ -690,6 +690,8 @@ public:
virtual void call_set_use_vsync(bool p_enable); virtual void call_set_use_vsync(bool p_enable);
virtual bool is_low_end() const;
VisualServerRaster(); VisualServerRaster();
~VisualServerRaster(); ~VisualServerRaster();

View file

@ -609,6 +609,10 @@ public:
static void set_use_vsync_callback(bool p_enable); static void set_use_vsync_callback(bool p_enable);
virtual bool is_low_end() const {
return visual_server->is_low_end();
}
VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread); VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread);
~VisualServerWrapMT(); ~VisualServerWrapMT();

View file

@ -1037,6 +1037,8 @@ public:
virtual void call_set_use_vsync(bool p_enable) = 0; virtual void call_set_use_vsync(bool p_enable) = 0;
virtual bool is_low_end() const = 0;
VisualServer(); VisualServer();
virtual ~VisualServer(); virtual ~VisualServer();
}; };