hajimehoshi / ebiten

Ebitengine - A dead simple 2D game engine for Go
https://ebitengine.org
Apache License 2.0
10.74k stars 649 forks source link

internal/shader: utility functions to treat normalized values #2644

Open hajimehoshi opened 1 year ago

hajimehoshi commented 1 year ago

Operating System

What feature would you like to be added?

I propose to add these functions

Note that the units might be affected by #1431.

For more details, see https://docs.google.com/document/d/1lJTKxMqyyO-LxNS4KmuNakQwlhdBgzkmP2LNwpJk5bg/edit#bookmark=id.b8qzndnzk6yq

TBD: Do we need inverted functions?

Why is this needed?

From the discussion of #2639, we found that normalizing positions of textures to [0, 1] is very common. To do this, users need to understand how images and textures work in Ebitengine, and to write some tricky code with an origin and a texture. Thus, it should be very useful to have utility functions to do that for Kage.

For more details, see https://docs.google.com/document/d/1lJTKxMqyyO-LxNS4KmuNakQwlhdBgzkmP2LNwpJk5bg/edit?usp=sharing

hajimehoshi commented 1 year ago

For #1870, we might have to have these functions:

tinne26 commented 1 year ago

By the way, to use position directly in pixels, without normalizing to [0, 1], don't we also need to use the origin from imageDstRegionOnTexture() and transform it from texels to pixels with tricky calculations too? Because if this is the case, we should also have a normalization function for it. Until we actually get the pixels mode, this specific conversion (if I'm imagining it correctly) seems extremely convoluted.

hajimehoshi commented 1 year ago

don't we also need to use the origin from imageDstRegionOnTexture() and transform it from texels to pixels with tricky calculations too?

In the pixel mode, we don't treat texels even for destination textures, right?

tinne26 commented 1 year ago

Right. What I'm asking is this: given a target of 400x400, will position go from 0.5 to 395.5, or do we have to correct first for the destination origin? Unless I'm misunderstanding something (which is highly likely), I assume that in pixel mode we simply would do:

//kage:pixel-mode
func Fragment(position vec4, _ vec2, _ vec4) vec4 {
    origin, _ := imageDstRegionOnTexture()
    dstPosition := position.xy - origin
}

But without pixel mode, this is currently much harder to do? Or is this step already unnecessary?

EDIT: I know that for many subimages position won't start at zero, but I still don't know if destination images with (0, 0) origin require atlas origin normalization or not to use position in the "natural range" of the destination image. If doing this is necessary, maybe we should have a normalization function for it too?

hajimehoshi commented 1 year ago

But without pixel mode, this is currently much harder to do? Or is this step already unnecessary?

If you are talking about how to get [0, 1] value, yes, this is a little much harder, but it's still possible. See https://github.com/hajimehoshi/ebiten/blob/2.5/examples/shader/texel.go (texel mode) vs https://github.com/hajimehoshi/ebiten/blob/main/examples/shader/texel.go (pixel mode).

I know that for many subimages position won't start at zero, but I still don't know if destination images with (0, 0) origin require atlas origin normalization or not to use position in the "natural range" of the destination image. If doing this is necessary, maybe we should have a normalization function for it too?

For a sub-image, I think we should provide a function to return [0, 1] assuming the sub-image's left-upper is (0, 0) and right-bottom is (1, 1). But this might be ambiguous. Let me think.

tinne26 commented 1 year ago

No, I'm talking about how to get the position value in [0, N] where N is the size of the destination image (let's assume it's a square image), without considering special cases like subimages or scaling due to anti-aliasing. Technically it's [0.5, N - 0.5], but you get the point. I don't know if we need to account for the origin or not in the current state.

hajimehoshi commented 12 months ago

This requires more discussion. I'll reset the milestone.