mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-14 15:07:26 +01:00
Compare commits
6 Commits
e7bb66bb2f
...
230619a036
Author | SHA1 | Date | |
---|---|---|---|
|
230619a036 | ||
|
b6252a41f2 | ||
|
0651803c40 | ||
|
ea6fce45ff | ||
|
66667fe877 | ||
|
7842942b24 |
1
doc.go
1
doc.go
@ -81,6 +81,7 @@
|
|||||||
//
|
//
|
||||||
// "debug": Use a debug layer.
|
// "debug": Use a debug layer.
|
||||||
// "warp": Use WARP (i.e. software rendering).
|
// "warp": Use WARP (i.e. software rendering).
|
||||||
|
// "tearing": Allow tearing when vsync is off.
|
||||||
// "version=VERSION": Specify a DirectX version (e.g. 11).
|
// "version=VERSION": Specify a DirectX version (e.g. 11).
|
||||||
// "featurelevel=FEATURE_LEVEL": Specify a feature level (e.g. 11_0). This is for DirectX 12.
|
// "featurelevel=FEATURE_LEVEL": Specify a feature level (e.g. 11_0). This is for DirectX 12.
|
||||||
//
|
//
|
||||||
|
@ -14,14 +14,19 @@
|
|||||||
|
|
||||||
//go:build ignore
|
//go:build ignore
|
||||||
|
|
||||||
|
// Specify the 'pixel' mode.
|
||||||
//kage:unit pixels
|
//kage:unit pixels
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
// Uniform variables.
|
||||||
var Time float
|
var Time float
|
||||||
var Cursor vec2
|
var Cursor vec2
|
||||||
|
|
||||||
|
// Fragment is the entry point of the fragment shader.
|
||||||
|
// Fragment returns the color value for the current position.
|
||||||
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
||||||
|
// You can define variables with a short variable declaration like Go.
|
||||||
pos := dstPos.xy - imageDstOrigin()
|
pos := dstPos.xy - imageDstOrigin()
|
||||||
|
|
||||||
lightpos := vec3(Cursor, 50)
|
lightpos := vec3(Cursor, 50)
|
||||||
@ -29,5 +34,8 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
|||||||
normal := normalize(imageSrc1UnsafeAt(srcPos) - 0.5)
|
normal := normalize(imageSrc1UnsafeAt(srcPos) - 0.5)
|
||||||
const ambient = 0.25
|
const ambient = 0.25
|
||||||
diffuse := 0.75 * max(0.0, dot(normal.xyz, lightdir))
|
diffuse := 0.75 * max(0.0, dot(normal.xyz, lightdir))
|
||||||
|
|
||||||
|
// You can treat multiple source images by
|
||||||
|
// imageSrc[N]At or imageSrc[N]UnsafeAt.
|
||||||
return imageSrc0UnsafeAt(srcPos) * (ambient + diffuse)
|
return imageSrc0UnsafeAt(srcPos) * (ambient + diffuse)
|
||||||
}
|
}
|
||||||
|
@ -140,12 +140,16 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{}
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
op.AntiAlias = aa
|
op.AntiAlias = aa
|
||||||
if !line {
|
|
||||||
// ebiten.EvenOdd is also fine here.
|
// For strokes (AppendVerticesAndIndicesForStroke), FillAll and NonZero work.
|
||||||
// NonZero and EvenOdd differ when rendering a complex polygons with self-intersections and/or holes.
|
//
|
||||||
// See https://en.wikipedia.org/wiki/Nonzero-rule and https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule .
|
// For filling (AppendVerticesAndIndicesForFilling), NonZero and EvenOdd work.
|
||||||
op.FillRule = ebiten.NonZero
|
// NonZero and EvenOdd differ when rendering a complex polygons with self-intersections and/or holes.
|
||||||
}
|
// See https://en.wikipedia.org/wiki/Nonzero-rule and https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule .
|
||||||
|
//
|
||||||
|
// For simplicity, this example always uses NonZero, whichever strokes or filling is done.
|
||||||
|
op.FillRule = ebiten.NonZero
|
||||||
|
|
||||||
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,9 +203,7 @@ func drawEbitenLogo(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{}
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
op.AntiAlias = aa
|
op.AntiAlias = aa
|
||||||
if !line {
|
op.FillRule = ebiten.NonZero
|
||||||
op.FillRule = ebiten.NonZero
|
|
||||||
}
|
|
||||||
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,9 +245,7 @@ func drawArc(screen *ebiten.Image, count int, aa bool, line bool) {
|
|||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{}
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
op.AntiAlias = aa
|
op.AntiAlias = aa
|
||||||
if !line {
|
op.FillRule = ebiten.NonZero
|
||||||
op.FillRule = ebiten.NonZero
|
|
||||||
}
|
|
||||||
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,9 +300,7 @@ func drawWave(screen *ebiten.Image, counter int, aa bool, line bool) {
|
|||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{}
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
op.AntiAlias = aa
|
op.AntiAlias = aa
|
||||||
if !line {
|
op.FillRule = ebiten.NonZero
|
||||||
op.FillRule = ebiten.NonZero
|
|
||||||
}
|
|
||||||
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
screen.DrawTriangles(vs, is, whiteSubImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ type graphics11 struct {
|
|||||||
newScreenHeight int
|
newScreenHeight int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGraphics11(useWARP bool, useDebugLayer bool) (gr11 *graphics11, ferr error) {
|
func newGraphics11(useWARP bool, useDebugLayer bool, allowTearing bool) (gr11 *graphics11, ferr error) {
|
||||||
g := &graphics11{
|
g := &graphics11{
|
||||||
vsyncEnabled: true,
|
vsyncEnabled: true,
|
||||||
}
|
}
|
||||||
@ -207,7 +207,7 @@ func newGraphics11(useWARP bool, useDebugLayer bool) (gr11 *graphics11, ferr err
|
|||||||
}
|
}
|
||||||
dxgiFactory := (*_IDXGIFactory)(df)
|
dxgiFactory := (*_IDXGIFactory)(df)
|
||||||
|
|
||||||
gi, err := newGraphicsInfra(dxgiFactory)
|
gi, err := newGraphicsInfra(dxgiFactory, allowTearing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ type graphics12 struct {
|
|||||||
pipelineStates
|
pipelineStates
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGraphics12(useWARP bool, useDebugLayer bool, featureLevel _D3D_FEATURE_LEVEL) (*graphics12, error) {
|
func newGraphics12(useWARP bool, useDebugLayer bool, allowTearing bool, featureLevel _D3D_FEATURE_LEVEL) (*graphics12, error) {
|
||||||
g := &graphics12{}
|
g := &graphics12{}
|
||||||
|
|
||||||
// Initialize not only a device but also other members like a fence.
|
// Initialize not only a device but also other members like a fence.
|
||||||
@ -116,7 +116,7 @@ func newGraphics12(useWARP bool, useDebugLayer bool, featureLevel _D3D_FEATURE_L
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := g.initializeDesktop(useWARP, useDebugLayer, featureLevel); err != nil {
|
if err := g.initializeDesktop(useWARP, useDebugLayer, allowTearing, featureLevel); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ func newGraphics12(useWARP bool, useDebugLayer bool, featureLevel _D3D_FEATURE_L
|
|||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *graphics12) initializeDesktop(useWARP bool, useDebugLayer bool, featureLevel _D3D_FEATURE_LEVEL) (ferr error) {
|
func (g *graphics12) initializeDesktop(useWARP bool, useDebugLayer bool, allowTearing bool, featureLevel _D3D_FEATURE_LEVEL) (ferr error) {
|
||||||
if err := d3d12.Load(); err != nil {
|
if err := d3d12.Load(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ func (g *graphics12) initializeDesktop(useWARP bool, useDebugLayer bool, feature
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gi, err := newGraphicsInfra(f)
|
gi, err := newGraphicsInfra(f, allowTearing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,7 @@ func NewGraphics() (graphicsdriver.Graphics, error) {
|
|||||||
|
|
||||||
var useWARP bool
|
var useWARP bool
|
||||||
var useDebugLayer bool
|
var useDebugLayer bool
|
||||||
|
var allowTearing bool
|
||||||
version := 11
|
version := 11
|
||||||
|
|
||||||
// Specify the feature level 11 by default.
|
// Specify the feature level 11 by default.
|
||||||
@ -108,6 +109,8 @@ func NewGraphics() (graphicsdriver.Graphics, error) {
|
|||||||
useWARP = true
|
useWARP = true
|
||||||
case t == "debug":
|
case t == "debug":
|
||||||
useDebugLayer = true
|
useDebugLayer = true
|
||||||
|
case t == "tearing":
|
||||||
|
allowTearing = true
|
||||||
case strings.HasPrefix(t, "version="):
|
case strings.HasPrefix(t, "version="):
|
||||||
v, err := strconv.Atoi(t[len("version="):])
|
v, err := strconv.Atoi(t[len("version="):])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -130,13 +133,13 @@ func NewGraphics() (graphicsdriver.Graphics, error) {
|
|||||||
|
|
||||||
switch version {
|
switch version {
|
||||||
case 11:
|
case 11:
|
||||||
g, err := newGraphics11(useWARP, useDebugLayer)
|
g, err := newGraphics11(useWARP, useDebugLayer, allowTearing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return g, nil
|
return g, nil
|
||||||
case 12:
|
case 12:
|
||||||
g, err := newGraphics12(useWARP, useDebugLayer, featureLevel)
|
g, err := newGraphics12(useWARP, useDebugLayer, allowTearing, featureLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -163,19 +166,21 @@ type graphicsInfra struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newGraphicsInfra takes the ownership of the given factory.
|
// newGraphicsInfra takes the ownership of the given factory.
|
||||||
func newGraphicsInfra(factory *_IDXGIFactory) (*graphicsInfra, error) {
|
func newGraphicsInfra(factory *_IDXGIFactory, allowTearing bool) (*graphicsInfra, error) {
|
||||||
g := &graphicsInfra{
|
g := &graphicsInfra{
|
||||||
factory: factory,
|
factory: factory,
|
||||||
}
|
}
|
||||||
runtime.SetFinalizer(g, (*graphicsInfra).release)
|
runtime.SetFinalizer(g, (*graphicsInfra).release)
|
||||||
|
|
||||||
if f, err := g.factory.QueryInterface(&_IID_IDXGIFactory5); err == nil && f != nil {
|
if allowTearing {
|
||||||
factory := (*_IDXGIFactory5)(f)
|
if f, err := g.factory.QueryInterface(&_IID_IDXGIFactory5); err == nil && f != nil {
|
||||||
defer factory.Release()
|
factory := (*_IDXGIFactory5)(f)
|
||||||
|
defer factory.Release()
|
||||||
|
|
||||||
var allowTearing int32
|
var allowTearing int32
|
||||||
if err := factory.CheckFeatureSupport(_DXGI_FEATURE_PRESENT_ALLOW_TEARING, unsafe.Pointer(&allowTearing), uint32(unsafe.Sizeof(allowTearing))); err == nil && allowTearing != 0 {
|
if err := factory.CheckFeatureSupport(_DXGI_FEATURE_PRESENT_ALLOW_TEARING, unsafe.Pointer(&allowTearing), uint32(unsafe.Sizeof(allowTearing))); err == nil && allowTearing != 0 {
|
||||||
g.allowTearing = true
|
g.allowTearing = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,8 +492,8 @@ func (cs *compileState) assign(block *block, fname string, pos token.Pos, lhs, r
|
|||||||
var rhsTypes []shaderir.Type
|
var rhsTypes []shaderir.Type
|
||||||
allblank := true
|
allblank := true
|
||||||
|
|
||||||
for i, e := range lhs {
|
if len(lhs) == len(rhs) {
|
||||||
if len(lhs) == len(rhs) {
|
for i, e := range lhs {
|
||||||
// Prase RHS first for the order of the statements.
|
// Prase RHS first for the order of the statements.
|
||||||
r, rts, ss, ok := cs.parseExpr(block, fname, rhs[i], true)
|
r, rts, ss, ok := cs.parseExpr(block, fname, rhs[i], true)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -582,6 +582,12 @@ func (cs *compileState) assign(block *block, fname string, pos token.Pos, lhs, r
|
|||||||
cs.addError(pos, fmt.Sprintf("cannot use type %s as type %s in variable declaration", rts[i].String(), lts[i].String()))
|
cs.addError(pos, fmt.Sprintf("cannot use type %s as type %s in variable declaration", rts[i].String(), lts[i].String()))
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
switch lts[0].Main {
|
||||||
|
case shaderir.Int:
|
||||||
|
r[i].Const = gconstant.ToInt(r[i].Const)
|
||||||
|
case shaderir.Float:
|
||||||
|
r[i].Const = gconstant.ToFloat(r[i].Const)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(lhs) == 1 {
|
if len(lhs) == 1 {
|
||||||
@ -621,20 +627,21 @@ func (cs *compileState) assign(block *block, fname string, pos token.Pos, lhs, r
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if i == 0 {
|
} else {
|
||||||
var ss []shaderir.Stmt
|
var ss []shaderir.Stmt
|
||||||
var ok bool
|
var ok bool
|
||||||
rhsExprs, rhsTypes, ss, ok = cs.parseExpr(block, fname, rhs[0], true)
|
rhsExprs, rhsTypes, ss, ok = cs.parseExpr(block, fname, rhs[0], true)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
if len(rhsExprs) != len(lhs) {
|
if len(lhs) != len(rhsExprs) {
|
||||||
cs.addError(pos, "single-value context and multiple-value context cannot be mixed")
|
cs.addError(pos, fmt.Sprintf("assignment mismatch: %d variables but %d", len(lhs), len(rhsExprs)))
|
||||||
}
|
return nil, false
|
||||||
stmts = append(stmts, ss...)
|
}
|
||||||
}
|
stmts = append(stmts, ss...)
|
||||||
|
|
||||||
|
for i, e := range lhs {
|
||||||
if define {
|
if define {
|
||||||
if _, ok := e.(*ast.Ident); !ok {
|
if _, ok := e.(*ast.Ident); !ok {
|
||||||
cs.addError(pos, "non-name on the left side of :=")
|
cs.addError(pos, "non-name on the left side of :=")
|
||||||
|
@ -4103,6 +4103,48 @@ func Bar() {
|
|||||||
`)); err != nil {
|
`)); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := compileToIR([]byte(`package main
|
||||||
|
|
||||||
|
func Foo() {
|
||||||
|
a, b := 0
|
||||||
|
_, _ = a, b
|
||||||
|
}
|
||||||
|
`)); err == nil {
|
||||||
|
t.Error("compileToIR must return an error but did not")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := compileToIR([]byte(`package main
|
||||||
|
|
||||||
|
func Foo() {
|
||||||
|
a, b, c := 0, 0
|
||||||
|
_, _ = a, b, c
|
||||||
|
}
|
||||||
|
`)); err == nil {
|
||||||
|
t.Error("compileToIR must return an error but did not")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := compileToIR([]byte(`package main
|
||||||
|
|
||||||
|
func Foo() {
|
||||||
|
var a, b int
|
||||||
|
a, b = 0
|
||||||
|
_, _ = a, b
|
||||||
|
}
|
||||||
|
`)); err == nil {
|
||||||
|
t.Error("compileToIR must return an error but did not")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := compileToIR([]byte(`package main
|
||||||
|
|
||||||
|
func Foo() {
|
||||||
|
var a, b, c int
|
||||||
|
a, b, c = 0, 0
|
||||||
|
_, _ = a, b, c
|
||||||
|
}
|
||||||
|
`)); err == nil {
|
||||||
|
t.Error("compileToIR must return an error but did not")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyntaxBitwiseOperator(t *testing.T) {
|
func TestSyntaxBitwiseOperator(t *testing.T) {
|
||||||
|
10
internal/shader/testdata/issue2655.expected.vs
vendored
10
internal/shader/testdata/issue2655.expected.vs
vendored
@ -5,7 +5,7 @@ void F2(in bool l0, out float l1, out vec2 l2);
|
|||||||
float F0(void) {
|
float F0(void) {
|
||||||
float l0 = float(0);
|
float l0 = float(0);
|
||||||
{
|
{
|
||||||
l0 = 0;
|
l0 = 0.0;
|
||||||
}
|
}
|
||||||
return l0;
|
return l0;
|
||||||
}
|
}
|
||||||
@ -14,9 +14,9 @@ void F1(out float l0, out vec2 l1) {
|
|||||||
float l2 = float(0);
|
float l2 = float(0);
|
||||||
vec2 l3 = vec2(0);
|
vec2 l3 = vec2(0);
|
||||||
{
|
{
|
||||||
int l4 = 0;
|
float l4 = float(0);
|
||||||
vec2 l5 = vec2(0);
|
vec2 l5 = vec2(0);
|
||||||
l4 = 0;
|
l4 = 0.0;
|
||||||
l2 = l4;
|
l2 = l4;
|
||||||
l5 = vec2(0.0);
|
l5 = vec2(0.0);
|
||||||
l3 = l5;
|
l3 = l5;
|
||||||
@ -30,9 +30,9 @@ void F2(in bool l0, out float l1, out vec2 l2) {
|
|||||||
float l3 = float(0);
|
float l3 = float(0);
|
||||||
vec2 l4 = vec2(0);
|
vec2 l4 = vec2(0);
|
||||||
{
|
{
|
||||||
int l5 = 0;
|
float l5 = float(0);
|
||||||
vec2 l6 = vec2(0);
|
vec2 l6 = vec2(0);
|
||||||
l5 = 0;
|
l5 = 0.0;
|
||||||
l3 = l5;
|
l3 = l5;
|
||||||
l6 = vec2(0.0);
|
l6 = vec2(0.0);
|
||||||
l4 = l6;
|
l4 = l6;
|
||||||
|
@ -2559,3 +2559,39 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #2934
|
||||||
|
func TestShaderAssignConst(t *testing.T) {
|
||||||
|
const w, h = 16, 16
|
||||||
|
|
||||||
|
dst := ebiten.NewImage(w, h)
|
||||||
|
s, err := ebiten.NewShader([]byte(`//kage:unit pixels
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
||||||
|
a := 0.0
|
||||||
|
a = 1
|
||||||
|
b, c := 0.0, 0.0
|
||||||
|
b, c = 1, 1
|
||||||
|
d := 0.0
|
||||||
|
d += 1
|
||||||
|
return vec4(a, b, c, d)
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.DrawRectShader(w, h, s, nil)
|
||||||
|
|
||||||
|
for j := 0; j < h; j++ {
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
got := dst.At(i, j).(color.RGBA)
|
||||||
|
want := color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
|
||||||
|
if !sameColors(got, want, 2) {
|
||||||
|
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -480,7 +480,7 @@ type StrokeOptions struct {
|
|||||||
// The returned vertice's SrcX and SrcY are 0, and ColorR, ColorG, ColorB, and ColorA are 1.
|
// The returned vertice's SrcX and SrcY are 0, and ColorR, ColorG, ColorB, and ColorA are 1.
|
||||||
//
|
//
|
||||||
// The returned values are intended to be passed to DrawTriangles or DrawTrianglesShader with a solid (non-transparent) color
|
// The returned values are intended to be passed to DrawTriangles or DrawTrianglesShader with a solid (non-transparent) color
|
||||||
// with the FillAll fill rule (not NonZero or EvenOdd fill rule).
|
// with FillAll or NonZero fill rule, not EvenOdd fill rule.
|
||||||
func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indices []uint16, op *StrokeOptions) ([]ebiten.Vertex, []uint16) {
|
func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indices []uint16, op *StrokeOptions) ([]ebiten.Vertex, []uint16) {
|
||||||
if op == nil {
|
if op == nil {
|
||||||
return vertices, indices
|
return vertices, indices
|
||||||
@ -536,7 +536,8 @@ func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indic
|
|||||||
ColorA: 1,
|
ColorA: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3)
|
// All the triangles are rendered in clockwise order to enable NonZero filling rule (#2833).
|
||||||
|
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+3, idx+2)
|
||||||
|
|
||||||
// Add line joints.
|
// Add line joints.
|
||||||
var nextRect [4]point
|
var nextRect [4]point
|
||||||
|
Loading…
Reference in New Issue
Block a user