mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-14 15:07:26 +01:00
Compare commits
1 Commits
142f503456
...
a666f485b8
Author | SHA1 | Date | |
---|---|---|---|
|
a666f485b8 |
9
image.go
9
image.go
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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{
|
||||||
{
|
{
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
152
shader_test.go
152
shader_test.go
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user