mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
internal/graphicsdriver/metal: invert Y at the vertex shader
Instead of using a negative height in the viewport, invert the Y direction at the vertex shader. This is a little more readable as a negative height is hacky. This is a preparation for DirectX 12. DirectX 12's coodination system is very similar to Metal, but doesn't treat a negative height in its viewport unfortunately. Updates #1007
This commit is contained in:
parent
ea35296be7
commit
566957dc1c
@ -55,6 +55,7 @@ type Graphics interface {
|
||||
SetVsyncEnabled(enabled bool)
|
||||
SetFullscreen(fullscreen bool)
|
||||
FramebufferYDirection() YDirection
|
||||
NDCYDirection() YDirection
|
||||
NeedsRestoring() bool
|
||||
NeedsClearingScreen() bool
|
||||
IsGL() bool
|
||||
|
@ -72,11 +72,13 @@ vertex VertexOut VertexShader(
|
||||
const device VertexIn* vertices [[buffer(0)]],
|
||||
constant float2& viewport_size [[buffer(1)]]
|
||||
) {
|
||||
// In Metal, the NDC's Y direction (upward) and the framebuffer's Y direction (downward) don't
|
||||
// match. Then, the Y direction must be inverted.
|
||||
float4x4 projectionMatrix = float4x4(
|
||||
float4(2.0 / viewport_size.x, 0, 0, 0),
|
||||
float4(0, 2.0 / viewport_size.y, 0, 0),
|
||||
float4(0, -2.0 / viewport_size.y, 0, 0),
|
||||
float4(0, 0, 1, 0),
|
||||
float4(-1, -1, 0, 1)
|
||||
float4(-1, 1, 0, 1)
|
||||
);
|
||||
|
||||
VertexIn in = vertices[vid];
|
||||
@ -829,14 +831,12 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graph
|
||||
|
||||
g.rce.SetRenderPipelineState(rps)
|
||||
|
||||
// In Metal, the NDC's Y direction (upward) and the framebuffer's Y direction (downward) don't
|
||||
// match. Then, the Y direction must be inverted.
|
||||
w, h := dst.internalSize()
|
||||
g.rce.SetViewport(mtl.Viewport{
|
||||
OriginX: 0,
|
||||
OriginY: float64(h),
|
||||
OriginY: 0,
|
||||
Width: float64(w),
|
||||
Height: -float64(h),
|
||||
Height: float64(h),
|
||||
ZNear: -1,
|
||||
ZFar: 1,
|
||||
})
|
||||
@ -1051,6 +1051,10 @@ func (g *Graphics) FramebufferYDirection() graphicsdriver.YDirection {
|
||||
return graphicsdriver.Downward
|
||||
}
|
||||
|
||||
func (g *Graphics) NDCYDirection() graphicsdriver.YDirection {
|
||||
return graphicsdriver.Upward
|
||||
}
|
||||
|
||||
func (g *Graphics) NeedsRestoring() bool {
|
||||
return false
|
||||
}
|
||||
|
@ -385,6 +385,10 @@ func (g *Graphics) FramebufferYDirection() graphicsdriver.YDirection {
|
||||
return graphicsdriver.Upward
|
||||
}
|
||||
|
||||
func (g *Graphics) NDCYDirection() graphicsdriver.YDirection {
|
||||
return graphicsdriver.Upward
|
||||
}
|
||||
|
||||
func (g *Graphics) NeedsRestoring() bool {
|
||||
return g.context.needsRestoring()
|
||||
}
|
||||
|
@ -67,3 +67,7 @@ const (
|
||||
WindowResizingModeOnlyFullscreenEnabled
|
||||
WindowResizingModeEnabled
|
||||
)
|
||||
|
||||
func NeedsInvertY() bool {
|
||||
return graphics().FramebufferYDirection() != graphics().NDCYDirection()
|
||||
}
|
||||
|
35
shader.go
35
shader.go
@ -26,6 +26,7 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shader"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
var shaderSuffix string
|
||||
@ -105,17 +106,6 @@ func imageSrc%[1]dAt(pos vec2) vec4 {
|
||||
}
|
||||
`, i, pos)
|
||||
}
|
||||
|
||||
shaderSuffix += `
|
||||
func __vertex(position vec2, texCoord vec2, color vec4) (vec4, vec2, vec4) {
|
||||
return mat4(
|
||||
2/__imageDstTextureSize.x, 0, 0, 0,
|
||||
0, 2/__imageDstTextureSize.y, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, -1, 0, 1,
|
||||
) * vec4(position, 0, 1), texCoord, color
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
// Shader represents a compiled shader program.
|
||||
@ -136,6 +126,29 @@ func NewShader(src []byte) (*Shader, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.Write(src)
|
||||
buf.WriteString(shaderSuffix)
|
||||
if ui.NeedsInvertY() {
|
||||
buf.WriteString(`
|
||||
func __vertex(position vec2, texCoord vec2, color vec4) (vec4, vec2, vec4) {
|
||||
return mat4(
|
||||
2/__imageDstTextureSize.x, 0, 0, 0,
|
||||
0, -2/__imageDstTextureSize.y, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, 1, 0, 1,
|
||||
) * vec4(position, 0, 1), texCoord, color
|
||||
}
|
||||
`)
|
||||
} else {
|
||||
buf.WriteString(`
|
||||
func __vertex(position vec2, texCoord vec2, color vec4) (vec4, vec2, vec4) {
|
||||
return mat4(
|
||||
2/__imageDstTextureSize.x, 0, 0, 0,
|
||||
0, 2/__imageDstTextureSize.y, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, -1, 0, 1,
|
||||
) * vec4(position, 0, 1), texCoord, color
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
fs := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fs, "", buf.Bytes(), parser.AllErrors)
|
||||
|
Loading…
Reference in New Issue
Block a user