Browse Source

Merge pull request #35302 from clayjohn/GLES3-env-map

Reduce complexity of irradiance map generation
Rémi Verschelde 5 years ago
parent
commit
4d052e51a2

+ 41 - 2
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -1834,7 +1834,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 		glGenFramebuffers(1, &tmp_fb);
 		glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
 
-		int size = 64;
+		int size = 32;
 
 		bool use_float = config.framebuffer_half_float_supported;
 
@@ -1854,6 +1854,24 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->irradiance, 0);
 
+		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, p_radiance_size, 2.0 * p_radiance_size, 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_MIPMAP_LINEAR);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+#ifdef DEBUG_ENABLED
+			GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+			ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+#endif
+		}
+
 		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);
@@ -1863,8 +1881,10 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 		// 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));
 
+		// Compute Irradiance for a large texture, specified by radiance size and then pull out a low mipmap corresponding to 32x32
+		int vp_size = p_radiance_size;
 		for (int i = 0; i < 2; i++) {
-			glViewport(0, i * size, size, size);
+			glViewport(0, i * vp_size, vp_size, vp_size);
 			glBindVertexArray(resources.quadie_array);
 
 			shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0);
@@ -1872,13 +1892,32 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
 			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 			glBindVertexArray(0);
 		}
+		glGenerateMipmap(GL_TEXTURE_2D);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D, tmp_tex);
+		glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
 
 		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);
 
+		shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, true);
+		shaders.copy.bind();
+		shaders.copy.set_uniform(CopyShaderGLES3::MIP_LEVEL, MAX(Math::floor(Math::log(float(p_radiance_size)) / Math::log(2.0f)) - 5.0f, 0.0f)); // Mip level that corresponds to a 32x32 texture
+
+		glViewport(0, 0, size, size * 2.0);
+		glBindVertexArray(resources.quadie_array);
+		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+		glBindVertexArray(0);
+
+		shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, false);
+
 		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(texture->target, texture->tex_id);
 		glDeleteFramebuffers(1, &tmp_fb);
+		glDeleteFramebuffers(1, &tmp_fb2);
+		glDeleteTextures(1, &tmp_tex);
 	}
 
 	// Now compute radiance

+ 8 - 0
drivers/gles3/shaders/copy.glsl

@@ -104,6 +104,10 @@ uniform sampler2D CbCr; //texunit:1
 
 /* clang-format on */
 
+#ifdef USE_LOD
+uniform float mip_level;
+#endif
+
 #if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY)
 uniform float layer;
 #endif
@@ -189,9 +193,13 @@ void main() {
 	color.r = textureLod(source, uv_interp, 0.0).r;
 	color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5);
 	color.a = 1.0;
+#else
+#ifdef USE_LOD
+	vec4 color = textureLod(source, uv_interp, mip_level);
 #else
 	vec4 color = textureLod(source, uv_interp, 0.0);
 #endif
+#endif
 
 #ifdef LINEAR_TO_SRGB
 	// regular Linear -> SRGB conversion

+ 2 - 2
drivers/gles3/shaders/cubemap_filter.glsl

@@ -183,12 +183,12 @@ vec2 Hammersley(uint i, uint N) {
 #ifdef LOW_QUALITY
 
 #define SAMPLE_COUNT 64u
-#define SAMPLE_DELTA 0.05
+#define SAMPLE_DELTA 0.1
 
 #else
 
 #define SAMPLE_COUNT 512u
-#define SAMPLE_DELTA 0.01
+#define SAMPLE_DELTA 0.03
 
 #endif