Compare commits

..

1 Commits

Author SHA1 Message Date
Bertrand Jung
a666f485b8
Merge 7dd4aa9150 into 88dae9c7d4 2024-04-12 23:11:56 +00:00
8 changed files with 135 additions and 215 deletions

View File

@ -711,8 +711,10 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
// //
// When the image i is disposed, DrawTrianglesShader does nothing. // When the image i is disposed, DrawTrianglesShader does nothing.
func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesShaderOptions) { func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesShaderOptions) {
if dsts[0] == nil || dsts[0].isDisposed() {
panic("ebiten: the first destination image given to DrawTrianglesShaderMRT must not be nil or disposed")
}
var dstImgs [graphics.ShaderDstImageCount]*ui.Image var dstImgs [graphics.ShaderDstImageCount]*ui.Image
var firstDst *Image
for i, dst := range dsts { for i, dst := range dsts {
if dst == nil { if dst == nil {
continue continue
@ -721,9 +723,6 @@ func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices
if dst.isDisposed() { if dst.isDisposed() {
panic("ebiten: the destination images given to DrawTrianglesShaderMRT must not be disposed") panic("ebiten: the destination images given to DrawTrianglesShaderMRT must not be disposed")
} }
if firstDst == nil {
firstDst = dst
}
dstImgs[i] = dst.image dstImgs[i] = dst.image
} }
@ -755,7 +754,7 @@ func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices
blend = options.CompositeMode.blend().internalBlend() blend = options.CompositeMode.blend().internalBlend()
} }
dst := firstDst dst := dsts[0]
vs := dst.ensureTmpVertices(len(vertices) * graphics.VertexFloatCount) vs := dst.ensureTmpVertices(len(vertices) * graphics.VertexFloatCount)
src := options.Images[0] src := options.Images[0]
for i, v := range vertices { for i, v := range vertices {

View File

@ -576,14 +576,12 @@ func drawTrianglesMRT(dsts [graphics.ShaderDstImageCount]*Image, srcs [graphics.
src.backend.sourceInThisFrame = true src.backend.sourceInThisFrame = true
} }
var firstDst *Image
var dstImgs [graphics.ShaderDstImageCount]*graphicscommand.Image var dstImgs [graphics.ShaderDstImageCount]*graphicscommand.Image
for i, dst := range dsts { for i, dst := range dsts {
if dst == nil { if dst == nil {
continue continue
} }
dst.ensureIsolatedFromSource(backends) dst.ensureIsolatedFromSource(backends)
firstDst = dst
dstImgs[i] = dst.backend.image dstImgs[i] = dst.backend.image
} }
@ -597,7 +595,7 @@ func drawTrianglesMRT(dsts [graphics.ShaderDstImageCount]*Image, srcs [graphics.
} }
} }
r := firstDst.regionWithPadding() r := dsts[0].regionWithPadding()
// TODO: Check if dstRegion does not to violate the region. // TODO: Check if dstRegion does not to violate the region.
dstRegion = dstRegion.Add(r.Min) dstRegion = dstRegion.Add(r.Min)

View File

@ -330,14 +330,7 @@ func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shade
copy(uniforms[graphics.PreservedUniformUint32Count:], origUniforms) copy(uniforms[graphics.PreservedUniformUint32Count:], origUniforms)
// Set the destination texture size. // Set the destination texture size.
var firstDst *Image dw, dh := dsts[0].InternalSize()
for _, dst := range dsts {
if dst != nil {
firstDst = dst
break
}
}
dw, dh := firstDst.InternalSize()
uniforms[0] = math.Float32bits(float32(dw)) uniforms[0] = math.Float32bits(float32(dw))
uniforms[1] = math.Float32bits(float32(dh)) uniforms[1] = math.Float32bits(float32(dh))
uniformIndex := 2 uniformIndex := 2

View File

@ -517,31 +517,30 @@ func (g *graphics11) removeShader(s *shader11) {
func (g *graphics11) setAsRenderTargets(dsts []*image11, useStencil bool) error { func (g *graphics11) setAsRenderTargets(dsts []*image11, useStencil bool) error {
var rtvs []*_ID3D11RenderTargetView var rtvs []*_ID3D11RenderTargetView
var dsv *_ID3D11DepthStencilView for _, i := range dsts {
for _, dst := range dsts {
// Ignore a nil image in case of MRT // Ignore a nil image in case of MRT
if dst == nil { if i == nil {
rtvs = append(rtvs, nil) rtvs = append(rtvs, nil)
continue continue
} }
if dst.renderTargetView == nil { if i.renderTargetView == nil {
rtv, err := g.device.CreateRenderTargetView(unsafe.Pointer(dst.texture), nil) rtv, err := g.device.CreateRenderTargetView(unsafe.Pointer(i.texture), nil)
if err != nil { if err != nil {
return err return err
} }
dst.renderTargetView = rtv i.renderTargetView = rtv
} }
rtvs = append(rtvs, dst.renderTargetView) rtvs = append(rtvs, i.renderTargetView)
if !useStencil || dsv != nil { if !useStencil {
continue continue
} }
if dst.screen { if i.screen {
return fmt.Errorf("directx: a stencil buffer is not available for a screen image") return fmt.Errorf("directx: a stencil buffer is not available for a screen image")
} }
if dst.stencil == nil { if i.stencil == nil {
w, h := dst.internalSize() w, h := i.internalSize()
s, err := g.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ s, err := g.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
Width: uint32(w), Width: uint32(w),
Height: uint32(h), Height: uint32(h),
@ -560,21 +559,20 @@ func (g *graphics11) setAsRenderTargets(dsts []*image11, useStencil bool) error
if err != nil { if err != nil {
return err return err
} }
dst.stencil = s i.stencil = s
} }
if dst.stencilView == nil { if i.stencilView == nil {
sv, err := g.device.CreateDepthStencilView(unsafe.Pointer(dst.stencil), nil) sv, err := g.device.CreateDepthStencilView(unsafe.Pointer(i.stencil), nil)
if err != nil { if err != nil {
return err return err
} }
dst.stencilView = sv i.stencilView = sv
} }
dsv = dst.stencilView
} }
g.deviceContext.OMSetRenderTargets(rtvs, dsv) g.deviceContext.OMSetRenderTargets(rtvs, dsts[0].stencilView)
if useStencil { if useStencil {
g.deviceContext.ClearDepthStencilView(dsv, uint8(_D3D11_CLEAR_STENCIL), 0, 0) g.deviceContext.ClearDepthStencilView(dsts[0].stencilView, uint8(_D3D11_CLEAR_STENCIL), 0, 0)
} }
return nil return nil
@ -587,7 +585,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
g.deviceContext.PSSetShaderResources(0, srvs[:]) g.deviceContext.PSSetShaderResources(0, srvs[:])
var dsts [graphics.ShaderDstImageCount]*image11 var dsts [graphics.ShaderDstImageCount]*image11
var vp _D3D11_VIEWPORT var viewports [graphics.ShaderDstImageCount]_D3D11_VIEWPORT
var targetCount int var targetCount int
firstTarget := -1 firstTarget := -1
for i, id := range dstIDs { for i, id := range dstIDs {
@ -600,7 +598,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
} }
dsts[i] = img dsts[i] = img
w, h := img.internalSize() w, h := img.internalSize()
vp = _D3D11_VIEWPORT{ viewports[i] = _D3D11_VIEWPORT{
TopLeftX: 0, TopLeftX: 0,
TopLeftY: 0, TopLeftY: 0,
Width: float32(w), Width: float32(w),
@ -623,12 +621,13 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
// If the number of targets is more than one, or if the only target is the first one, then // If the number of targets is more than one, or if the only target is the first one, then
// it is safe to assume that MRT is used. // it is safe to assume that MRT is used.
// Also, it only matters in order to specify empty targets/viewports when not all slots are // Also, it only matters in order to specify empty targets/viewports when not all slots are
// being filled, even though it's not a MRT scenario. // being filled.
if targetCount > 1 || firstTarget > 0 { if targetCount > 1 || firstTarget > 0 {
targetCount = graphics.ShaderDstImageCount targetCount = graphics.ShaderDstImageCount
} }
g.deviceContext.RSSetViewports(viewports[:targetCount])
g.deviceContext.RSSetViewports([]_D3D11_VIEWPORT{vp})
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil { if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
return err return err
} }

View File

@ -1084,7 +1084,7 @@ func (g *graphics12) NewShader(program *shaderir.Program) (graphicsdriver.Shader
func (g *graphics12) setAsRenderTargets(dsts []*image12, useStencil bool) error { func (g *graphics12) setAsRenderTargets(dsts []*image12, useStencil bool) error {
var rtvs []_D3D12_CPU_DESCRIPTOR_HANDLE var rtvs []_D3D12_CPU_DESCRIPTOR_HANDLE
var dsv *_D3D12_CPU_DESCRIPTOR_HANDLE var dsvPtr *_D3D12_CPU_DESCRIPTOR_HANDLE
for i, img := range dsts { for i, img := range dsts {
// Ignore a nil image in case of MRT // Ignore a nil image in case of MRT
@ -1127,18 +1127,18 @@ func (g *graphics12) setAsRenderTargets(dsts []*image12, useStencil bool) error
rtv := rtvBase rtv := rtvBase
rtvs = append(rtvs, rtv) rtvs = append(rtvs, rtv)
if !useStencil || dsv != nil { if !useStencil || dsvPtr != nil {
continue continue
} }
if err := img.ensureDepthStencilView(g.device); err != nil { if err := img.ensureDepthStencilView(g.device); err != nil {
return err return err
} }
sv, err := img.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() dsv, err := img.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
if err != nil { if err != nil {
return err return err
} }
dsv = &sv dsvPtr = &dsv
} }
if !useStencil { if !useStencil {
@ -1147,8 +1147,8 @@ func (g *graphics12) setAsRenderTargets(dsts []*image12, useStencil bool) error
} }
g.drawCommandList.OMSetStencilRef(0) g.drawCommandList.OMSetStencilRef(0)
g.drawCommandList.OMSetRenderTargets(rtvs, false, dsv) g.drawCommandList.OMSetRenderTargets(rtvs, false, dsvPtr)
g.drawCommandList.ClearDepthStencilView(*dsv, _D3D12_CLEAR_FLAG_STENCIL, 0, 0, nil) g.drawCommandList.ClearDepthStencilView(*dsvPtr, _D3D12_CLEAR_FLAG_STENCIL, 0, 0, nil)
return nil return nil
} }
@ -1177,7 +1177,7 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
var resourceBarriers []_D3D12_RESOURCE_BARRIER_Transition var resourceBarriers []_D3D12_RESOURCE_BARRIER_Transition
var dsts [graphics.ShaderDstImageCount]*image12 var dsts [graphics.ShaderDstImageCount]*image12
var vp _D3D12_VIEWPORT var viewports [graphics.ShaderDstImageCount]_D3D12_VIEWPORT
var targetCount int var targetCount int
firstTarget := -1 firstTarget := -1
for i, id := range dstIDs { for i, id := range dstIDs {
@ -1190,7 +1190,7 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
} }
dsts[i] = img dsts[i] = img
w, h := img.internalSize() w, h := img.internalSize()
vp = _D3D12_VIEWPORT{ viewports[i] = _D3D12_VIEWPORT{
TopLeftX: 0, TopLeftX: 0,
TopLeftY: 0, TopLeftY: 0,
Width: float32(w), Width: float32(w),
@ -1225,12 +1225,14 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
// If the number of targets is more than one, or if the only target is the first one, then // If the number of targets is more than one, or if the only target is the first one, then
// it is safe to assume that MRT is used. // it is safe to assume that MRT is used.
// Also, it only matters in order to specify empty targets/viewports when not all slots are // Also, it only matters in order to specify empty targets/viewports when not all slots are
// being filled, even though it's not a MRT scenario. // being filled.
usesMRT := targetCount > 1 || firstTarget > 0 usesMRT := targetCount > 1 || firstTarget > 0
if usesMRT { if usesMRT {
targetCount = graphics.ShaderDstImageCount targetCount = graphics.ShaderDstImageCount
} }
g.drawCommandList.RSSetViewports(viewports[:targetCount])
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil { if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
return err return err
} }
@ -1240,8 +1242,6 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
g.needFlushDrawCommandList = true g.needFlushDrawCommandList = true
g.drawCommandList.RSSetViewports([]_D3D12_VIEWPORT{vp})
g.drawCommandList.IASetPrimitiveTopology(_D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST) g.drawCommandList.IASetPrimitiveTopology(_D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
g.drawCommandList.IASetVertexBuffers(0, []_D3D12_VERTEX_BUFFER_VIEW{ g.drawCommandList.IASetVertexBuffers(0, []_D3D12_VERTEX_BUFFER_VIEW{
{ {

View File

@ -70,7 +70,7 @@ func (i *image12) disposeImpl() {
func (i *image12) ReadPixels(args []graphicsdriver.PixelsArgs) error { func (i *image12) ReadPixels(args []graphicsdriver.PixelsArgs) error {
if i.screen { if i.screen {
return errors.New("directx: ReadPixels cannot be called on the screen") return errors.New("directx: Pixels cannot be called on the screen")
} }
if err := i.graphics.flushCommandList(i.graphics.drawCommandList); err != nil { if err := i.graphics.flushCommandList(i.graphics.drawCommandList); err != nil {

View File

@ -484,18 +484,6 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
} }
// Create a pipeline state. // Create a pipeline state.
rtBlendDesc := _D3D12_RENDER_TARGET_BLEND_DESC{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
}
psoDesc := _D3D12_GRAPHICS_PIPELINE_STATE_DESC{ psoDesc := _D3D12_GRAPHICS_PIPELINE_STATE_DESC{
pRootSignature: rootSignature, pRootSignature: rootSignature,
VS: _D3D12_SHADER_BYTECODE{ VS: _D3D12_SHADER_BYTECODE{
@ -510,7 +498,102 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
AlphaToCoverageEnable: 0, AlphaToCoverageEnable: 0,
IndependentBlendEnable: 0, IndependentBlendEnable: 0,
RenderTarget: [8]_D3D12_RENDER_TARGET_BLEND_DESC{ RenderTarget: [8]_D3D12_RENDER_TARGET_BLEND_DESC{
rtBlendDesc, // TODO: need to fill them all? {
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
{
BlendEnable: 1,
LogicOpEnable: 0,
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
LogicOp: _D3D12_LOGIC_OP_NOOP,
RenderTargetWriteMask: writeMask,
},
}, },
}, },
SampleMask: math.MaxUint32, SampleMask: math.MaxUint32,

View File

@ -2595,155 +2595,3 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
} }
} }
} }
// Issue #2930
func TestShaderMRT(t *testing.T) {
const w, h = 16, 16
s, err := ebiten.NewShader([]byte(`//kage:unit pixels
package main
func Fragment(dstPos vec4, srcPos vec2, color vec4) (vec4, vec4, vec4, vec4, vec4, vec4, vec4, vec4) {
return vec4(1, 0, 0, 1),
vec4(0, 1, 0, 1),
vec4(0, 0, 1, 1),
vec4(1, 0, 1, 1),
vec4(1, 1, 0, 1),
vec4(0, 1, 1, 1),
vec4(1, 1, 1, 1),
vec4(1, 1, 1, 0)
}
`))
if err != nil {
t.Fatal(err)
}
bounds := image.Rect(0, 0, w, h)
opts := &ebiten.NewImageOptions{
Unmanaged: true,
}
vertices := []ebiten.Vertex{
{
DstX: 0,
DstY: 0,
},
{
DstX: w,
DstY: 0,
},
{
DstX: 0,
DstY: h,
},
{
DstX: w,
DstY: h,
},
}
indices := []uint16{0, 1, 2, 1, 2, 3}
t.Run("8 locations", func(t *testing.T) {
imgs := [8]*ebiten.Image{
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
}
wantColors := [8]color.RGBA{
{R: 0xff, G: 0, B: 0, A: 0xff},
{R: 0, G: 0xff, B: 0, A: 0xff},
{R: 0, G: 0, B: 0xff, A: 0xff},
{R: 0xff, G: 0, B: 0xff, A: 0xff},
{R: 0xff, G: 0xff, B: 0, A: 0xff},
{R: 0, G: 0xff, B: 0xff, A: 0xff},
{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
{R: 0xff, G: 0xff, B: 0xff, A: 0},
}
ebiten.DrawTrianglesShaderMRT(imgs, vertices, indices, s, nil)
for k, dst := range imgs {
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
want := wantColors[k]
if !sameColors(got, want, 1) {
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
}
}
}
}
})
/*t.Run("Empty locations", func(t *testing.T) {
imgs := [8]*ebiten.Image{
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
}
wantColors := [8]color.RGBA{
{},
{R: 0, G: 0xff, B: 0, A: 0xff},
{},
{R: 0xff, G: 0, B: 0xff, A: 0xff},
{},
{R: 0, G: 0xff, B: 0xff, A: 0xff},
{},
{R: 0xff, G: 0xff, B: 0xff, A: 0},
}
dsts := [8]*ebiten.Image{
nil, imgs[1], nil, imgs[3], nil, imgs[5], nil, imgs[7],
}
ebiten.DrawTrianglesShaderMRT(dsts, vertices, indices, s, nil)
for k, dst := range imgs {
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
want := wantColors[k]
if !sameColors(got, want, 1) {
t.Errorf("%d dst.At(%d, %d): got: %v, want: %v", k, i, j, got, want)
}
}
}
}
})*/
t.Run("1 location (first slot)", func(t *testing.T) {
imgs := [8]*ebiten.Image{
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
ebiten.NewImageWithOptions(bounds, opts),
}
wantColors := [8]color.RGBA{
{R: 0xff, G: 0, B: 0, A: 0xff},
{}, {}, {}, {}, {}, {}, {},
}
dsts := [8]*ebiten.Image{
imgs[0], nil, nil, nil, nil, nil, nil, nil,
}
ebiten.DrawTrianglesShaderMRT(dsts, vertices, indices, s, nil)
for k, dst := range imgs {
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
want := wantColors[k]
if !sameColors(got, want, 1) {
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
}
}
}
}
})
}