Anyone know the best way to get LIGHT_POSITION in world-space?
Asked Answered
I

7

0

I'm making a CanvasShader.
Normally for doing something in world-space I'd just set up a varying in vertex() like

varying vec2 WorldSpace;

void vertex() {
	WorldSpace = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
}

and it gets interpolated and everything is happy.

Problem is, LIGHT_POSITION is just wherever the light is in screen coordinates, completely unrelated to LIGHT_VERTEX. No access to LIGHT_POSITION in vertex(), and obviously passing down a matrix with a flat varying and doing those multiplications in light() is a terrible idea.

I guess I don't even need the world position exactly. I just need x&y pixel differences between LIGHT_POSITION and LIGHT_VERTEX, and I need that calculation to remain consistent with camera scaling.

Any ideas? For easy reference I'll put the light-pass built-ins below here:

Impetuous answered 19/10, 2023 at 23:20 Comment(0)
I
0

Impetuous No access to LIGHT_POSITION in vertex()

There can be many lights in the scene and in contrast to light function which is called per light, the vertex function is executed only once.

If it's only a single light (or few of them), you can pass it as an uniform.
What exactly do you need this for?

Implead answered 19/10, 2023 at 23:35 Comment(0)
I
0

Maleeny

Cutting off the light added to the front-face of a tile if the light's source would be y-sorted behind it. I'm trying to fake "height" on tiles by encoding it into NORMAL_TEXTURE.a, using that to offset LIGHT_VERTEX, then doing a step(LIGHT_VERTEX.y, LIGHT_POSITION.y)

Here, code:

//normal_a, true_color, and color_mod are varyings.
void light() {
	float cNdotL = max(0.0, dot(NORMAL, LIGHT_DIRECTION));
	//These lines only function correctly at Camera2D.zoom == (1, 1)
	float LvYadj = LIGHT_VERTEX.y - normal_a * MAX_HEIGHT_OFFSET;
	float LvYstepLpY = step(LvYadj, LIGHT_POSITION.y);
	LIGHT.rgb = LIGHT_COLOR.rgb * true_color.rgb * color_mod.rgb
		* LIGHT_ENERGY * cNdotL * LvYstepLpY;
	LIGHT.a = LIGHT_COLOR.a;
}
Impetuous answered 20/10, 2023 at 0:1 Comment(0)
I
0

Impetuous This makes my head explode.
As a general hint, when there is a need to send some information from light function to fragment function, you can exploit multiple shader passes. First render the information out from the light function in the first pass and then read the screen texture in the second pass to get the information back into the fragment function. Or vice versa.

Implead answered 20/10, 2023 at 0:38 Comment(0)
I
0

Impetuous What's stopping you from transforming LIGHT_VERTEX into the same space the LIGHT_POSITION is in?

Implead answered 20/10, 2023 at 0:53 Comment(0)
I
0

Implead They're already both in screen space. Doing the comparison there just gets messed up by zoom... Oh yeah maybe I just need to get the ratio to scale that by. Would be easy enough to set a global uniform when the game is running. Idk how to go about getting that ratio in the editor viewport though 🤔

Impetuous answered 20/10, 2023 at 1:15 Comment(0)
I
0

Impetuous How about EditorPlugin::get_editor_interface().get_editor_viewport_2d().get_camera_2D() ?

Implead answered 20/10, 2023 at 1:26 Comment(0)
I
0

I think that should do the trick.

Impetuous answered 20/10, 2023 at 1:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.