mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
ebiten: Bug fix: Fix the texel calculation
In shaders, texCoord is always in texture0's texels. Convert them at imageNTextureAt functions correctly. Fixes #1290
This commit is contained in:
parent
69f87d5fd1
commit
609a3c4e22
@ -26,14 +26,14 @@ const (
|
||||
PreservedUniformVariablesNum = 1 + // the destination texture size
|
||||
1 + // the texture sizes array
|
||||
1 + // the offsets array of the second and the following images
|
||||
1 + // the texture source origin
|
||||
1 // the texture source sizes
|
||||
1 + // the texture source region's origin
|
||||
1 // the texture source region's size
|
||||
|
||||
DestinationTextureSizeUniformVariableIndex = 0
|
||||
TextureSizesUniformVariableIndex = 1
|
||||
TextureSourceOffsetsUniformVariableIndex = 2
|
||||
TextureSourceOriginUniformVariableIndex = 3
|
||||
TextureSourceSizesUniformVariableIndex = 4
|
||||
DestinationTextureSizeUniformVariableIndex = 0
|
||||
TextureSizesUniformVariableIndex = 1
|
||||
TextureSourceOffsetsUniformVariableIndex = 2
|
||||
TextureSourceRegionOriginUniformVariableIndex = 3
|
||||
TextureSourceRegionSizeUniformVariableIndex = 4
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -167,7 +167,6 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
||||
sourceRegion.Y /= float32(h)
|
||||
sourceRegion.Width /= float32(w)
|
||||
sourceRegion.Height /= float32(h)
|
||||
// TODO: This doesn't work when the src image sizes are different.
|
||||
for i := range offsets {
|
||||
offsets[i][0] /= float32(w)
|
||||
offsets[i][1] /= float32(h)
|
||||
|
@ -1029,30 +1029,13 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
||||
}
|
||||
us[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets
|
||||
|
||||
// Set the source origin of the first image.
|
||||
// Set the source region's origin of texture0.
|
||||
uorigin := []float32{float32(sourceRegion.X), float32(sourceRegion.Y)}
|
||||
us[graphics.TextureSourceOriginUniformVariableIndex] = uorigin
|
||||
us[graphics.TextureSourceRegionOriginUniformVariableIndex] = uorigin
|
||||
|
||||
// Set the source sizes.
|
||||
ussizes := make([]float32, 2*len(srcs))
|
||||
if srcs[0] != nil {
|
||||
w, h := sourceRegion.Width, sourceRegion.Height
|
||||
bw, bh := srcs[0].internalSize()
|
||||
for i, src := range srcs {
|
||||
if i == 0 {
|
||||
ussizes[2*i] = float32(w)
|
||||
ussizes[2*i+1] = float32(h)
|
||||
continue
|
||||
}
|
||||
if src == nil {
|
||||
continue
|
||||
}
|
||||
tw, th := src.internalSize()
|
||||
ussizes[2*i] = float32(w) * float32(bw) / float32(tw)
|
||||
ussizes[2*i+1] = float32(h) * float32(bh) / float32(th)
|
||||
}
|
||||
}
|
||||
us[graphics.TextureSourceSizesUniformVariableIndex] = ussizes
|
||||
// Set the source region's size of texture0.
|
||||
ussize := []float32{float32(sourceRegion.Width), float32(sourceRegion.Height)}
|
||||
us[graphics.TextureSourceRegionSizeUniformVariableIndex] = ussize
|
||||
|
||||
// Set the additional uniform variables.
|
||||
for i, v := range uniforms {
|
||||
|
@ -336,37 +336,17 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
{
|
||||
origin := make([]float32, 2)
|
||||
origin[0] = sourceRegion.X
|
||||
origin[1] = sourceRegion.Y
|
||||
const idx = graphics.TextureSourceOriginUniformVariableIndex
|
||||
origin := []float32{float32(sourceRegion.X), float32(sourceRegion.Y)}
|
||||
const idx = graphics.TextureSourceRegionOriginUniformVariableIndex
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = origin
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
{
|
||||
sizes := make([]float32, 2*len(srcs))
|
||||
if baseimg := g.images[srcs[0]]; baseimg != nil {
|
||||
w, h := sourceRegion.Width, sourceRegion.Height
|
||||
bw, bh := baseimg.framebufferSize()
|
||||
for i, src := range srcs {
|
||||
if i == 0 {
|
||||
sizes[2*i] = float32(w)
|
||||
sizes[2*i+1] = float32(h)
|
||||
continue
|
||||
}
|
||||
img := g.images[src]
|
||||
if img == nil {
|
||||
continue
|
||||
}
|
||||
tw, th := img.framebufferSize()
|
||||
sizes[2*i] = float32(w) * float32(bw) / float32(tw)
|
||||
sizes[2*i+1] = float32(h) * float32(bh) / float32(th)
|
||||
}
|
||||
}
|
||||
const idx = graphics.TextureSourceSizesUniformVariableIndex
|
||||
size := []float32{float32(sourceRegion.Width), float32(sourceRegion.Height)}
|
||||
const idx = graphics.TextureSourceRegionSizeUniformVariableIndex
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = sizes
|
||||
us[idx].value = size
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
|
||||
|
@ -241,12 +241,8 @@ func defaultProgram() shaderir.Program {
|
||||
}
|
||||
// Source region origin
|
||||
p.Uniforms[3] = shaderir.Type{Main: shaderir.Vec2}
|
||||
// Source region sizes
|
||||
p.Uniforms[4] = shaderir.Type{
|
||||
Main: shaderir.Array,
|
||||
Length: graphics.ShaderImageNum,
|
||||
Sub: []shaderir.Type{{Main: shaderir.Vec2}},
|
||||
}
|
||||
// Source region size
|
||||
p.Uniforms[4] = shaderir.Type{Main: shaderir.Vec2}
|
||||
return p
|
||||
}
|
||||
|
||||
|
24
shader.go
24
shader.go
@ -49,30 +49,38 @@ func image%[1]dTextureSize() vec2 {
|
||||
}
|
||||
|
||||
shaderSuffix += fmt.Sprintf(`
|
||||
// The unit is texture0's texels.
|
||||
var __textureSourceOffsets [%[1]d]vec2
|
||||
|
||||
// The unit is texture0's texels.
|
||||
var __textureSourceOrigin vec2
|
||||
var __textureSourceSizes [%[2]d]vec2
|
||||
|
||||
// The unit is texture0's texels.
|
||||
var __textureSourceSize vec2
|
||||
`, graphics.ShaderImageNum-1, graphics.ShaderImageNum)
|
||||
|
||||
for i := 0; i < graphics.ShaderImageNum; i++ {
|
||||
var offset string
|
||||
pos := "pos"
|
||||
if i >= 1 {
|
||||
offset = fmt.Sprintf(" + __textureSourceOffsets[%d]", i-1)
|
||||
// Convert the position in texture0's texels to the target texture texels.
|
||||
pos = fmt.Sprintf("(pos + __textureSourceOffsets[%d]) * __textureSizes[0] / __textureSizes[%d]", i-1, i)
|
||||
}
|
||||
// __t%d is a special variable for a texture variable.
|
||||
shaderSuffix += fmt.Sprintf(`
|
||||
func image%[1]dTextureAt(pos vec2) vec4 {
|
||||
return texture2D(__t%[1]d, pos%[2]s)
|
||||
// pos is the position in texture0's texels.
|
||||
return texture2D(__t%[1]d, %[2]s)
|
||||
}
|
||||
|
||||
func image%[1]dTextureBoundsAt(pos vec2) vec4 {
|
||||
return texture2D(__t%[1]d, pos%[2]s) *
|
||||
// pos is the position in texture0's texels.
|
||||
return texture2D(__t%[1]d, %[2]s) *
|
||||
step(__textureSourceOrigin.x, pos.x) *
|
||||
(1 - step(__textureSourceOrigin.x + __textureSourceSizes[%[1]d].x, pos.x)) *
|
||||
(1 - step(__textureSourceOrigin.x + __textureSourceSize.x, pos.x)) *
|
||||
step(__textureSourceOrigin.y, pos.y) *
|
||||
(1 - step(__textureSourceOrigin.y + __textureSourceSizes[%[1]d].y, pos.y))
|
||||
(1 - step(__textureSourceOrigin.y + __textureSourceSize.y, pos.y))
|
||||
}
|
||||
`, i, offset)
|
||||
`, i, pos)
|
||||
}
|
||||
|
||||
shaderSuffix += `
|
||||
|
Loading…
Reference in New Issue
Block a user