|
@@ -1275,87 +1275,200 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
glGenTextures(1, &sky->radiance);
|
|
|
- glBindTexture(GL_TEXTURE_2D, sky->radiance);
|
|
|
|
|
|
- GLuint tmp_fb;
|
|
|
+ if (config.use_texture_array_environment) {
|
|
|
|
|
|
- glGenFramebuffers(1, &tmp_fb);
|
|
|
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
|
|
|
+ //texture3D
|
|
|
+ glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
|
|
|
|
|
|
- int size = p_radiance_size;
|
|
|
+ GLuint tmp_fb;
|
|
|
|
|
|
- int lod = 0;
|
|
|
+ glGenFramebuffers(1, &tmp_fb);
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
|
|
|
|
|
|
- int mipmaps = 6;
|
|
|
+ int size = p_radiance_size;
|
|
|
|
|
|
- int mm_level = mipmaps;
|
|
|
+ int array_level = 6;
|
|
|
|
|
|
- bool use_float = config.hdr_supported;
|
|
|
+ bool use_float = config.hdr_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;
|
|
|
+ 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;
|
|
|
|
|
|
- while (mm_level) {
|
|
|
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internal_format, size, size * 2, array_level, 0, format, type, NULL);
|
|
|
|
|
|
- glTexImage2D(GL_TEXTURE_2D, lod, internal_format, size, size * 2, 0, format, type, NULL);
|
|
|
- lod++;
|
|
|
- mm_level--;
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
|
- if (size > 1)
|
|
|
- size >>= 1;
|
|
|
- }
|
|
|
+ GLuint tmp_fb2;
|
|
|
+ GLuint tmp_tex;
|
|
|
+ {
|
|
|
+ //generate another one for rendering, as can't read and write from a single texarray it seems
|
|
|
+ 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_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
|
+ ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
|
|
|
+#endif
|
|
|
+ }
|
|
|
|
|
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod - 1);
|
|
|
+ for (int j = 0; j < array_level; j++) {
|
|
|
|
|
|
- lod = 0;
|
|
|
- mm_level = mipmaps;
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
|
|
|
|
|
|
- size = p_radiance_size;
|
|
|
+ if (j == 0) {
|
|
|
|
|
|
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
|
|
|
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_PANORAMA, true);
|
|
|
- shaders.cubemap_filter.bind();
|
|
|
+ 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);
|
|
|
+ } else {
|
|
|
|
|
|
- while (mm_level) {
|
|
|
+ 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
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, j / float(array_level - 1));
|
|
|
+
|
|
|
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
+ glBindVertexArray(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tmp_fb);
|
|
|
+ glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, sky->radiance, 0, j);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+ glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
|
|
|
+
|
|
|
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
|
|
+
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
+
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
|
|
+ glDeleteFramebuffers(1, &tmp_fb);
|
|
|
+ glDeleteFramebuffers(1, &tmp_fb2);
|
|
|
+ glDeleteTextures(1, &tmp_tex);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //regular single texture with mipmaps
|
|
|
+ glBindTexture(GL_TEXTURE_2D, sky->radiance);
|
|
|
+
|
|
|
+ GLuint tmp_fb;
|
|
|
|
|
|
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->radiance, lod);
|
|
|
+ glGenFramebuffers(1, &tmp_fb);
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
|
|
|
+
|
|
|
+ int size = p_radiance_size;
|
|
|
+
|
|
|
+ int lod = 0;
|
|
|
+
|
|
|
+ int mipmaps = 6;
|
|
|
+
|
|
|
+ int mm_level = mipmaps;
|
|
|
+
|
|
|
+ bool use_float = config.hdr_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;
|
|
|
+
|
|
|
+ while (mm_level) {
|
|
|
+
|
|
|
+ glTexImage2D(GL_TEXTURE_2D, lod, internal_format, size, size * 2, 0, format, type, NULL);
|
|
|
+ lod++;
|
|
|
+ mm_level--;
|
|
|
+
|
|
|
+ if (size > 1)
|
|
|
+ size >>= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod - 1);
|
|
|
+
|
|
|
+ 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) {
|
|
|
+
|
|
|
+ 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);
|
|
|
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
|
+ ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
|
|
|
#endif
|
|
|
|
|
|
- for (int i = 0; i < 2; i++) {
|
|
|
- glViewport(0, i * size, size, size);
|
|
|
- glBindVertexArray(resources.quadie_array);
|
|
|
+ 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);
|
|
|
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, lod / float(mipmaps - 1));
|
|
|
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0);
|
|
|
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, lod / float(mipmaps - 1));
|
|
|
|
|
|
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
- glBindVertexArray(0);
|
|
|
- }
|
|
|
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
+ glBindVertexArray(0);
|
|
|
+ }
|
|
|
|
|
|
- if (size > 1)
|
|
|
- size >>= 1;
|
|
|
- lod++;
|
|
|
- mm_level--;
|
|
|
- }
|
|
|
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
|
|
|
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_PANORAMA, false);
|
|
|
+ if (size > 1)
|
|
|
+ size >>= 1;
|
|
|
+ lod++;
|
|
|
+ mm_level--;
|
|
|
+ }
|
|
|
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
|
|
|
+ shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
|
|
|
|
|
|
- //restore ranges
|
|
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod - 1);
|
|
|
+ //restore ranges
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod - 1);
|
|
|
|
|
|
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
|
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
- 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_MIPMAP_LINEAR);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
|
|
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
|
|
- glDeleteFramebuffers(1, &tmp_fb);
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
|
|
+ glDeleteFramebuffers(1, &tmp_fb);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* SHADER API */
|
|
@@ -6857,6 +6970,7 @@ void RasterizerStorageGLES3::initialize() {
|
|
|
frame.current_rt = NULL;
|
|
|
config.keep_original_textures = false;
|
|
|
config.generate_wireframes = false;
|
|
|
+ config.use_texture_array_environment = GLOBAL_DEF("rendering/quality/texture_array_environments", true);
|
|
|
}
|
|
|
|
|
|
void RasterizerStorageGLES3::finalize() {
|