summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp25
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.h1
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp2
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp56
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h1
-rw-r--r--drivers/gles2/shader_gles2.h1
-rw-r--r--drivers/gles2/shaders/scene.glsl180
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp23
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h1
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp37
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp153
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h1
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl119
-rw-r--r--drivers/gles3/shaders/scene.glsl29
15 files changed, 461 insertions, 170 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index e34705f7b7..ac54af722c 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -291,6 +291,10 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const float *p_weights, const int *p_bones) {
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
uint32_t buffer_ofs = 0;
@@ -339,6 +343,11 @@ void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_coun
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
+
if (storage->config.support_32_bits_indices) { //should check for
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0);
@@ -358,6 +367,10 @@ void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_coun
void RasterizerCanvasGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
uint32_t buffer_ofs = 0;
@@ -435,6 +448,10 @@ void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_v
}
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), buffer_data);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL);
@@ -749,6 +766,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
WARN_PRINT("NinePatch without texture not supported yet in GLES2 backend, skipping.");
continue;
}
+ if (tex->width == 0 || tex->height == 0) {
+ WARN_PRINT("Cannot set empty texture to NinePatch.");
+ continue;
+ }
Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height);
@@ -883,7 +904,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
}
glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * (16 + 16) * 2, buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, buffer, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements);
@@ -2034,6 +2055,8 @@ void RasterizerCanvasGLES2::initialize() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ data.polygon_index_buffer_size = index_size;
}
// ninepatch buffers
diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h
index ab636dca71..ba636a9763 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.h
+++ b/drivers/gles2/rasterizer_canvas_gles2.h
@@ -65,6 +65,7 @@ public:
GLuint polygon_index_buffer;
uint32_t polygon_buffer_size;
+ uint32_t polygon_index_buffer_size;
GLuint ninepatch_vertices;
GLuint ninepatch_elements;
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 1deecbf3cc..bc47fb46f5 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -2702,7 +2702,7 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C
}
glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector3) * 8, vertices);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, vertices, GL_DYNAMIC_DRAW);
// bind sky vertex array....
glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0);
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 82cb1ef90b..40e7f0c441 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -85,7 +85,9 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define glClearDepth glClearDepthf
// enable extensions manually for android and ios
+#ifndef UWP_ENABLED
#include <dlfcn.h> // needed to load extensions
+#endif
#ifdef IPHONE_ENABLED
@@ -93,13 +95,18 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
//void *glRenderbufferStorageMultisampleAPPLE;
//void *glResolveMultisampleFramebufferAPPLE;
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE
-#elif ANDROID_ENABLED
+#elif defined(ANDROID_ENABLED)
#include <GLES2/gl2ext.h>
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT;
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT
+
+#elif defined(UWP_ENABLED)
+#include <GLES2/gl2ext.h>
+#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleANGLE
+#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleANGLE
#endif
#define GL_MAX_SAMPLES 0x8D57
@@ -4583,13 +4590,24 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
GLuint color_internal_format;
GLuint color_format;
GLuint color_type = GL_UNSIGNED_BYTE;
+ Image::Format image_format;
if (rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+#ifdef GLES_OVER_GL
+ color_internal_format = GL_RGBA8;
+#else
color_internal_format = GL_RGBA;
+#endif
color_format = GL_RGBA;
+ image_format = Image::FORMAT_RGBA8;
} else {
+#ifdef GLES_OVER_GL
+ color_internal_format = GL_RGB8;
+#else
color_internal_format = GL_RGB;
+#endif
color_format = GL_RGB;
+ image_format = Image::FORMAT_RGB8;
}
rt->used_dof_blur_near = false;
@@ -4646,7 +4664,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, rt->width, rt->height);
+ glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
}
@@ -4676,10 +4694,10 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
return;
}
- texture->format = Image::FORMAT_RGBA8;
- texture->gl_format_cache = GL_RGBA;
+ texture->format = image_format;
+ texture->gl_format_cache = color_format;
texture->gl_type_cache = GL_UNSIGNED_BYTE;
- texture->gl_internal_format_cache = GL_RGBA;
+ texture->gl_internal_format_cache = color_internal_format;
texture->tex_id = rt->color;
texture->width = rt->width;
texture->alloc_width = rt->width;
@@ -4714,7 +4732,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->multisample_depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_internalformat, rt->width, rt->height);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth);
@@ -5178,7 +5196,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
// create a multisample depth buffer, we're not reusing Godots because Godot's didn't get created..
glGenRenderbuffers(1, &rt->external.depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->external.depth);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_internalformat, rt->width, rt->height);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->external.depth);
}
@@ -5291,7 +5309,7 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
glGenRenderbuffers(1, &cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, cls->size, cls->height);
+ glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, cls->size, cls->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
glGenTextures(1, &cls->distance);
@@ -5772,6 +5790,8 @@ void RasterizerStorageGLES2::initialize() {
config.keep_original_textures = false;
config.shrink_textures_x2 = false;
+ config.depth_internalformat = GL_DEPTH_COMPONENT;
+ config.depth_type = GL_UNSIGNED_INT;
#ifdef GLES_OVER_GL
config.float_texture_supported = true;
@@ -5779,20 +5799,20 @@ void RasterizerStorageGLES2::initialize() {
config.pvrtc_supported = false;
config.etc1_supported = false;
config.support_npot_repeat_mipmap = true;
- config.depth_internalformat = GL_DEPTH_COMPONENT;
- config.depth_type = GL_UNSIGNED_INT;
+ config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
#else
config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
config.pvrtc_supported = config.extensions.has("IMG_texture_compression_pvrtc") || config.extensions.has("WEBGL_compressed_texture_pvrtc");
config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot");
- // on mobile check for 24 bit depth support
+
+ // on mobile check for 24 bit depth support for RenderBufferStorage
if (config.extensions.has("GL_OES_depth24")) {
- config.depth_internalformat = _DEPTH_COMPONENT24_OES;
+ config.depth_buffer_internalformat = _DEPTH_COMPONENT24_OES;
config.depth_type = GL_UNSIGNED_INT;
} else {
- config.depth_internalformat = GL_DEPTH_COMPONENT16;
+ config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
config.depth_type = GL_UNSIGNED_SHORT;
}
#endif
@@ -5871,7 +5891,7 @@ void RasterizerStorageGLES2::initialize() {
GLuint depth;
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, config.depth_internalformat, config.depth_type, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -5890,8 +5910,12 @@ void RasterizerStorageGLES2::initialize() {
if (status != GL_FRAMEBUFFER_COMPLETE) {
// If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT
// This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT
-
+#ifdef GLES_OVER_GL
config.depth_internalformat = GL_DEPTH_COMPONENT16;
+#else
+ // OES_depth_texture extension only specifies GL_DEPTH_COMPONENT.
+ config.depth_internalformat = GL_DEPTH_COMPONENT;
+#endif
config.depth_type = GL_UNSIGNED_SHORT;
glGenFramebuffers(1, &fbo);
@@ -5899,7 +5923,7 @@ void RasterizerStorageGLES2::initialize() {
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 32, 32, 0, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 6de530d8c3..daf6b93afc 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -99,6 +99,7 @@ public:
GLuint depth_internalformat;
GLuint depth_type;
+ GLuint depth_buffer_internalformat;
} config;
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index 2456a83d35..c7a6465194 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -119,6 +119,7 @@ private:
bool ok;
Version() {
code_version = 0;
+ frag_id = 0;
ok = false;
uniform_location = NULL;
}
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index e36e776881..25dbbf3c90 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -1547,155 +1547,157 @@ FRAGMENT_SHADER_CODE
#endif // !USE_SHADOW_TO_OPACITY
#ifdef BASE_PASS
- //none
+ {
+ // IBL precalculations
+ float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0);
+ vec3 f0 = F0(metallic, specular, albedo);
+ vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0);
#ifdef AMBIENT_LIGHT_DISABLED
- ambient_light = vec3(0.0, 0.0, 0.0);
+ ambient_light = vec3(0.0, 0.0, 0.0);
#else
#ifdef USE_RADIANCE_MAP
- vec3 ref_vec = reflect(-eye_position, N);
- ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz);
+ vec3 ref_vec = reflect(-eye_position, N);
+ ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz);
- ref_vec.z *= -1.0;
+ ref_vec.z *= -1.0;
- specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
- {
- vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
- vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).xyz * bg_energy;
+ specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
+#ifndef USE_LIGHTMAP
+ {
+ 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;
+ env_ambient *= 1.0 - F;
- ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
- }
+ ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
+ }
+#endif
#else
- ambient_light = ambient_color.rgb;
- specular_light = bg_color.rgb * bg_energy;
+ ambient_light = ambient_color.rgb;
+ specular_light = bg_color.rgb * bg_energy;
#endif
-
#endif // AMBIENT_LIGHT_DISABLED
- ambient_light *= ambient_energy;
+ ambient_light *= ambient_energy;
#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
- vec4 ambient_accum = vec4(0.0);
- vec4 reflection_accum = vec4(0.0);
+ vec4 ambient_accum = vec4(0.0);
+ vec4 reflection_accum = vec4(0.0);
#ifdef USE_REFLECTION_PROBE1
- reflection_process(reflection_probe1,
+ reflection_process(reflection_probe1,
#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
- normal_interp, vertex_interp, refprobe1_local_matrix,
- refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset,
+ normal_interp, vertex_interp, refprobe1_local_matrix,
+ refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset,
#endif
- refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness,
- ambient_light, specular_light, reflection_accum, ambient_accum);
+ refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness,
+ ambient_light, specular_light, reflection_accum, ambient_accum);
#endif // USE_REFLECTION_PROBE1
#ifdef USE_REFLECTION_PROBE2
- reflection_process(reflection_probe2,
+ reflection_process(reflection_probe2,
#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
- normal_interp, vertex_interp, refprobe2_local_matrix,
- refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset,
+ normal_interp, vertex_interp, refprobe2_local_matrix,
+ refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset,
#endif
- refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness,
- ambient_light, specular_light, reflection_accum, ambient_accum);
+ refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness,
+ ambient_light, specular_light, reflection_accum, ambient_accum);
#endif // USE_REFLECTION_PROBE2
- if (reflection_accum.a > 0.0) {
- specular_light = reflection_accum.rgb / reflection_accum.a;
- }
+ if (reflection_accum.a > 0.0) {
+ specular_light = reflection_accum.rgb / reflection_accum.a;
+ }
#ifndef USE_LIGHTMAP
- if (ambient_accum.a > 0.0) {
- ambient_light = ambient_accum.rgb / ambient_accum.a;
- }
+ if (ambient_accum.a > 0.0) {
+ ambient_light = ambient_accum.rgb / ambient_accum.a;
+ }
#endif
#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
- // environment BRDF approximation
-
- {
+ // environment BRDF approximation
+ {
#if defined(DIFFUSE_TOON)
- //simplify for toon, as
- specular_light *= specular * metallic * albedo * 2.0;
+ //simplify for toon, as
+ specular_light *= specular * metallic * albedo * 2.0;
#else
- // scales the specular reflections, needs to be be computed before lighting happens,
- // but after environment and reflection probes are added
- //TODO: this curve is not really designed for gammaspace, should be adjusted
- const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
- const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
- vec4 r = roughness * c0 + c1;
- float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0);
- float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
- vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
-
- vec3 f0 = F0(metallic, specular, albedo);
- specular_light *= env.x * f0 + env.y;
+ // scales the specular reflections, needs to be be computed before lighting happens,
+ // but after environment and reflection probes are added
+ //TODO: this curve is not really designed for gammaspace, should be adjusted
+ const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
+ const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
+ vec4 r = roughness * c0 + c1;
+ float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
+ vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
+ specular_light *= env.x * F + env.y;
#endif
- }
+ }
#ifdef USE_LIGHTMAP
- //ambient light will come entirely from lightmap is lightmap is used
- ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy;
+ //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, 0.0, 1.0),
- vec3(0.866025, 0.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, 0.0, -1.0),
- vec3(0.866025, 0.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;
- }
+ {
+ vec3 cone_dirs[12] = vec3[](
+ vec3(0.0, 0.0, 1.0),
+ vec3(0.866025, 0.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, 0.0, -1.0),
+ vec3(0.866025, 0.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;
+ captured /= sum;
- if (lightmap_capture_sky) {
- ambient_light = mix(ambient_light, captured.rgb, captured.a);
- } else {
- ambient_light = captured.rgb;
+ if (lightmap_capture_sky) {
+ ambient_light = mix(ambient_light, captured.rgb, captured.a);
+ } else {
+ ambient_light = captured.rgb;
+ }
}
- }
#endif
-
+ }
#endif //BASE PASS
//
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index edffe852a2..55d16a6c2e 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -128,7 +128,7 @@ void RasterizerCanvasGLES3::light_internal_update(RID p_rid, Light *p_light) {
li->ubo_data.shadow_distance_mult = (p_light->radius_cache * 1.1);
glBindBuffer(GL_UNIFORM_BUFFER, li->ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightInternal::UBOData), &li->ubo_data);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInternal::UBOData), &li->ubo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
@@ -326,6 +326,12 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun
glBindVertexArray(data.polygon_buffer_pointer_array);
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffers to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
+
uint32_t buffer_ofs = 0;
//vertex
@@ -417,6 +423,12 @@ void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count
glBindVertexArray(data.polygon_buffer_pointer_array);
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffers to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
+
uint32_t buffer_ofs = 0;
//vertex
@@ -508,6 +520,11 @@ void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_v
}
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+#ifndef GLES_OVER_GL
+ // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
+ glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
+#endif
+ //TODO the below call may need to be replaced with: glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), &b[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4, &b[0]);
glBindVertexArray(data.polygon_buffer_quad_arrays[version]);
glDrawArrays(prim[p_points], 0, p_points);
@@ -1882,7 +1899,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
state.canvas_item_ubo_data.time = storage->frame.time[0];
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
state.canvas_texscreen_used = false;
@@ -2109,6 +2126,8 @@ void RasterizerCanvasGLES3::initialize() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW); //allocate max size
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ data.polygon_index_buffer_size = index_size;
}
store_transform(Transform(), state.canvas_item_ubo_data.projection_matrix);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index bf5ef30820..382b1e5640 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -64,6 +64,7 @@ public:
GLuint particle_quad_array;
uint32_t polygon_buffer_size;
+ uint32_t polygon_index_buffer_size;
} data;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 519fdf2b3b..9815936d1e 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -2011,7 +2011,7 @@ void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_disabled, bool p_rever
}
}
-void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) {
+void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RasterizerStorageGLES3::Sky *p_sky, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) {
glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.scene_ubo); //bind globals ubo
@@ -2019,14 +2019,15 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
if (!p_shadow && !p_directional_add) {
glBindBufferBase(GL_UNIFORM_BUFFER, 2, state.env_radiance_ubo); //bind environment radiance info
- if (p_base_env) {
+ if (p_sky != NULL) {
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
if (storage->config.use_texture_array_environment) {
- glBindTexture(GL_TEXTURE_2D_ARRAY, p_base_env);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, p_sky->radiance);
} else {
- glBindTexture(GL_TEXTURE_2D, p_base_env);
+ glBindTexture(GL_TEXTURE_2D, p_sky->radiance);
}
-
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+ glBindTexture(GL_TEXTURE_2D, p_sky->irradiance);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, true);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, storage->config.use_texture_array_environment);
use_radiance_map = true;
@@ -2550,7 +2551,7 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
}
glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector3) * 8, vertices);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, vertices, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
glBindVertexArray(state.sky_array);
@@ -2690,7 +2691,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
}
glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::SceneDataUBO), &state.ubo_data);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.ubo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
//fill up environment
@@ -2698,7 +2699,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform);
glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
@@ -2808,7 +2809,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
}
glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightDataUBO), &ubo_data);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), &ubo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
directional_light = li;
@@ -4231,7 +4232,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
_fill_render_list(p_cull_result, p_cull_count, true, false);
render_list.sort_by_key(false);
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true);
- _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, 0, false, false, true, false, false);
+ _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, NULL, false, false, true, false, false);
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false);
glColorMask(1, 1, 1, 1);
@@ -4355,7 +4356,6 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
RasterizerStorageGLES3::Sky *sky = NULL;
Ref<CameraFeed> feed;
- GLuint env_radiance_tex = 0;
if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
clear_color = Color(0, 0, 0, 0);
@@ -4409,9 +4409,6 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
sky = storage->sky_owner.getornull(env->sky);
- if (sky) {
- env_radiance_tex = sky->radiance;
- }
break;
case VS::ENV_BG_CANVAS:
//copy canvas to 3d buffer and convert it to linear
@@ -4505,7 +4502,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
}
if (probe && probe->probe_ptr->interior) {
- env_radiance_tex = 0; //for rendering probe interiors, radiance must not be used.
+ sky = NULL; //for rendering probe interiors, radiance must not be used.
}
state.texscreen_copied = false;
@@ -4524,7 +4521,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
if (state.directional_light_count == 0) {
directional_light = NULL;
- _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, false, shadow_atlas != NULL);
+ _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, false, shadow_atlas != NULL);
} else {
for (int i = 0; i < state.directional_light_count; i++) {
directional_light = directional_lights[i];
@@ -4532,7 +4529,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glEnable(GL_BLEND);
}
_setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
- _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, i > 0, shadow_atlas != NULL);
+ _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, i > 0, shadow_atlas != NULL);
}
}
@@ -4610,12 +4607,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
if (state.directional_light_count == 0) {
directional_light = NULL;
- _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, false, shadow_atlas != NULL);
+ _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, false, shadow_atlas != NULL);
} else {
for (int i = 0; i < state.directional_light_count; i++) {
directional_light = directional_lights[i];
_setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
- _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != NULL);
+ _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, shadow_atlas != NULL);
}
}
@@ -4898,7 +4895,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
if (light->reverse_cull) {
flip_facing = !flip_facing;
}
- _render_list(render_list.elements, render_list.element_count, light_transform, light_projection, 0, flip_facing, false, true, false, false);
+ _render_list(render_list.elements, render_list.element_count, light_transform, light_projection, NULL, flip_facing, false, true, false, false);
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false);
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID, false);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index e6d2449653..a756ce251e 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -837,7 +837,7 @@ public:
_FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform);
- void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
+ void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RasterizerStorageGLES3::Sky *p_sky, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
_FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 71737426a9..4509c9d17e 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1757,6 +1757,7 @@ RID RasterizerStorageGLES3::sky_create() {
Sky *sky = memnew(Sky);
sky->radiance = 0;
+ sky->irradiance = 0;
return sky_owner.make_rid(sky);
}
@@ -1768,7 +1769,9 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
if (sky->panorama.is_valid()) {
sky->panorama = RID();
glDeleteTextures(1, &sky->radiance);
+ glDeleteTextures(1, &sky->irradiance);
sky->radiance = 0;
+ sky->irradiance = 0;
}
sky->panorama = p_panorama;
@@ -1791,10 +1794,14 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //need this for proper sampling
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10);
+ // Need Mipmaps regardless of whether they are set in import by user
+ glGenerateMipmap(texture->target);
+ glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameterf(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) {
@@ -1808,6 +1815,66 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
#endif
}
+ {
+ //Irradiance map
+ glActiveTexture(GL_TEXTURE1);
+ glGenTextures(1, &sky->irradiance);
+ glBindTexture(GL_TEXTURE_2D, sky->irradiance);
+
+ GLuint tmp_fb;
+
+ glGenFramebuffers(1, &tmp_fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
+
+ int size = 64;
+
+ bool use_float = config.framebuffer_half_float_supported;
+
+ GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
+ GLenum format = GL_RGBA;
+ GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
+
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->irradiance, 0);
+
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, true);
+ shaders.cubemap_filter.bind();
+
+ // Very large Panoramas require way too much effort to compute irradiance so use a mipmap
+ // level that corresponds to a panorama of 1024x512
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, MAX(Math::floor(Math::log(float(texture->width)) / Math::log(2.0f)) - 10.0f, 0.0f));
+
+ for (int i = 0; i < 2; i++) {
+ glViewport(0, i * size, size, size);
+ glBindVertexArray(resources.quadie_array);
+
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glBindVertexArray(0);
+ }
+
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, false);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+ glDeleteFramebuffers(1, &tmp_fb);
+ }
+
+ // Now compute radiance
+
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &sky->radiance);
@@ -1833,8 +1900,8 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internal_format, size, size * 2, array_level, 0, format, type, NULL);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLuint tmp_fb2;
GLuint tmp_tex;
@@ -1846,8 +1913,8 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glBindTexture(GL_TEXTURE_2D, tmp_tex);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
@@ -1858,25 +1925,25 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
- if (j == 0) {
+ if (j < 3) {
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, true);
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false);
shaders.cubemap_filter.bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4));
} else {
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, false);
shaders.cubemap_filter.bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_ARRAY_INDEX, j - 1); //read from previous to ensure better blur
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(size / 2));
}
for (int i = 0; i < 2; i++) {
@@ -1902,7 +1969,6 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, false);
//restore ranges
glActiveTexture(GL_TEXTURE0);
@@ -1947,23 +2013,64 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ GLuint tmp_fb2;
+ GLuint tmp_tex;
+ {
+ // Need a temporary framebuffer for rendering so we can read from previous iterations
+ glGenFramebuffers(1, &tmp_fb2);
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
+ glGenTextures(1, &tmp_tex);
+ glBindTexture(GL_TEXTURE_2D, tmp_tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#ifdef DEBUG_ENABLED
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+#endif
+ }
lod = 0;
mm_level = mipmaps;
size = p_radiance_size;
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
- shaders.cubemap_filter.bind();
-
while (mm_level) {
-
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->radiance, lod);
+
#ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
#endif
+ glBindTexture(GL_TEXTURE_2D, tmp_tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
+ if (lod < 3) {
+
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, false);
+ shaders.cubemap_filter.bind();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->tex_id);
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4));
+ } else {
+
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, true);
+ shaders.cubemap_filter.bind();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, sky->radiance);
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, float(lod - 1)); //read from previous to ensure better blur
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(size));
+ }
for (int i = 0; i < 2; i++) {
glViewport(0, i * size, size, size);
@@ -1976,6 +2083,14 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glBindVertexArray(0);
}
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tmp_fb);
+ glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, sky->radiance, 0, lod);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, tmp_fb2);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glBlitFramebuffer(0, 0, size, size * 2, 0, 0, size, size * 2, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
if (size > 1)
size >>= 1;
lod++;
@@ -1995,6 +2110,8 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
glDeleteFramebuffers(1, &tmp_fb);
+ glDeleteFramebuffers(1, &tmp_fb2);
+ glDeleteTextures(1, &tmp_tex);
}
}
@@ -3099,7 +3216,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
}
glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, material->ubo_size, local_ubo);
+ glBufferData(GL_UNIFORM_BUFFER, material->ubo_size, local_ubo, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 3b1021d0e1..350b259b2b 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -388,6 +388,7 @@ public:
RID panorama;
GLuint radiance;
+ GLuint irradiance;
int radiance_size;
};
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index 619e29b130..f94ac8c81c 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -30,12 +30,22 @@ uniform sampler2DArray source_dual_paraboloid_array; //texunit:0
uniform int source_array_index;
#endif
-#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
+#ifdef USE_SOURCE_DUAL_PARABOLOID
+uniform sampler2D source_dual_paraboloid; //texunit:0
+#endif
+
+#if defined(USE_SOURCE_DUAL_PARABOLOID) || defined(COMPUTE_IRRADIANCE)
+uniform float source_mip_level;
+#endif
+
+#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID)
uniform samplerCube source_cube; //texunit:0
#endif
uniform int face_id;
uniform float roughness;
+uniform float source_resolution;
+
in highp vec2 uv_interp;
layout(location = 0) out vec4 frag_color;
@@ -133,6 +143,19 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
return TangentX * H.x + TangentY * H.y + N * H.z;
}
+float DistributionGGX(vec3 N, vec3 H, float roughness) {
+ float a = roughness * roughness;
+ float a2 = a * a;
+ float NdotH = max(dot(N, H), 0.0);
+ float NdotH2 = NdotH * NdotH;
+
+ float nom = a2;
+ float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+ denom = M_PI * denom * denom;
+
+ return nom / denom;
+}
+
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float GGX(float NdotV, float a) {
float k = a / 2.0;
@@ -160,10 +183,12 @@ vec2 Hammersley(uint i, uint N) {
#ifdef LOW_QUALITY
#define SAMPLE_COUNT 64u
+#define SAMPLE_DELTA 0.05
#else
-#define SAMPLE_COUNT 1024u
+#define SAMPLE_COUNT 512u
+#define SAMPLE_DELTA 0.01
#endif
@@ -171,7 +196,7 @@ uniform bool z_flip;
#ifdef USE_SOURCE_PANORAMA
-vec4 texturePanorama(vec3 normal, sampler2D pano) {
+vec4 texturePanorama(vec3 normal, sampler2D pano, float mipLevel) {
vec2 st = vec2(
atan(normal.x, normal.z),
@@ -182,7 +207,7 @@ vec4 texturePanorama(vec3 normal, sampler2D pano) {
st /= vec2(M_PI * 2.0, M_PI);
- return textureLod(pano, st, 0.0);
+ return textureLod(pano, st, mipLevel);
}
#endif
@@ -202,6 +227,20 @@ vec4 textureDualParaboloidArray(vec3 normal) {
#endif
+#ifdef USE_SOURCE_DUAL_PARABOLOID
+vec4 textureDualParaboloid(vec3 normal) {
+
+ vec3 norm = normalize(normal);
+ norm.xy /= 1.0 + abs(norm.z);
+ norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25);
+ if (norm.z < 0.0) {
+ norm.y = 0.5 - norm.y + 0.5;
+ }
+ return textureLod(source_dual_paraboloid, norm.xy, source_mip_level);
+}
+
+#endif
+
void main() {
#ifdef USE_DUAL_PARABOLOID
@@ -225,7 +264,7 @@ void main() {
#ifdef USE_SOURCE_PANORAMA
- frag_color = vec4(texturePanorama(N, source_panorama).rgb, 1.0);
+ frag_color = vec4(texturePanorama(N, source_panorama, 0.0).rgb, 1.0);
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
@@ -233,12 +272,51 @@ void main() {
frag_color = vec4(textureDualParaboloidArray(N).rgb, 1.0);
#endif
-#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
+#ifdef USE_SOURCE_DUAL_PARABOLOID
+
+ frag_color = vec4(textureDualParaboloid(N).rgb, 1.0);
+#endif
+
+#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID)
N.y = -N.y;
frag_color = vec4(texture(N, source_cube).rgb, 1.0);
#endif
+#else // USE_DIRECT_WRITE
+
+#ifdef COMPUTE_IRRADIANCE
+
+ vec3 irradiance = vec3(0.0);
+
+ // tangent space calculation from origin point
+ vec3 UpVector = vec3(0.0, 1.0, 0.0);
+ vec3 TangentX = cross(UpVector, N);
+ vec3 TangentY = cross(N, TangentX);
+
+ float num_samples = 0.0f;
+
+ for (float phi = 0.0; phi < 2.0 * M_PI; phi += SAMPLE_DELTA) {
+ for (float theta = 0.0; theta < 0.5 * M_PI; theta += SAMPLE_DELTA) {
+ // Calculate sample positions
+ vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
+ // Find world vector of sample position
+ vec3 H = tangentSample.x * TangentX + tangentSample.y * TangentY + tangentSample.z * N;
+
+ vec2 st = vec2(atan(H.x, H.z), acos(H.y));
+ if (st.x < 0.0) {
+ st.x += M_PI * 2.0;
+ }
+ st /= vec2(M_PI * 2.0, M_PI);
+
+ irradiance += texture(source_panorama, st, source_mip_level).rgb * cos(theta) * sin(theta);
+ num_samples++;
+ }
+ }
+ irradiance = M_PI * irradiance * (1.0 / float(num_samples));
+
+ frag_color = vec4(irradiance, 1.0);
+
#else
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
@@ -246,15 +324,26 @@ void main() {
for (uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) {
vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
- vec3 H = ImportanceSampleGGX(xi, roughness, N);
+ vec3 H = normalize(ImportanceSampleGGX(xi, roughness, N));
vec3 V = N;
- vec3 L = (2.0 * dot(V, H) * H - V);
+ vec3 L = normalize(2.0 * dot(V, H) * H - V);
- float ndotl = clamp(dot(N, L), 0.0, 1.0);
+ float ndotl = max(dot(N, L), 0.0);
if (ndotl > 0.0) {
+
+ float D = DistributionGGX(N, H, roughness);
+ float ndoth = max(dot(N, H), 0.0);
+ float hdotv = max(dot(H, V), 0.0);
+ float pdf = D * ndoth / (4.0 * hdotv) + 0.0001;
+
+ float saTexel = 4.0 * M_PI / (6.0 * source_resolution * source_resolution);
+ float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
+
+ float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
+
#ifdef USE_SOURCE_PANORAMA
- sum.rgb += texturePanorama(L, source_panorama).rgb * ndotl;
+ sum.rgb += texturePanorama(L, source_panorama, mipLevel).rgb * ndotl;
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
@@ -262,7 +351,12 @@ void main() {
sum.rgb += textureDualParaboloidArray(L).rgb * ndotl;
#endif
-#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
+#ifdef USE_SOURCE_DUAL_PARABOLOID
+
+ sum.rgb += textureDualParaboloid(L).rgb * ndotl;
+#endif
+
+#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID)
L.y = -L.y;
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
#endif
@@ -273,5 +367,6 @@ void main() {
frag_color = vec4(sum.rgb, 1.0);
-#endif
+#endif // COMPUTE_IRRADIANCE
+#endif // USE_DIRECT_WRITE
}
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 403de25dd0..e1b0e9f595 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -627,6 +627,8 @@ layout(std140) uniform Radiance { // ubo:2
#define RADIANCE_MAX_LOD 5.0
+uniform sampler2D irradiance_map; // texunit:-6
+
#ifdef USE_RADIANCE_MAP_ARRAY
uniform sampler2DArray radiance_map; // texunit:-2
@@ -1766,6 +1768,11 @@ FRAGMENT_SHADER_CODE
vec3 eye_vec = view;
+ // IBL precalculations
+ float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0);
+ vec3 f0 = F0(metallic, specular, albedo);
+ vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0);
+
#ifdef USE_RADIANCE_MAP
#ifdef AMBIENT_LIGHT_DISABLED
@@ -1775,22 +1782,27 @@ FRAGMENT_SHADER_CODE
{ //read radiance from dual paraboloid
- vec3 ref_vec = reflect(-eye_vec, normal); //2.0 * ndotv * normal - view; // reflect(v, n);
+ vec3 ref_vec = reflect(-eye_vec, normal);
ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz);
vec3 radiance = textureDualParaboloid(radiance_map, ref_vec, roughness) * bg_energy;
env_reflection_light = radiance;
}
- //no longer a cubemap
- //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y);
}
#ifndef USE_LIGHTMAP
{
- vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
- vec3 env_ambient = textureDualParaboloid(radiance_map, ambient_dir, 1.0) * bg_energy;
+ vec3 norm = normal;
+ norm = normalize((radiance_inverse_xform * vec4(norm, 0.0)).xyz);
+ norm.xy /= 1.0 + abs(norm.z);
+ norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25);
+ if (norm.z > 0.0) {
+ norm.y = 0.5 - norm.y + 0.5;
+ }
+
+ vec3 env_ambient = texture(irradiance_map, norm.xy).rgb * bg_energy;
+ env_ambient *= 1.0 - F;
ambient_light = mix(ambient_light_color.rgb, env_ambient, radiance_ambient_contribution);
- //ambient_light=vec3(0.0,0.0,0.0);
}
#endif
#endif //AMBIENT_LIGHT_DISABLED
@@ -1892,12 +1904,9 @@ FRAGMENT_SHADER_CODE
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
vec4 r = roughness * c0 + c1;
- float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0);
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
-
- vec3 f0 = F0(metallic, specular, albedo);
- specular_light *= env.x * f0 + env.y;
+ specular_light *= env.x * F + env.y;
#endif
}