mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
ebiten: Add new shader builtin functions: image[N]TextureBoundAt
Fixes #1287
This commit is contained in:
parent
523dc6f2a0
commit
69f87d5fd1
@ -24,8 +24,8 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||
center := ScreenSize / 2
|
||||
amount := (center - Cursor) / image2TextureSize() / 10
|
||||
var clr vec3
|
||||
clr.r = image2TextureAt(vec2(texCoord.x+amount.x, texCoord.y)).r
|
||||
clr.r = image2TextureBoundsAt(texCoord + amount).r
|
||||
clr.g = image2TextureAt(texCoord).g
|
||||
clr.b = image2TextureAt(vec2(texCoord.x-amount.x, texCoord.y)).b
|
||||
clr.b = image2TextureBoundsAt(texCoord - amount).b
|
||||
return vec4(clr, 1.0)
|
||||
}
|
||||
|
@ -3,4 +3,4 @@
|
||||
|
||||
package main
|
||||
|
||||
var chromaticaberration_go = []byte("// Copyright 2020 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build ignore\n\npackage main\n\nvar Time float\nvar Cursor vec2\nvar ScreenSize vec2\n\nfunc Fragment(position vec4, texCoord vec2, color vec4) vec4 {\n\tcenter := ScreenSize / 2\n\tamount := (center - Cursor) / image2TextureSize() / 10\n\tvar clr vec3\n\tclr.r = image2TextureAt(vec2(texCoord.x+amount.x, texCoord.y)).r\n\tclr.g = image2TextureAt(texCoord).g\n\tclr.b = image2TextureAt(vec2(texCoord.x-amount.x, texCoord.y)).b\n\treturn vec4(clr, 1.0)\n}\n")
|
||||
var chromaticaberration_go = []byte("// Copyright 2020 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build ignore\n\npackage main\n\nvar Time float\nvar Cursor vec2\nvar ScreenSize vec2\n\nfunc Fragment(position vec4, texCoord vec2, color vec4) vec4 {\n\tcenter := ScreenSize / 2\n\tamount := (center - Cursor) / image2TextureSize() / 10\n\tvar clr vec3\n\tclr.r = image2TextureBoundsAt(texCoord + amount).r\n\tclr.g = image2TextureAt(texCoord).g\n\tclr.b = image2TextureBoundsAt(texCoord - amount).b\n\treturn vec4(clr, 1.0)\n}\n")
|
||||
|
@ -30,8 +30,8 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||
// TODO: Add len(samples)
|
||||
sum := clr
|
||||
for i := 0; i < 10; i++ {
|
||||
// TODO: Consider the source region not to violate the region.
|
||||
sum += image2TextureAt(texCoord + dir*samples[i]/image2TextureSize())
|
||||
pos := texCoord + dir*samples[i]/image2TextureSize()
|
||||
sum += image2TextureBoundsAt(pos)
|
||||
}
|
||||
sum /= 10 + 1
|
||||
|
||||
|
@ -3,4 +3,4 @@
|
||||
|
||||
package main
|
||||
|
||||
var radialblur_go = []byte("// Copyright 2020 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build ignore\n\npackage main\n\nvar Time float\nvar Cursor vec2\nvar ScreenSize vec2\n\nfunc Fragment(position vec4, texCoord vec2, color vec4) vec4 {\n\tdir := normalize(position.xy - Cursor)\n\tclr := image2TextureAt(texCoord)\n\n\tsamples := [10]float{\n\t\t-22, -14, -8, -4, -2, 2, 4, 8, 14, 22,\n\t}\n\t// TODO: Add len(samples)\n\tsum := clr\n\tfor i := 0; i < 10; i++ {\n\t\t// TODO: Consider the source region not to violate the region.\n\t\tsum += image2TextureAt(texCoord + dir*samples[i]/image2TextureSize())\n\t}\n\tsum /= 10 + 1\n\n\tdist := distance(position.xy, Cursor)\n\tt := clamp(dist/256, 0, 1)\n\treturn mix(clr, sum, t)\n}\n")
|
||||
var radialblur_go = []byte("// Copyright 2020 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build ignore\n\npackage main\n\nvar Time float\nvar Cursor vec2\nvar ScreenSize vec2\n\nfunc Fragment(position vec4, texCoord vec2, color vec4) vec4 {\n\tdir := normalize(position.xy - Cursor)\n\tclr := image2TextureAt(texCoord)\n\n\tsamples := [10]float{\n\t\t-22, -14, -8, -4, -2, 2, 4, 8, 14, 22,\n\t}\n\t// TODO: Add len(samples)\n\tsum := clr\n\tfor i := 0; i < 10; i++ {\n\t\tpos := texCoord + dir*samples[i]/image2TextureSize()\n\t\tsum += image2TextureBoundsAt(pos)\n\t}\n\tsum /= 10 + 1\n\n\tdist := distance(position.xy, Cursor)\n\tt := clamp(dist/256, 0, 1)\n\treturn mix(clr, sum, t)\n}\n")
|
||||
|
42
image.go
42
image.go
@ -270,13 +270,21 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
|
||||
vs := graphics.QuadVertices(sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, 1, 1, 1, 1, filter == driver.FilterScreen)
|
||||
is := graphics.QuadIndices()
|
||||
|
||||
var sr driver.Region
|
||||
sr = driver.Region{
|
||||
X: float32(bounds.Min.X),
|
||||
Y: float32(bounds.Min.Y),
|
||||
Width: float32(bounds.Dx()),
|
||||
Height: float32(bounds.Dy()),
|
||||
}
|
||||
|
||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
||||
if options.Shader == nil {
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil, canSkipMipmap(options.GeoM, filter))
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, sr, nil, nil, canSkipMipmap(options.GeoM, filter))
|
||||
return nil
|
||||
}
|
||||
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, nil, mode, filter, driver.AddressUnsafe, driver.Region{}, options.Shader.shader, options.Uniforms, canSkipMipmap(options.GeoM, filter))
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, nil, mode, filter, driver.AddressUnsafe, sr, options.Shader.shader, options.Uniforms, canSkipMipmap(options.GeoM, filter))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -421,7 +429,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
copy(is, indices)
|
||||
|
||||
var sr driver.Region
|
||||
if options.Shader == nil && options.Address != AddressUnsafe {
|
||||
b := img.Bounds()
|
||||
sr = driver.Region{
|
||||
X: float32(b.Min.X),
|
||||
@ -429,7 +436,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
Width: float32(b.Dx()),
|
||||
Height: float32(b.Dy()),
|
||||
}
|
||||
}
|
||||
|
||||
var srcs [graphics.ShaderImageNum]*mipmap.Mipmap
|
||||
if img != nil {
|
||||
@ -440,7 +446,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, nil, nil, false)
|
||||
return
|
||||
}
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, options.Shader.shader, options.Uniforms, false)
|
||||
i.mipmap.DrawTriangles(srcs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, options.Shader.shader, options.Uniforms, false)
|
||||
}
|
||||
|
||||
// DrawRectShaderOptions represents options for DrawRectShader
|
||||
@ -517,7 +523,18 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
||||
vs := graphics.QuadVertices(0, 0, float32(width), float32(height), a, b, c, d, tx, ty, 1, 1, 1, 1, false)
|
||||
is := graphics.QuadIndices()
|
||||
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, shader.shader, options.Uniforms, canSkipMipmap(options.GeoM, driver.FilterNearest))
|
||||
var sr driver.Region
|
||||
if img := options.Images[0]; img != nil {
|
||||
b := img.Bounds()
|
||||
sr = driver.Region{
|
||||
X: float32(b.Min.X),
|
||||
Y: float32(b.Min.Y),
|
||||
Width: float32(b.Dx()),
|
||||
Height: float32(b.Dy()),
|
||||
}
|
||||
}
|
||||
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, shader.shader, options.Uniforms, canSkipMipmap(options.GeoM, driver.FilterNearest))
|
||||
}
|
||||
|
||||
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader
|
||||
@ -613,7 +630,18 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
||||
is := make([]uint16, len(indices))
|
||||
copy(is, indices)
|
||||
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, shader.shader, options.Uniforms, false)
|
||||
var sr driver.Region
|
||||
if img := options.Images[0]; img != nil {
|
||||
b := img.Bounds()
|
||||
sr = driver.Region{
|
||||
X: float32(b.Min.X),
|
||||
Y: float32(b.Min.Y),
|
||||
Width: float32(b.Dx()),
|
||||
Height: float32(b.Dy()),
|
||||
}
|
||||
}
|
||||
|
||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, sr, shader.shader, options.Uniforms, false)
|
||||
}
|
||||
|
||||
// SubImage returns an image representing the portion of the image p visible through r.
|
||||
|
@ -60,7 +60,7 @@ type Graphics interface {
|
||||
//
|
||||
// * float32
|
||||
// * []float32
|
||||
DrawShader(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, uniforms []interface{}) error
|
||||
DrawShader(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, sourceRegion Region, mode CompositeMode, uniforms []interface{}) error
|
||||
}
|
||||
|
||||
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
||||
|
@ -25,11 +25,15 @@ const (
|
||||
// Any shaders in Ebiten must have these uniform variables.
|
||||
PreservedUniformVariablesNum = 1 + // the destination texture size
|
||||
1 + // the texture sizes array
|
||||
1 // the offsets array of the second and the following images
|
||||
1 + // the offsets array of the second and the following images
|
||||
1 + // the texture source origin
|
||||
1 // the texture source sizes
|
||||
|
||||
DestinationTextureSizeUniformVariableIndex = 0
|
||||
TextureSizesUniformVariableIndex = 1
|
||||
TextureOffsetsUniformVariableIndex = 2
|
||||
TextureSourceOffsetsUniformVariableIndex = 2
|
||||
TextureSourceOriginUniformVariableIndex = 3
|
||||
TextureSourceSizesUniformVariableIndex = 4
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -163,12 +163,10 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
|
||||
|
||||
if srcs[0] != nil {
|
||||
w, h := srcs[0].InternalSize()
|
||||
if address != driver.AddressUnsafe {
|
||||
sourceRegion.X /= float32(w)
|
||||
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)
|
||||
@ -416,7 +414,7 @@ func (c *drawTrianglesCommand) Exec(indexOffset int) error {
|
||||
imgs[i] = src.image.ID()
|
||||
}
|
||||
|
||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), imgs, c.offsets, c.shader.shader.ID(), c.nindices, indexOffset, c.mode, c.uniforms)
|
||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), imgs, c.offsets, c.shader.shader.ID(), c.nindices, indexOffset, c.sourceRegion, c.mode, c.uniforms)
|
||||
}
|
||||
return theGraphicsDriver.Draw(c.dst.image.ID(), c.srcs[0].image.ID(), c.nindices, indexOffset, c.mode, c.color, c.filter, c.address, c.sourceRegion)
|
||||
}
|
||||
|
@ -991,7 +991,7 @@ func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, sourceRegion driver.Region, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
dst := g.images[dstID]
|
||||
var srcs [graphics.ShaderImageNum]*Image
|
||||
for i, srcID := range srcIDs {
|
||||
@ -1008,7 +1008,7 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
||||
|
||||
// Set the destination texture size.
|
||||
dw, dh := dst.internalSize()
|
||||
us[0] = []float32{float32(dw), float32(dh)}
|
||||
us[graphics.DestinationTextureSizeUniformVariableIndex] = []float32{float32(dw), float32(dh)}
|
||||
|
||||
// Set the source texture sizes.
|
||||
usizes := make([]float32, 2*len(srcs))
|
||||
@ -1019,7 +1019,7 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
||||
usizes[2*i+1] = float32(h)
|
||||
}
|
||||
}
|
||||
us[1] = usizes
|
||||
us[graphics.TextureSizesUniformVariableIndex] = usizes
|
||||
|
||||
// Set the source offsets.
|
||||
uoffsets := make([]float32, 2*len(offsets))
|
||||
@ -1027,7 +1027,32 @@ func (g *Graphics) DrawShader(dstID driver.ImageID, srcIDs [graphics.ShaderImage
|
||||
uoffsets[2*i] = offset[0]
|
||||
uoffsets[2*i+1] = offset[1]
|
||||
}
|
||||
us[2] = uoffsets
|
||||
us[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets
|
||||
|
||||
// Set the source origin of the first image.
|
||||
uorigin := []float32{float32(sourceRegion.X), float32(sourceRegion.Y)}
|
||||
us[graphics.TextureSourceOriginUniformVariableIndex] = 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 additional uniform variables.
|
||||
for i, v := range uniforms {
|
||||
|
@ -289,7 +289,7 @@ func (g *Graphics) removeShader(shader *Shader) {
|
||||
delete(g.shaders, shader.id)
|
||||
}
|
||||
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader driver.ShaderID, indexLen int, indexOffset int, sourceRegion driver.Region, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
d := g.images[dst]
|
||||
s := g.shaders[shader]
|
||||
|
||||
@ -301,38 +301,74 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
|
||||
g.context.blendFunc(mode)
|
||||
|
||||
us := make([]uniformVariable, graphics.PreservedUniformVariablesNum+len(uniforms))
|
||||
vw, vh := d.framebufferSize()
|
||||
us[0].name = "U0"
|
||||
us[0].value = []float32{float32(vw), float32(vh)}
|
||||
us[0].typ = s.ir.Uniforms[0]
|
||||
|
||||
vsizes := make([]float32, 2*len(srcs))
|
||||
{
|
||||
const idx = graphics.DestinationTextureSizeUniformVariableIndex
|
||||
w, h := d.framebufferSize()
|
||||
us[idx].name = "U0"
|
||||
us[idx].value = []float32{float32(w), float32(h)}
|
||||
us[idx].typ = s.ir.Uniforms[0]
|
||||
}
|
||||
{
|
||||
sizes := make([]float32, 2*len(srcs))
|
||||
for i, src := range srcs {
|
||||
if img := g.images[src]; img != nil {
|
||||
w, h := img.framebufferSize()
|
||||
vsizes[2*i] = float32(w)
|
||||
vsizes[2*i+1] = float32(h)
|
||||
sizes[2*i] = float32(w)
|
||||
sizes[2*i+1] = float32(h)
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
const idx = 1
|
||||
const idx = graphics.TextureSizesUniformVariableIndex
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = vsizes
|
||||
us[idx].value = sizes
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
|
||||
{
|
||||
voffsets := make([]float32, 2*len(offsets))
|
||||
for i, o := range offsets {
|
||||
voffsets[2*i] = o[0]
|
||||
voffsets[2*i+1] = o[1]
|
||||
}
|
||||
{
|
||||
const idx = 1 + 1
|
||||
const idx = graphics.TextureSourceOffsetsUniformVariableIndex
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = voffsets
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
{
|
||||
origin := make([]float32, 2)
|
||||
origin[0] = sourceRegion.X
|
||||
origin[1] = sourceRegion.Y
|
||||
const idx = graphics.TextureSourceOriginUniformVariableIndex
|
||||
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
|
||||
us[idx].name = fmt.Sprintf("U%d", idx)
|
||||
us[idx].value = sizes
|
||||
us[idx].typ = s.ir.Uniforms[idx]
|
||||
}
|
||||
|
||||
for i, v := range uniforms {
|
||||
const offset = graphics.PreservedUniformVariablesNum
|
||||
|
@ -337,11 +337,9 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
|
||||
vertices[i*graphics.VertexFloatNum+2] += oxf
|
||||
vertices[i*graphics.VertexFloatNum+3] += oyf
|
||||
}
|
||||
if address != driver.AddressUnsafe {
|
||||
sourceRegion.X += oxf
|
||||
sourceRegion.Y += oyf
|
||||
}
|
||||
}
|
||||
|
||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||
for i := range offsets {
|
||||
|
@ -239,6 +239,14 @@ func defaultProgram() shaderir.Program {
|
||||
Length: graphics.ShaderImageNum - 1,
|
||||
Sub: []shaderir.Type{{Main: shaderir.Vec2}},
|
||||
}
|
||||
// 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}},
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
@ -364,7 +372,7 @@ func ShaderProgramImages(imageNum int) shaderir.Program {
|
||||
Exprs: []shaderir.Expr{
|
||||
{
|
||||
Type: shaderir.UniformVariable,
|
||||
Index: graphics.TextureOffsetsUniformVariableIndex,
|
||||
Index: graphics.TextureSourceOffsetsUniformVariableIndex,
|
||||
},
|
||||
{
|
||||
Type: shaderir.NumberExpr,
|
||||
|
16
shader.go
16
shader.go
@ -49,19 +49,29 @@ func image%[1]dTextureSize() vec2 {
|
||||
}
|
||||
|
||||
shaderSuffix += fmt.Sprintf(`
|
||||
var __textureOffsets [%d]vec2
|
||||
`, graphics.ShaderImageNum-1)
|
||||
var __textureSourceOffsets [%[1]d]vec2
|
||||
var __textureSourceOrigin vec2
|
||||
var __textureSourceSizes [%[2]d]vec2
|
||||
`, graphics.ShaderImageNum-1, graphics.ShaderImageNum)
|
||||
|
||||
for i := 0; i < graphics.ShaderImageNum; i++ {
|
||||
var offset string
|
||||
if i >= 1 {
|
||||
offset = fmt.Sprintf(" + __textureOffsets[%d]", i-1)
|
||||
offset = fmt.Sprintf(" + __textureSourceOffsets[%d]", i-1)
|
||||
}
|
||||
// __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)
|
||||
}
|
||||
|
||||
func image%[1]dTextureBoundsAt(pos vec2) vec4 {
|
||||
return texture2D(__t%[1]d, pos%[2]s) *
|
||||
step(__textureSourceOrigin.x, pos.x) *
|
||||
(1 - step(__textureSourceOrigin.x + __textureSourceSizes[%[1]d].x, pos.x)) *
|
||||
step(__textureSourceOrigin.y, pos.y) *
|
||||
(1 - step(__textureSourceOrigin.y + __textureSourceSizes[%[1]d].y, pos.y))
|
||||
}
|
||||
`, i, offset)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user