Browse Source

Implemented environment arrays for skybox reflection and roughness, quality increase is enormous.

Juan Linietsky 8 years ago
parent
commit
7263137dba

+ 4 - 3
core/math/matrix3.cpp

@@ -451,9 +451,10 @@ Basis::operator String() const {
 }
 
 Basis::operator Quat() const {
-#ifdef MATH_CHECKS
-	ERR_FAIL_COND_V(is_rotation() == false, Quat());
-#endif
+	//commenting this check because precision issues cause it to fail when it shouldn't
+	//#ifdef MATH_CHECKS
+	//ERR_FAIL_COND_V(is_rotation() == false, Quat());
+	//#endif
 	real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
 	real_t temp[4];
 

+ 8 - 1
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -1884,14 +1884,21 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 
 		if (p_base_env) {
 			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
-			glBindTexture(GL_TEXTURE_2D, p_base_env);
+			if (storage->config.use_texture_array_environment) {
+				glBindTexture(GL_TEXTURE_2D_ARRAY, p_base_env);
+			} else {
+				glBindTexture(GL_TEXTURE_2D, p_base_env);
+			}
 			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);
 		} else {
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false);
+			state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false);
 		}
 	} else {
 
 		state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false);
+		state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false);
 	}
 
 	state.cull_front = false;

