diff --git a/internal/graphics/vertex.go b/internal/graphics/vertex.go index 6cff70737..7a2d29fb9 100644 --- a/internal/graphics/vertex.go +++ b/internal/graphics/vertex.go @@ -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 ( diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index f39c3c168..f9d8a6fde 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -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) diff --git a/internal/graphicsdriver/metal/graphics.go b/internal/graphicsdriver/metal/graphics.go index 6ee09888b..f2ab7ad88 100644 --- a/internal/graphicsdriver/metal/graphics.go +++ b/internal/graphicsdriver/metal/graphics.go @@ -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 { diff --git a/internal/graphicsdriver/opengl/graphics.go b/internal/graphicsdriver/opengl/graphics.go index 22be98f46..0d92e2a07 100644 --- a/internal/graphicsdriver/opengl/graphics.go +++ b/internal/graphicsdriver/opengl/graphics.go @@ -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] } diff --git a/internal/testing/shader.go b/internal/testing/shader.go index 077825fc5..3a0e19287 100644 --- a/internal/testing/shader.go +++ b/internal/testing/shader.go @@ -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 } diff --git a/shader.go b/shader.go index ee7dd6cc3..83a1a4a1a 100644 --- a/shader.go +++ b/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 += `