-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
+2
View File
@@ -803,6 +803,8 @@ public:
_create_func = _create_current;
}
virtual bool is_low_end() const { return true; }
RasterizerDummy() {}
~RasterizerDummy() {}
};
+2
View File
@@ -66,6 +66,8 @@ public:
static void make_current();
static void register_config();
virtual bool is_low_end() const { return true; }
RasterizerGLES2();
~RasterizerGLES2();
};
+88 -2
View File
@@ -2028,6 +2028,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
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++) {
RenderList::Element *e = p_elements[i];
@@ -2039,6 +2043,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
LightInstance *light = NULL;
ReflectionProbeInstance *refprobe_1 = NULL;
ReflectionProbeInstance *refprobe_2 = NULL;
RasterizerStorageGLES2::Texture *lightmap = NULL;
bool use_lightmap_capture = false;
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_PROBE2, refprobe_2 != NULL);
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);
}
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);
}
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;
@@ -2224,6 +2259,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
if (refprobe_1 || refprobe_2) {
_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);
@@ -2239,6 +2278,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
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);
prev_geometry = e->geometry;
@@ -2248,6 +2292,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
prev_light = light;
prev_refprobe_1 = refprobe_1;
prev_refprobe_2 = refprobe_2;
prev_lightmap = lightmap;
prev_use_lightmap_capture = use_lightmap_capture;
}
_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_REFLECTION_PROBE1, 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) {
@@ -2818,6 +2866,44 @@ void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
}
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;
}
+79 -31
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);
}
//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 w = img->get_width();
@@ -591,7 +575,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
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
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() {
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) {
}
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 {
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) {
}
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 {
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) {
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 {
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) {
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 {
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) {
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 {
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 {
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);
ERR_FAIL_COND(!inst);
} break;*/
/*case VS::INSTANCE_LIGHTMAP_CAPTURE: {
case VS::INSTANCE_LIGHTMAP_CAPTURE: {
inst = lightmap_capture_data_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;*/
} break;
default: {
if (!inst) {
ERR_FAIL();
@@ -3819,11 +3857,11 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc
/*case VS::INSTANCE_GI_PROBE: {
inst = gi_probe_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
} break; */
case VS::INSTANCE_LIGHTMAP_CAPTURE: {
inst = lightmap_capture_data_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;*/
} break;
default: {
if (!inst) {
@@ -4094,6 +4132,8 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
return VS::INSTANCE_IMMEDIATE;
} else if (reflection_probe_owner.owns(p_rid)) {
return VS::INSTANCE_REFLECTION_PROBE;
} else if (lightmap_capture_data_owner.owns(p_rid)) {
return VS::INSTANCE_LIGHTMAP_CAPTURE;
} else {
return VS::INSTANCE_NONE;
}
@@ -4281,7 +4321,15 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
memdelete(reflection_probe);
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 {
return false;
}
+15
View File
@@ -1046,6 +1046,21 @@ public:
/* 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 void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds);
virtual AABB lightmap_capture_get_bounds(RID p_capture) const;
+69 -19
View File
@@ -27,15 +27,15 @@ attribute vec3 normal_attrib; // attrib:1
attribute vec4 tangent_attrib; // attrib:2
#endif
#ifdef ENABLE_COLOR_INTERP
#if defined(ENABLE_COLOR_INTERP)
attribute vec4 color_attrib; // attrib:3
#endif
#ifdef ENABLE_UV_INTERP
#if defined(ENABLE_UV_INTERP)
attribute vec2 uv_attrib; // attrib:4
#endif
#ifdef ENABLE_UV2_INTERP
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
attribute vec2 uv2_attrib; // attrib:5
#endif
@@ -102,15 +102,15 @@ varying vec3 tangent_interp;
varying vec3 binormal_interp;
#endif
#ifdef ENABLE_COLOR_INTERP
#if defined(ENABLE_COLOR_INTERP)
varying vec4 color_interp;
#endif
#ifdef ENABLE_UV_INTERP
#if defined(ENABLE_UV_INTERP)
varying vec2 uv_interp;
#endif
#ifdef ENABLE_UV2_INTERP
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
varying vec2 uv2_interp;
#endif
@@ -317,18 +317,18 @@ void main() {
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
#ifdef ENABLE_COLOR_INTERP
#if defined(ENABLE_COLOR_INTERP)
color_interp = color_attrib;
#ifdef USE_INSTANCING
color_interp *= instance_color;
#endif
#endif
#ifdef ENABLE_UV_INTERP
#if defined(ENABLE_UV_INTERP)
uv_interp = uv_attrib;
#endif
#ifdef ENABLE_UV2_INTERP
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib;
#endif
@@ -521,7 +521,7 @@ VERTEX_SHADER_CODE
#if defined(LIGHT_USE_PSSM4)
shadow_coord3 = light_shadow_matrix3 * vi4;
shadow_coord3 = light_shadow_matrix3 * vi4;
shadow_coord4 = light_shadow_matrix4 * vi4;
#endif
@@ -612,7 +612,7 @@ uniform mat4 world_transform;
uniform highp float time;
#ifdef SCREEN_UV_USED
#if defined(SCREEN_UV_USED)
uniform vec2 screen_pixel_size;
#endif
@@ -643,7 +643,7 @@ uniform mat4 refprobe1_local_matrix;
uniform bool refprobe1_exterior;
uniform highp samplerCube reflection_probe1; //texunit:-4
uniform highp samplerCube reflection_probe1; //texunit:-5
uniform float refprobe1_intensity;
uniform vec4 refprobe1_ambient;
@@ -670,7 +670,7 @@ uniform mat4 refprobe2_local_matrix;
uniform bool refprobe2_exterior;
uniform highp samplerCube reflection_probe2; //texunit:-5
uniform highp samplerCube reflection_probe2; //texunit:-6
uniform float refprobe2_intensity;
uniform vec4 refprobe2_ambient;
@@ -773,7 +773,16 @@ void reflection_process(samplerCube reflection_map,
#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
@@ -866,15 +875,15 @@ varying vec3 tangent_interp;
varying vec3 binormal_interp;
#endif
#ifdef ENABLE_COLOR_INTERP
#if defined(ENABLE_COLOR_INTERP)
varying vec4 color_interp;
#endif
#ifdef ENABLE_UV_INTERP
#if defined(ENABLE_UV_INTERP)
varying vec2 uv_interp;
#endif
#ifdef ENABLE_UV2_INTERP
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
varying vec2 uv2_interp;
#endif
@@ -1285,11 +1294,11 @@ void main() {
#endif
float normaldepth = 1.0;
#ifdef ALPHA_SCISSOR_USED
#if defined(ALPHA_SCISSOR_USED)
float alpha_scissor = 0.5;
#endif
#ifdef SCREEN_UV_USED
#if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
#endif
@@ -1319,7 +1328,7 @@ FRAGMENT_SHADER_CODE
vec3 eye_position = -normalize(vertex_interp);
#ifdef ALPHA_SCISSOR_USED
#if defined(ALPHA_SCISSOR_USED)
if (alpha < alpha_scissor) {
discard;
}
@@ -1404,6 +1413,47 @@ FRAGMENT_SHADER_CODE
#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
//
+2
View File
@@ -66,6 +66,8 @@ public:
static void make_current();
static void register_config();
virtual bool is_low_end() const { return false; }
RasterizerGLES3();
~RasterizerGLES3();
};
+3 -3
View File
@@ -1029,7 +1029,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
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
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);
glDeleteTextures(1, &gi_probe_data->tex_id);
gi_probe_owner.free(p_rid);
gi_probe_data_owner.free(p_rid);
memdelete(gi_probe_data);
} 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);
lightmap_capture->instance_remove_deps();
gi_probe_owner.free(p_rid);
lightmap_capture_data_owner.free(p_rid);
memdelete(lightmap_capture);
} else if (canvas_occluder_owner.owns(p_rid)) {