Implemented shaders on sprites.

This commit is contained in:
Andrey Parhomenko 2023-05-26 18:31:04 +03:00
parent f913f95d61
commit b853924e19
5 changed files with 144 additions and 75 deletions

View file

@ -7,6 +7,7 @@ import (
"bytes" "bytes"
"log" "log"
"strings" "strings"
"fmt"
) )
type Player struct { type Player struct {
@ -17,26 +18,65 @@ type Player struct {
type Debug struct{} type Debug struct{}
type Rect struct {
*gx.DrawableRectangle
}
func NewRect() *Rect {
return &Rect{&gx.DrawableRectangle{
Rectangle: gx.Rectangle{
W: 200,
H: 400,
T: gx.T(),
},
Color: gx.Color{
gx.MaxColorV,
0,
0,
gx.MaxColorV,
},
Visible: true,
/*Shader: gx.SolidWhiteColorShader,
Options: gx.ShaderOptions{
Images: [4]*gx.Image{
playerImg,
nil,
nil,
nil,
},
},*/
}}
}
func (r *Rect) Update(e *gx.Engine) error {
return nil
}
var ( var (
playerImg *gx.Image playerImg *gx.Image
) )
func NewPlayer() *Player { func NewPlayer() *Player {
return &Player{ ret := &Player{
Sprite: &gx.Sprite{ Sprite: &gx.Sprite{
T: gx.Transform { T: gx.Transform {
S: gx.Vector{5, 5}, S: gx.Vector{5, 5},
RA: gx.Vector{320, 240}, RA: gx.Vector{320, 240},
}, },
I: playerImg,
Visible: true, Visible: true,
Shader: gx.SolidWhiteColorShader,
}, },
MoveSpeed: 90., MoveSpeed: 90.,
ScaleSpeed: .2, ScaleSpeed: .2,
} }
ret.Images[0] = playerImg
return ret
} }
func (p *Player) Start(e *gx.Engine) { func (p *Player) Start(e *gx.Engine, v ...any) {
fmt.Println("starting")
c := e.Camera() c := e.Camera()
c.T.RA = gx.V(360, -240) c.T.RA = gx.V(360, -240)
} }
@ -130,28 +170,6 @@ func main() {
e.Add(0, NewPlayer()) e.Add(0, NewPlayer())
e.Add(1, &Debug{}) e.Add(1, &Debug{})
e.Add(-1, gx.DrawableRectangle{ e.Add(-1, NewRect())
Rectangle: gx.Rectangle{
W: 4,
H: 4,
T: gx.T(),
},
Color: gx.Color{
gx.MaxColorV,
0,
0,
gx.MaxColorV,
},
Visible: true,
Shader: gx.SolidWhiteColorShader,
Options: gx.ShaderOptions{
Images: [4]*gx.Image{
playerImg,
nil,
nil,
nil,
},
},
})
e.Run() e.Run()
} }

View file

@ -20,8 +20,12 @@ type Layer int
// Window configuration type. // Window configuration type.
type WindowConfig struct { type WindowConfig struct {
Title string Title string
Width, Height int
FixedSize bool Width,
Height int
FixedSize,
Fullscreen,
VSync bool VSync bool
} }
@ -29,7 +33,7 @@ type WindowConfig struct {
type Engine struct { type Engine struct {
wcfg *WindowConfig wcfg *WindowConfig
layers *sparsex.Sparse[Layer, *poolx.Pool[Drawer]] layers *sparsex.Sparse[Layer, *poolx.Pool[Drawer]]
behavers *poolx.Pool[Behaver] updaters *poolx.Pool[Updater]
lastTime time.Time lastTime time.Time
dt Float dt Float
camera *Camera camera *Camera
@ -72,26 +76,36 @@ func New(
S: Vector{1, 1}, S: Vector{1, 1},
}, },
}, },
behavers: poolx.New[Behaver](), updaters: poolx.New[Updater](),
} }
} }
// Add new object considering what // Add new object considering what
// interfaces it implements. // interfaces it implements.
func (e *Engine) Add(l Layer, b any) { func (e *Engine) Add(l Layer, b any) {
beh, ok := b.(Behaver) starter, ok := b.(Starter)
if ok { if ok {
e.addBehaver(beh) starter.Start(e)
}
updater, ok := b.(Updater)
if ok {
e.addUpdater(updater)
} }
drw, ok := b.(Drawer) drawer, ok := b.(Drawer)
if ok { if ok {
e.addDrawer(l, drw) e.addDrawer(l, drawer)
} }
} }
// Del object from Engine. // Delete object from Engine.
func (e *Engine) Del(b any) { func (e *Engine) Del(b any, v ...any) {
deleter, ok := b.(Deleter)
if ok {
deleter.Delete(e, v...)
}
drawer, ok := b.(Drawer) drawer, ok := b.(Drawer)
if ok { if ok {
for layer := range e.layers.Vals() { for layer := range e.layers.Vals() {
@ -99,9 +113,9 @@ func (e *Engine) Del(b any) {
} }
} }
behaver, ok := b.(Behaver) updater, ok := b.(Updater)
if ok { if ok {
e.behavers.Del(behaver) e.updaters.Del(updater)
} }
} }
@ -121,9 +135,8 @@ func (e *Engine) addDrawer(l Layer, d Drawer) {
} }
func (e *Engine) addBehaver(b Behaver) { func (e *Engine) addUpdater(b Updater) {
e.behavers.Append(b) e.updaters.Append(b)
b.Start(e)
} }
func (e *engine) Update() error { func (e *engine) Update() error {
@ -134,7 +147,7 @@ func (e *engine) Update() error {
AppendPressedKeys(e.keys[:0]) AppendPressedKeys(e.keys[:0])
e.dt = time.Since(e.lastTime).Seconds() e.dt = time.Since(e.lastTime).Seconds()
for p := range eng.behavers.Range() { for p := range eng.updaters.Range() {
err = p.V.Update(eng) err = p.V.Update(eng)
if err != nil { if err != nil {
return err return err

View file

@ -4,8 +4,9 @@ package gx
// will call the function OnStart // will call the function OnStart
// when first appear on scene BEFORE // when first appear on scene BEFORE
// the OnUpdate. // the OnUpdate.
// The v value will be get from Add function.
type Starter interface { type Starter interface {
Start(*Engine) Start(*Engine, ...any)
} }
// Implementing the interface type // Implementing the interface type
@ -15,9 +16,10 @@ type Updater interface {
Update(*Engine) error Update(*Engine) error
} }
// The general interface for // Implementing the interface type
type Behaver interface { // will call the function on deleting
Starter // the object.
Updater type Deleter interface {
Delete(*Engine, ...any)
} }

View file

@ -22,14 +22,19 @@ type Rectangle struct {
type DrawableRectangle struct { type DrawableRectangle struct {
Rectangle Rectangle
Shader *Shader
// Solid color of the rectangle. // Solid color of the rectangle.
// Will be ignored if the Shader // Will be ignored if the Shader
// field is not nil. // field is not nil.
Color Color Color Color
Options ShaderOptions // Shader to be applied
Shader *Shader
// Shader variables.
Uniforms map[string] any
// Shader images
Images [4]*Image
// Should be draw or not.
Visible bool Visible bool
} }
@ -56,26 +61,29 @@ func NewImage(w, h int) (*Image) {
return ebiten.NewImage(w, h) return ebiten.NewImage(w, h)
} }
func (r DrawableRectangle) IsVisible() bool { func (r *DrawableRectangle) IsVisible() bool {
return r.Visible return r.Visible
} }
func (r DrawableRectangle) Draw( func (r *DrawableRectangle) Draw(
e *Engine, e *Engine,
i *Image, i *Image,
) { ) {
t := r.T t := r.T
t.S.X *= r.W
t.S.Y *= r.H
rm := e.Camera().RealMatrix(e, true)
m := t.Matrix(e)
m.Concat(rm)
// Draw solid color if no shader. // Draw solid color if no shader.
if r.Shader == nil { if r.Shader == nil {
img := NewImage(1, 1) img := NewImage(1, 1)
img.Set(0, 0, r.Color) img.Set(0, 0, r.Color)
t.S.X *= r.W
t.S.Y *= r.H
m := t.Matrix(e)
rm := e.Camera().RealMatrix(e, true)
m.Concat(rm)
opts := &ebiten.DrawImageOptions{ opts := &ebiten.DrawImageOptions{
GeoM: m, GeoM: m,
} }
@ -83,20 +91,35 @@ func (r DrawableRectangle) Draw(
return return
} }
// Use the Color as base image if no is provided. // Use the Color as base image if no is provided.
if r.Options.Images[0] == nil { var did bool
r.Options.Images[0] = NewImage(1, 1) if r.Images[0] == nil {
r.Options.Images[0].Set(0, 0, r.Color) r.Images[0] = NewImage(1, 1)
r.Images[0].Set(0, 0, r.Color)
did = true
} }
w, h := r.Images[0].Size()
if !did {
t.S.X /= Float(w)
t.S.Y /= Float(h)
t.S.X *= r.W
t.S.Y *= r.H
}
rm := e.Camera().RealMatrix(e, true)
m := t.Matrix(e)
m.Concat(rm)
// Drawing with shader. // Drawing with shader.
opts := &ebiten.DrawRectShaderOptions{ opts := &ebiten.DrawRectShaderOptions{
GeoM: m, GeoM: m,
Images: r.Options.Images, Images: r.Images,
Uniforms: r.Options.Uniforms, Uniforms: r.Uniforms,
} }
w, h := r.Options.Images[0].Size()
i.DrawRectShader(w, h, r.Shader, opts) i.DrawRectShader(w, h, r.Shader, opts)
} }

View file

@ -5,9 +5,10 @@ import (
) )
type Sprite struct { type Sprite struct {
I *Image
T Transform T Transform
S *Shader Shader *Shader
Images [4]*Image
Uniforms map[string] any
Floating, Visible bool Floating, Visible bool
} }
@ -15,25 +16,37 @@ func (s *Sprite) Draw(
e *Engine, e *Engine,
i *Image, i *Image,
) { ) {
op := &ebiten.DrawImageOptions{ // Nothing to draw.
if s.Images[0] == nil {
return
} }
m := &Matrix{} m := &Matrix{}
m.Concat(s.T.Matrix(e)) m.Concat(s.T.Matrix(e))
if e.camera != nil { if !s.Floating {
m.Concat(e.camera.RealMatrix( m.Concat(e.Camera().RealMatrix(
e, e,
true, true,
)) ))
} }
op.GeoM = *m // Drawing without shader.
/*if s.S != nil { if s.Shader == nil {
bufImg := ebiten.NewImageFromImage(s.I) opts := &ebiten.DrawImageOptions{}
} */ opts.GeoM = *m
i.DrawImage(s.Images[0], opts)
return
}
i.DrawImage(s.I, op) // Drawing with shader.
w, h := s.Images[0].Size()
opts := &ebiten.DrawRectShaderOptions{
Images: s.Images,
Uniforms: s.Uniforms,
GeoM: *m,
}
i.DrawRectShader(w, h, s.Shader, opts)
} }
func (s *Sprite) IsVisible() bool { func (s *Sprite) IsVisible() bool {