mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +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)
|
SetVsyncEnabled(enabled bool)
|
||||||
SetFullscreen(fullscreen bool)
|
SetFullscreen(fullscreen bool)
|
||||||
FramebufferYDirection() YDirection
|
FramebufferYDirection() YDirection
|
||||||
|
NDCYDirection() YDirection
|
||||||
NeedsRestoring() bool
|
NeedsRestoring() bool
|
||||||
NeedsClearingScreen() bool
|
NeedsClearingScreen() bool
|
||||||
IsGL() bool
|
IsGL() bool
|
||||||
|
@ -72,11 +72,13 @@ vertex VertexOut VertexShader(
|
|||||||
const device VertexIn* vertices [[buffer(0)]],
|
const device VertexIn* vertices [[buffer(0)]],
|
||||||
constant float2& viewport_size [[buffer(1)]]
|
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(
|
float4x4 projectionMatrix = float4x4(
|
||||||
float4(2.0 / viewport_size.x, 0, 0, 0),
|
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(0, 0, 1, 0),
|
||||||
float4(-1, -1, 0, 1)
|
float4(-1, 1, 0, 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
VertexIn in = vertices[vid];
|
VertexIn in = vertices[vid];
|
||||||
@ -829,14 +831,12 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graph
|
|||||||
|
|
||||||
g.rce.SetRenderPipelineState(rps)
|
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()
|
w, h := dst.internalSize()
|
||||||
g.rce.SetViewport(mtl.Viewport{
|
g.rce.SetViewport(mtl.Viewport{
|
||||||
OriginX: 0,
|
OriginX: 0,
|
||||||
OriginY: float64(h),
|
OriginY: 0,
|
||||||
Width: float64(w),
|
Width: float64(w),
|
||||||
Height: -float64(h),
|
Height: float64(h),
|
||||||
ZNear: -1,
|
ZNear: -1,
|
||||||
ZFar: 1,
|
ZFar: 1,
|
||||||
})
|
})
|
||||||
@ -1051,6 +1051,10 @@ func (g *Graphics) FramebufferYDirection() graphicsdriver.YDirection {
|
|||||||
return graphicsdriver.Downward
|
return graphicsdriver.Downward
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Graphics) NDCYDirection() graphicsdriver.YDirection {
|
||||||
|
return graphicsdriver.Upward
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Graphics) NeedsRestoring() bool {
|
func (g *Graphics) NeedsRestoring() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -385,6 +385,10 @@ func (g *Graphics) FramebufferYDirection() graphicsdriver.YDirection {
|
|||||||
return graphicsdriver.Upward
|
return graphicsdriver.Upward
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Graphics) NDCYDirection() graphicsdriver.YDirection {
|
||||||
|
return graphicsdriver.Upward
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Graphics) NeedsRestoring() bool {
|
func (g *Graphics) NeedsRestoring() bool {
|
||||||
return g.context.needsRestoring()
|
return g.context.needsRestoring()
|
||||||
}
|
}
|
||||||
|
@ -67,3 +67,7 @@ const (
|
|||||||
WindowResizingModeOnlyFullscreenEnabled
|
WindowResizingModeOnlyFullscreenEnabled
|
||||||
WindowResizingModeEnabled
|
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/mipmap"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shader"
|
"github.com/hajimehoshi/ebiten/v2/internal/shader"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
var shaderSuffix string
|
var shaderSuffix string
|
||||||
@ -105,17 +106,6 @@ func imageSrc%[1]dAt(pos vec2) vec4 {
|
|||||||
}
|
}
|
||||||
`, i, pos)
|
`, 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.
|
// Shader represents a compiled shader program.
|
||||||
@ -136,6 +126,29 @@ func NewShader(src []byte) (*Shader, error) {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.Write(src)
|
buf.Write(src)
|
||||||
buf.WriteString(shaderSuffix)
|
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()
|
fs := token.NewFileSet()
|
||||||
f, err := parser.ParseFile(fs, "", buf.Bytes(), parser.AllErrors)
|
f, err := parser.ParseFile(fs, "", buf.Bytes(), parser.AllErrors)
|
||||||
|
Loading…
Reference in New Issue
Block a user