+ 169 - 55
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -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() {

+ 2 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -86,6 +86,8 @@ public:
 
 		bool generate_wireframes;
 
+		bool use_texture_array_environment;
+
 		Set<String> extensions;
 
 		bool keep_original_textures;

+ 48 - 8
drivers/gles3/shaders/cubemap_filter.glsl

@@ -19,9 +19,16 @@ void main() {
 precision highp float;
 precision highp int;
 
-#ifdef USE_PANORAMA
+#ifdef USE_SOURCE_PANORAMA
 uniform sampler2D source_panorama; //texunit:0
-#else
+#endif
+
+#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
+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)
 uniform samplerCube source_cube; //texunit:0
 #endif
 
@@ -169,7 +176,7 @@ vec2 Hammersley(uint i, uint N) {
 
 uniform bool z_flip;
 
-#ifdef USE_PANORAMA
+#ifdef USE_SOURCE_PANORAMA
 
 vec4 texturePanorama(vec3 normal,sampler2D pano ) {
 
@@ -189,6 +196,21 @@ vec4 texturePanorama(vec3 normal,sampler2D pano ) {
 
 #endif
 
+#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
+
+
+vec4 textureDualParaboloidArray(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);
+	norm.y+=max(0.0,sign(-norm.z))*0.5;
+	return textureLod(source_dual_paraboloid_array, vec3(norm.xy, float(source_array_index) ), 0.0);
+
+}
+
+#endif
+
 void main() {
 
 #ifdef USE_DUAL_PARABOLOID
@@ -198,7 +220,7 @@ void main() {
 	N = normalize(N);
 
 	if (!z_flip) {
-		N.y=-N.y; //y is flipped to improve blending between both sides
+		//N.y=-N.y; //y is flipped to improve blending between both sides
 	} else {
 		N.z=-N.z;
 	}
@@ -212,13 +234,24 @@ void main() {
 
 #ifdef USE_DIRECT_WRITE
 
-#ifdef USE_PANORAMA
+#ifdef USE_SOURCE_PANORAMA
 
 	frag_color=vec4(texturePanorama(N,source_panorama).rgb,1.0);
-#else
+#endif
+
+#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
+
+	frag_color=vec4(textureDualParaboloidArray(N).rgb,1.0);
+#endif
+
+#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
+
 	frag_color=vec4(texture(N,source_cube).rgb,1.0);
 #endif
 
+
+
+
 #else
 
 	vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
@@ -233,9 +266,16 @@ void main() {
 		float ndotl = clamp(dot(N, L),0.0,1.0);
 
 		if (ndotl>0.0) {
-#ifdef USE_PANORAMA
+#ifdef USE_SOURCE_PANORAMA
 			sum.rgb += texturePanorama(H,source_panorama).rgb *ndotl;
-#else
+#endif
+
+#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
+
+			sum.rgb += textureDualParaboloidArray(H).rgb *ndotl;
+#endif
+
+#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
 			sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl;
 #endif
 			sum.a += ndotl;

+ 45 - 23
drivers/gles3/shaders/scene.glsl

@@ -405,7 +405,6 @@ uniform bool no_ambient_light;
 
 #ifdef USE_RADIANCE_MAP
 
-uniform sampler2D radiance_map; //texunit:-2
 
 
 layout(std140) uniform Radiance { //ubo:2
@@ -415,6 +414,49 @@ layout(std140) uniform Radiance { //ubo:2
 
 };
 
+#define RADIANCE_MAX_LOD 5.0
+
+#ifdef USE_RADIANCE_MAP_ARRAY
+
+uniform sampler2DArray radiance_map; //texunit:-2
+
+vec3 textureDualParaboloid(sampler2DArray p_tex, vec3 p_vec,float p_roughness) {
+
+	vec3 norm = normalize(p_vec);
+	norm.xy/=1.0+abs(norm.z);
+	norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25);
+
+	// we need to lie the derivatives (normg) and assume that DP side is always the same
+	// to get proper texure filtering
+	vec2 normg=norm.xy;
+	norm.y+=max(0.0,sign(norm.z))*0.5;
+
+	// thanks to OpenGL spec using floor(layer + 0.5) for texture arrays,
+	// it's easy to have precision errors using fract() to interpolate layers
+	// as such, using fixed point to ensure it works.
+
+	float index = p_roughness * RADIANCE_MAX_LOD;
+	int indexi = int(index * 256.0);
+	vec3 base = textureGrad(p_tex, vec3(norm.xy, float(indexi/256)),dFdx(normg),dFdy(normg)).xyz;
+	vec3 next = textureGrad(p_tex, vec3(norm.xy, float(indexi/256+1)),dFdx(normg),dFdy(normg)).xyz;
+	return mix(base,next,float(indexi%256)/256.0);
+}
+
+#else
+
+uniform sampler2D radiance_map; //texunit:-2
+
+vec3 textureDualParaboloid(sampler2D p_tex, vec3 p_vec,float p_roughness) {
+
+	vec3 norm = normalize(p_vec);
+	norm.xy/=1.0+abs(norm.z);
+	norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25);
+	norm.y+=max(0.0,sign(norm.z))*0.5;
+	return textureLod(p_tex, norm.xy, p_roughness * RADIANCE_MAX_LOD).xyz;
+}
+
+#endif
+
 #endif
 
 /* Material Uniforms */
@@ -1231,23 +1273,7 @@ void gi_probes_compute(vec3 pos, vec3 normal, float roughness, inout vec3 out_sp
 
 #endif
 
-vec3 textureDualParabolod(sampler2D p_tex, vec3 p_vec,float p_lod) {
-
-	vec3 norm = normalize(p_vec);
-	float y_ofs=0.0;
-	if (norm.z>=0.0) {
-
-		norm.z+=1.0;
-		y_ofs+=0.5;
-	} else {
-		norm.z=1.0 - norm.z;
-		norm.y=-norm.y;
-	}
 
-	norm.xy/=norm.z;
-	norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25+y_ofs);
-	return textureLod(p_tex, norm.xy, p_lod).xyz;
-}
 
 void main() {
 
@@ -1387,15 +1413,11 @@ FRAGMENT_SHADER_CODE
 	} else {
 		{
 
-
-#define RADIANCE_MAX_LOD 5.0
-			float lod = roughness * RADIANCE_MAX_LOD;
-
 			{ //read radiance from dual paraboloid
 
 				vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n);
 				ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz);
-				vec3 radiance = textureDualParabolod(radiance_map,ref_vec,lod) * bg_energy;
+				vec3 radiance = textureDualParaboloid(radiance_map,ref_vec,roughness) * bg_energy;
 				specular_light = radiance;
 
 			}
@@ -1407,7 +1429,7 @@ FRAGMENT_SHADER_CODE
 		{
 
 			vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz);
-			vec3 env_ambient=textureDualParabolod(radiance_map,ambient_dir,RADIANCE_MAX_LOD) * bg_energy;
+			vec3 env_ambient=textureDualParaboloid(radiance_map,ambient_dir,1.0) * bg_energy;
 
 			ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution);
 			//ambient_light=vec3(0.0,0.0,0.0);

+ 7 - 6
scene/3d/mesh_instance.cpp

@@ -340,12 +340,13 @@ void MeshInstance::create_debug_tagents() {
 		mi->set_mesh(am);
 		mi->set_name("DebugTangents");
 		add_child(mi);
-		if (get_parent()) {
-			if (get_parent() == get_tree()->get_edited_scene_root())
-				mi->set_owner(get_parent());
-			else
-				mi->set_owner(get_parent()->get_owner());
-		}
+#ifdef TOOLS_ENABLED
+
+		if (this == get_tree()->get_edited_scene_root())
+			mi->set_owner(this);
+		else
+			mi->set_owner(get_owner());
+#endif
 	}
 }
 

+ 1 - 1
scene/resources/environment.cpp

@@ -818,7 +818,7 @@ float Environment::get_fog_height_curve() const {
 void Environment::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background);
-	ClassDB::bind_method(D_METHOD("set_sky", "sky:CubeMap"), &Environment::set_sky);
+	ClassDB::bind_method(D_METHOD("set_sky", "sky:Sky"), &Environment::set_sky);
 	ClassDB::bind_method(D_METHOD("set_sky_scale", "scale"), &Environment::set_sky_scale);
 	ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color);
 	ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy);