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"
"log"
"strings"
"fmt"
)
type Player struct {
@ -17,26 +18,65 @@ type Player 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 (
playerImg *gx.Image
)
func NewPlayer() *Player {
return &Player{
ret := &Player{
Sprite: &gx.Sprite{
T: gx.Transform {
S: gx.Vector{5, 5},
RA: gx.Vector{320, 240},
},
I: playerImg,
Visible: true,
Shader: gx.SolidWhiteColorShader,
},
MoveSpeed: 90.,
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.T.RA = gx.V(360, -240)
}
@ -130,28 +170,6 @@ func main() {
e.Add(0, NewPlayer())
e.Add(1, &Debug{})
e.Add(-1, gx.DrawableRectangle{
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.Add(-1, NewRect())
e.Run()
}

View file

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

View file

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

View file

@ -22,14 +22,19 @@ type Rectangle struct {
type DrawableRectangle struct {
Rectangle
Shader *Shader
// Solid color of the rectangle.
// Will be ignored if the Shader
// field is not nil.
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
}
@ -56,26 +61,29 @@ func NewImage(w, h int) (*Image) {
return ebiten.NewImage(w, h)
}
func (r DrawableRectangle) IsVisible() bool {
func (r *DrawableRectangle) IsVisible() bool {
return r.Visible
}
func (r DrawableRectangle) Draw(
func (r *DrawableRectangle) Draw(
e *Engine,
i *Image,
) {
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.
if r.Shader == nil {
img := NewImage(1, 1)
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{
GeoM: m,
}
@ -83,20 +91,35 @@ func (r DrawableRectangle) Draw(
return
}
// Use the Color as base image if no is provided.
if r.Options.Images[0] == nil {
r.Options.Images[0] = NewImage(1, 1)
r.Options.Images[0].Set(0, 0, r.Color)
var did bool
if r.Images[0] == nil {
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.
opts := &ebiten.DrawRectShaderOptions{
GeoM: m,
Images: r.Options.Images,
Uniforms: r.Options.Uniforms,
Images: r.Images,
Uniforms: r.Uniforms,
}
w, h := r.Options.Images[0].Size()
i.DrawRectShader(w, h, r.Shader, opts)
}

View file

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