How to make a properly working magnifying glass shader
Asked Answered
C

8

0

SCREEN_TEXTURE : hint_screen_texture
This thing captures the entire screen, even what is outside the game window and it is very annoying, I only need what is in the window.

Cyclopropane answered 17/11, 2023 at 16:43 Comment(0)
P
0

Cyclopropane maybe there is an easier way idk...

Of course there is. No need for any of that black magic πŸ™‚, and all the relevant parameters are already there in built-ins. So just transform the object center into screen UV space and scale the UV coordinate around it:

shader_type canvas_item;

uniform sampler2D screen: hint_screen_texture;
uniform float magFactor = 2.0;
varying vec2 center;

void vertex(){
	center = (CANVAS_MATRIX * MODEL_MATRIX[3]).xy;
}

void fragment(){
	vec2 centerUV = center * SCREEN_PIXEL_SIZE;
	COLOR = texture(screen, (SCREEN_UV - centerUV) / magFactor + centerUV);
}

Btw you should rephrase your question to "How to make a magnifying glass shader" to make up for the xy problem situation πŸ˜‰

Puiia answered 19/11, 2023 at 16:49 Comment(0)
Z
0

Cyclopropane I feel like this can probably be reported to the issue tracker, though try and search first. An opened issue might already exist.

Zaremski answered 17/11, 2023 at 18:11 Comment(0)
T
0

I don't think there IS a window texture to read from. Godot would have to write to it, which it isn't doing because it's already writing those pixels to the screen texture.

What exactly are you trying to do and what is the issue you're having? There's surely a way to transform your UVs to just the rect portion of SCREEN_TEXTURE that you want.

Thurstan answered 17/11, 2023 at 22:29 Comment(0)
C
0

Thurstan Im trying to do a properly working magnifying glass.

I found the best, in my opinion, shader from the Internet

shader_type canvas_item;

uniform vec2 tiling = vec2(1,1); 
uniform vec2 offset = vec2(0,0);
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, repeat_enable, filter_linear_mipmap;

void fragment()
{
	
	vec4 color = texture(SCREEN_TEXTURE, SCREEN_UV * tiling + offset);
	color.a = texture(TEXTURE, UV).a;
	COLOR = color;
}

But since it does not work correctly without a script (the offset must be adjusted to the object on which the shader is applied), I had to look for a very long time to find the formula by which the offset will change.

form_x = ((magnifier.position.x + magnifier.size.x/2) / (DisplayServer.window_get_size().x / (1.0-mat.get_shader_parameter("tiling").x)) )
form_y = ((magnifier.position.y + magnifier.size.y/2) / (DisplayServer.window_get_size().y / (1.0-mat.get_shader_parameter("tiling").y)) )
mat.set_shader_parameter("offset", Vector2(form_x, form_y))

It works great, with one exception: if you resize the window or make the window fullscreen, the offset immediately starts to work incorrectly.

Click to reveal Click to hide



Cyclopropane answered 19/11, 2023 at 15:34 Comment(0)
C
0

Thurstan and the reason of these bugs is my screen, which resolution isnt equals window's resolution. I'm too tired to look for new formulas, so the WINDOW_TEXTURE is the most easiest way. But as I understand, it is extremely difficult to make it, because it does not exist by default as SCREEN_TEXTURE

Cyclopropane answered 19/11, 2023 at 15:37 Comment(0)
C
0

maybe there is an easier way idk...

Cyclopropane answered 19/11, 2023 at 16:6 Comment(0)
P
0

Cyclopropane maybe there is an easier way idk...

Of course there is. No need for any of that black magic πŸ™‚, and all the relevant parameters are already there in built-ins. So just transform the object center into screen UV space and scale the UV coordinate around it:

shader_type canvas_item;

uniform sampler2D screen: hint_screen_texture;
uniform float magFactor = 2.0;
varying vec2 center;

void vertex(){
	center = (CANVAS_MATRIX * MODEL_MATRIX[3]).xy;
}

void fragment(){
	vec2 centerUV = center * SCREEN_PIXEL_SIZE;
	COLOR = texture(screen, (SCREEN_UV - centerUV) / magFactor + centerUV);
}

Btw you should rephrase your question to "How to make a magnifying glass shader" to make up for the xy problem situation πŸ˜‰

Puiia answered 19/11, 2023 at 16:49 Comment(0)
C
0

Puiia can't believe it can be MUCH easier πŸ€¦β€β™‚οΈ

Anyway, it turns out a little inaccurate without the offset. It already depends on the size of the viewport, so this will be easier to fix. As a last resort, i can leave everything as is, because the deviation is small.

COLOR = texture(screen, (SCREEN_UV - centerUV) / magFactor + centerUV);

COLOR = texture(screen, (SCREEN_UV - centerUV) / magFactor + centerUV + vec2(0.025, 0.033));

0.025/0.033 is very close to 3/4 (game aspect ratio), so then... Otherwise, that is another story πŸ™‚

Many thanks for help πŸ™

Cyclopropane answered 20/11, 2023 at 13:14 Comment(0)
P
0

Cyclopropane I don't get any inaccuracies. In any case, it's not a good idea to hardcode offsets like this because the same numbers will result in a different offset when you change the resolution. If you need to offset it for a fraction of a pixel, use SCREEN_PIXEL_SIZE. It gives you the pixels size in normalized 0-1 screen space which coincides with UV space.

Puiia answered 20/11, 2023 at 13:26 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.