Hello,

I'm trying to carry this magnifying glass shader to Godot 3:

But I'm not an expert in shader and despite my attempts to adapt the rendering doesn't seem to work. However I think I'm not far from the goal, would anyone know how to find the problem?

Here is the Godot archive of my test: http://www.loicjoint.com/clients/Yan/loupe_test.zip

It's for an important project, it would be really great if someone could help me.

Thank you very much!

Well, I had a free moment and I like messing with shaders, even if I'm not the best at it by any means... :sunglasses: Here is the shader and controller script updated to work with Godot 3.0. Hopefully it helps.

Shader:


shader_type canvas_item;

uniform vec2 mouse_pos = vec2(0.0, 0.0);
uniform float aspect_ratios = 1.0;

vec2 zoom_point(vec2 uv, vec2 point, float zoom)
{
	return (uv - point) / zoom + point;
}

void fragment()
{
	vec2 uv = SCREEN_UV;
	float lens_radius = 0.08;
	float mouse_dist = distance(uv*vec2(1.0, aspect_ratios), mouse_pos*vec2(1.0, aspect_ratios));
	
	if (mouse_dist < lens_radius)
	{
		float zoom = 2.0;
		vec2 zoomed = zoom_point(uv, mouse_pos, zoom);
		COLOR = vec4(texture(SCREEN_TEXTURE, zoomed).rgb, 1.0);
	}
	else if (mouse_dist < lens_radius + 0.004)
	{
		COLOR = vec4(0.0, 0.0, 0.0, 1.0);
	}
	else
	{
		discard;
		//COLOR = vec4(0.0, 0.0, 0.0, 0.35);
		//COLOR = vec4(textureLod(SCREEN_TEXTURE, uv, 2).rgb, 1.0);
	}
}

Controller script:


extends TextureRect

var shader_material;
var screen_size;

func _ready():
	screen_size = OS.window_size;
	shader_material = material;
	shader_material.set_shader_param("aspect_ratios", screen_size.y / screen_size.x);

func _input(event):
	if (event is InputEventMouseMotion):
		var norm_mouse = get_viewport().get_mouse_position() / screen_size;
		norm_mouse.y = 1.0 - norm_mouse.y;
		shader_material.set_shader_param("mouse_pos", norm_mouse);
		update();

Yes !! It works perfectly, a thousand thanks to you TwistedTwigleg, it's really a great service you're doing for me here! Thank you again! :)

@LOIC said: Yes !! It works perfectly, a thousand thanks to you TwistedTwigleg, it's really a great service you're doing for me here! Thank you again! :)

No problem! I'm glad it works :smile:

11 days later

@TwistedTwigleg said:

No problem! I'm glad it works :smile:

Thanks again for your help ;)

I have another problem, not very bad I think, but I try to use this shader twice at the same time in the same scene (basically, it's two magnifying glasses side by side, like binoculars). Is this possible from this script?

I have done several tests with several methods but each time I only get one magnifying glass... I'm really not very good at shading.

Thank you again a thousand times!

@LOIC said: I have another problem, not very bad I think, but I try to use this shader twice at the same time in the same scene (basically, it's two magnifying glasses side by side, like binoculars). Is this possible from this script?

I have done several tests with several methods but each time I only get one magnifying glass... I'm really not very good at shading.

I think the reasons you cannot have two magnifying glasses at the same time is because each magnifying glass uses the SCREEN_TEXTURE property in the shader. Normally only one shader can access the screen texture at a time, so to get around this you'll likely need to use a BackBufferCopy (documentation) node or place each of the magnifying glasses on their own CanvasLayer node.

I opened a issue on GitHub about this awhile ago and in Godot 3.1, using either the BackBufferCopy or the CanvasLayer node should fix the issue.

Hopefully this helps :smile:

Or, you know, one idea is to use a single screen_texture and use a mask to make it into a binocular view..?

@TwistedTwigleg said: I think the reasons you cannot have two magnifying glasses at the same time is because each magnifying glass uses the SCREEN_TEXTURE property in the shader. Normally only one shader can access the screen texture at a time, so to get around this you'll likely need to use a BackBufferCopy (documentation) node or place each of the magnifying glasses on their own CanvasLayer node.

I opened a issue on GitHub about this awhile ago and in Godot 3.1, using either the BackBufferCopy or the CanvasLayer node should fix the issue.

Hopefully this helps :smile:

Wow, thank you so much for this very precious help, I could never have found the source of the problem without you! I managed to solve the problem on my side with canvas layers and some work on the scripts. Again a very big thank you for your help and the time you spent helping me!

@LOIC said:

@TwistedTwigleg said: I think the reasons you cannot have two magnifying glasses at the same time is because each magnifying glass uses the SCREEN_TEXTURE property in the shader. Normally only one shader can access the screen texture at a time, so to get around this you'll likely need to use a BackBufferCopy (documentation) node or place each of the magnifying glasses on their own CanvasLayer node.

I opened a issue on GitHub about this awhile ago and in Godot 3.1, using either the BackBufferCopy or the CanvasLayer node should fix the issue.

Hopefully this helps :smile:

Wow, thank you so much for this very precious help, I could never have found the source of the problem without you! I managed to solve the problem on my side with canvas layers and some work on the scripts. Again a very big thank you for your help and the time you spent helping me!

No problem, happy to help. :smile: I only stumbled across the problem when I was working on a project for a future tutorial, otherwise I wouldn't have know about it either.

4 years later