Page 1 of 1

[Solved] Shader question: Getting current pixel x/y color from passed reference image

Posted: Sat Apr 23, 2022 4:26 pm
by Jasoco
I know the title is really wonky. I don't know the lingo enough to know how to word it better.

I have a really stupid problem I've been trying to figure out for hours now relating to shaders.

So I have a DepthMap canvas and my main canvas. I use a shader to draw to the DepthMap canvas stuff in certain colors. Like one color for certain things and another for everything else or whatever. That part isn't important. I then draw the same stuff normally to the main canvas using my normal shader. I am passing the DepthMap to the main shader and I am trying to grab the color of the pixel in that DepthMap from within the main shader but I am having trouble grabbing the proper pixel coordinate. For some reason I am only grabbing the bottom right corner pixel of the DepthMap. I've tried everything I can to figure out how to pass the proper coordinates to the Texel function but it just isn't working. It's always just the bottom right pixel. Which in screen space coordinates is vec2(1.0,1.0) I assume. I've tried everything. I've Googled. I've looked at other projects using the g3d library. Nothing seems to work. pixcoord is always 1.0, 1.0 (Where 1.0 basically means furthest right/down on the canvas. 0.0 would mean furthest left and up and 0.5 would be the middle) no matter what even though I'd think it should be whatever the current pixel coordinate is for the shader at that moment. Right? Is there some other variable it's supposed to be? I'm literally about to rip my hair out. lol

Hours I've been trying. I think someone else was having this issue a few pages back too. (Notice in their screenshot that they have a smaller version of the scene rendered in black and white, that's what I'm doing as well. I want to be able to compare the pixel from the DepthMap with the same pixel in the main canvas.) No one ever answered it and I don't know if they ever solved it. I'm so desperate! I feel like I'm missing the most obvious thing here.

Note that "DepthMap" has no meaning. It's just what I'm calling it right now. It could be called anything really. It's just a 3D canvas that I'm drawing the world to using a special shader.

Re: Shader question: Getting current pixel x/y color from passed reference image

Posted: Sat Apr 23, 2022 5:08 pm
by darkfrei
https://www.shadertoy.com/view/WdlSRB

Code: Select all

const vec2 pixelPosition = vec2(100.5, 100.5);
const vec4 color = vec4(1., 1., 1., 1.);
const vec4 background = vec4(0., 0., 0., 1.);

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    fragColor = vec4(fragCoord == pixelPosition ? color : background);
}
https://www.shadertoy.com/view/4tVcWW

Code: Select all

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{	
	vec2 xy = fragCoord.xy / iResolution.xy;
    vec4 texColor = texture(iChannel0, xy);
	float gray = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
    vec4 greyscale = vec4(vec3(gray), texColor.a);
    texColor *= max(
        vec4(
        vec3(abs(sin(iTime)), 
             abs(sin(iTime)),
             abs(sin(iTime))),
        1.0),
    greyscale);
    fragColor = texColor;
}
But I don't know how to convert it to the Love2D's shader.

Re: Shader question: Getting current pixel x/y color from passed reference image

Posted: Sat Apr 23, 2022 8:02 pm
by Jasoco
Unfortunately no they aren't what I need.

It refuses to pass the current pixel coordinate as a value and just keeps passing 1.0, 1.0. No matter what I do.

Here's some pseudocode.

Code: Select all

// This is the canvas being passed
// The image would be basically some black and white pixels
uniform Image DepthMap;

vec4 effect(vec4 color, Image tex, vec2 texcoord, vec2 pixcoord) {
	// This grabs the current pixel color of the main image the
	// shader is currently working on
	vec4 texcolor = Texel(tex, texcoord);

	// This code is supposed to grab the color of the pixel in the
	// DepthMap image at the current pixel coordinates
	float tex2color = Texel(DepthMap, pixcoord);

	if (tex2color.r == 0) {
		// Do something here if the currently grabbed pixel color
		// has some color in the red channel
		texcolor.b = 1.0;
		// With this example, the shader should check the pixel color
		// at the current coordinates in the DepthMap image and
		// if its red channel is zero then change the output color's blue
		// channel to full. Just an example of course.
	}
	
	// Returns the color to draw at that pixel coordinate after all
	// the work is done
	return texcolor;
}
From what I understand:
Texel() is the Löve shader equivalent to texture()
texcoord is the coordinate of the pixel on the mesh's texture
pixcoord is the coordinate of the pixel on the main image itself

Right now instead of working how I would expect it to, it's just coloring the entire image blue tinted if the pixel in the bottom right corner of the DepthMap just happens to be black. What I would expect it to do is work on every pixel one at a time checking the same pixel coordinate on the DepthMap and using that to change the color of the current pixel so only parts of the screen should/would be tinted blue. But instead since the "float tex2color = Texel(DepthMap, pixcoord);" line is for some reason only grabbing the pixel in the bottom right corner it's just tinting the whole screen blue until I move the camera enough that the the bottom corner of the DepthMap is white instead. I'm so confused! lol

I always figured this was the kind of shader you'd need to write to do color blending for like transparency or whatever. Apparently not.

Re: Shader question: Getting current pixel x/y color from passed reference image

Posted: Sat Apr 23, 2022 10:36 pm
by ReFreezed
pixcoord is in pixels, unlike texcoord which is normalized. So, the value is way too large for the Texel function. You can use love_ScreenSize to normalize those coords.

Re: Shader question: Getting current pixel x/y color from passed reference image

Posted: Sun Apr 24, 2022 2:10 am
by Jasoco
ReFreezed wrote: Sat Apr 23, 2022 10:36 pm pixcoord is in pixels, unlike texcoord which is normalized. So, the value is way too large for the Texel function. You can use love_ScreenSize to normalize those coords.
Thank you! It seems the following works:

Code: Select all

float tex2color = Texel(DepthMap, pixcoord.xy / love_ScreenSize.xy).r;
if (tex2color > 0) {
	texcolor.g = 1.0; // Do stuff here
}
I know it's not the real way to do it but using this I have rudimentary liquid transparency in my project.
1650765899.png
1650765899.png (323.22 KiB) Viewed 2429 times
(BTW the dithering and low resolution is part of the game, not because I filtered the PNG through some cheese grater. Maybe one day I'll finally show this project off.)

Re: [Solved] Shader question: Getting current pixel x/y color from passed reference image

Posted: Sun Apr 24, 2022 3:00 am
by ReFreezed
Looks nice. :)

Re: [Solved] Shader question: Getting current pixel x/y color from passed reference image

Posted: Sun Apr 24, 2022 5:08 am
by Jasoco
Thanks! I'm learning more about shaders every day. Still haven't figured out the best way to handle simple lighting yet. But I know it can be done because numerous projects have done it already.