summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidovski <david@davidovski.xyz>2024-04-22 14:55:24 +0100
committerdavidovski <david@davidovski.xyz>2024-04-22 14:55:24 +0100
commiteeca23dc59e60def65dfefc28b69d6cfc85467ff (patch)
treed875998b4d335e766cf7a4dce0421705a638837e
parentca826dfbc5d0e39e2fc96a4fb13565d82ad81cf5 (diff)
add clouds in bg
-rw-r--r--main.go28
-rw-r--r--shaders/clouds.kage132
-rw-r--r--shaders/vcr.kage12
3 files changed, 162 insertions, 10 deletions
diff --git a/main.go b/main.go
index 500d82a..a05d2ec 100644
--- a/main.go
+++ b/main.go
@@ -44,6 +44,9 @@ var (
//go:embed shaders/vcr.kage
vcrShader_src []byte
+ //go:embed shaders/clouds.kage
+ cloudShader_src []byte
+
//go:embed assets/tiles.png
tilesPng_src []byte
@@ -146,6 +149,7 @@ func (g * Game)ReplayPoint() {
obj.vy = point.vy
obj.alpha = point.alpha
}
+ g.time -=1
}
func (g * Game)ResetPlayerAi() {
@@ -205,7 +209,7 @@ func (g * Game) ResetAll() {
func (g *Game) Init() {
g.surface = ebiten.NewImage(screenWidth, screenHeight)
- g.shaderName = "none"
+ g.shaderName = "sky"
g.player = NewPlayer(g, 4 * tileSize, 9 * tileSize)
g.objects = append(g.objects, g.player)
@@ -281,6 +285,7 @@ func (g *Game) Update() error {
}
if g.state == REVERSING {
+ g.time -= 1
for x := 0; x < rewindSpeed; x++ {
g.ReplayPoint()
}
@@ -364,9 +369,18 @@ func (g *Game) PlaceObject(cx, cy int) {
}
+func DrawBackground(screen *ebiten.Image, time int) {
+ shop := &ebiten.DrawRectShaderOptions{}
+ shop.Uniforms = map[string]any{
+ "Time": float32(time) / 60,
+ }
+ screen.DrawRectShader(screenWidth, screenHeight, shaders["sky"], shop)
+}
+
func (g *Game) Draw(screen *ebiten.Image) {
g.surface.Fill(color.Alpha16{0x9ccf})
+ DrawBackground(g.surface, g.time)
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(g.offsetX), float64(g.offsetY))
@@ -406,7 +420,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
shop.Images[3] = g.surface
screen.DrawRectShader(screenWidth, screenHeight, shaders[g.shaderName], shop)
- //ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.ActualTPS()))
+ ebitenutil.DebugPrint(screen, fmt.Sprintf("shader: %s", g.shaderName))
//screen.DrawImage(surface, &ebiten.DrawImageOptions{})
}
@@ -430,6 +444,10 @@ func LoadShaders() error {
return err
}
+ shaders["sky"], err = ebiten.NewShader([]byte(cloudShader_src))
+ if err != nil {
+ return err
+ }
return nil
}
func (g *Game) KillPlayer() {
@@ -563,8 +581,10 @@ func (g *Game) LoadImages() {
}
func main() {
- LoadShaders()
-
+ err := LoadShaders()
+ if err != nil {
+ log.Fatal(err)
+ }
ebiten.SetWindowTitle("Hello, World!")
game := &Game{}
game.LoadAudio()
diff --git a/shaders/clouds.kage b/shaders/clouds.kage
new file mode 100644
index 0000000..26597e5
--- /dev/null
+++ b/shaders/clouds.kage
@@ -0,0 +1,132 @@
+//go:build ignore
+
+//kage:unit pixels
+
+package main
+
+var Time float
+
+const cloudscale = 0.8
+const speed = 0.01
+const clouddark = 0.6
+const cloudlight = 0.3
+const cloudcover = 0.2
+const cloudalpha = 8.0
+const skytint = 0.5
+
+func rand(co vec2) float {
+ return fract(sin(dot(co.xy, vec2(12.9898,-78.233))) * 43758.5453)
+}
+
+func hash( p vec2 ) vec2 {
+ p = vec2(dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)))
+ return -1.0 + 2.0*fract(sin(p)*43758.5453123)
+}
+
+func noise( p vec2 ) float {
+ const K1 = 0.366025404
+ const K2 = 0.211324865
+ i := floor(p + (p.x+p.y)*K1);
+ a := p - i + (i.x+i.y)*K2
+
+ var o vec2
+ if (a.x>a.y) {
+ o = vec2(1.0,0.0)
+ } else {
+ o = vec2(0.0,1.0)
+ }
+
+ b := a - o + K2
+ c := a - 1.0 + 2.0*K2
+ h := max(0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0)
+ n := h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)))
+ return dot(n, vec3(70.0))
+}
+
+
+
+func fbm(n vec2) float {
+ v := n
+ total := 0.0
+ amplitude := 0.1
+ for i := 0; i < 7; i++ {
+ total += noise(v) * amplitude
+ v = mat2(1.6, 1.2, -1.2, 1.6) * v
+ amplitude *= 0.4
+ }
+ return total
+}
+
+func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
+ m := mat2(1.6, 1.2, -1.2, 1.6)
+ skycolour1 := vec3(0.45, 0.57, 0.66)
+ skycolour2 := vec3(0.55, 0.77, 0.86)
+
+ p := srcPos.xy / imageSrc0Size().xy;
+ uv := p*vec2(imageSrc0Size().x/imageSrc0Size().y,1.0);
+ time := Time * speed
+ q := fbm(uv * cloudscale * 0.5)
+
+ //ridged noise shape
+ r := 0.0
+ uv *= cloudscale
+ uv.x -= q - time
+ weight := 0.8
+ for i:=0; i<8; i++{
+ r += abs(weight*noise( uv ))
+ uv = m*uv + time
+ weight *= 0.7
+ }
+
+ //noise shape
+ f := 0.0
+ uv = p*vec2(imageSrc0Size().x/imageSrc0Size().y,1.0);
+ uv *= cloudscale
+ uv.x -= q - time
+ weight = 0.7
+ for i:=0;i<8;i++{
+ f += weight*noise( uv )
+ uv = m*uv + time
+ weight *= 0.6
+ }
+
+ f *= r + f
+
+ //noise colour
+ c := 0.0
+ time = Time * speed * 2.0
+ uv = p*vec2(imageSrc0Size().x/imageSrc0Size().y,1.0)
+ uv *= cloudscale*2.0
+ uv.x -= q - time
+ weight = 0.4
+ for i:=0;i<7;i++{
+ c += weight*noise( uv )
+ uv = m*uv + time
+ weight *= 0.6
+ }
+
+ //noise ridge colour
+ c1 := 0.0
+ time = Time * speed * 3.0
+ uv = p*vec2(imageSrc0Size().x/imageSrc0Size().y,1.0)
+ uv *= cloudscale*3.0
+ uv.x -= q - time
+ weight = 0.4
+ for i:=0; i<7; i++{
+ c1 += abs(weight*noise( uv ))
+ uv = m*uv + time
+ weight *= 0.6
+ }
+
+ c += c1
+
+ skycolour := mix(skycolour2, skycolour1, p.y);
+ cloudcolour := vec3(1.1, 1.1, 0.9) * clamp((clouddark + cloudlight*c), 0.0, 1.0);
+
+ f = cloudcover + cloudalpha*f*r;
+
+ result := mix(skycolour, clamp(skytint * skycolour + cloudcolour, 0.0, 1.0), clamp(f + c, 0.0, 1.0));
+
+ return vec4( result, 1.0 );
+}
+
diff --git a/shaders/vcr.kage b/shaders/vcr.kage
index fd555d8..45a543e 100644
--- a/shaders/vcr.kage
+++ b/shaders/vcr.kage
@@ -13,7 +13,7 @@ const noiseY = 100.0
const colorOffsetIntensity = 1.2
func rand(co vec2) float {
- return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
+ return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453)
}
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
@@ -21,7 +21,7 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
uv := srcPos / imageSrc0Size()
uv.x = uv.x + (rand(vec2(Time,srcPos.y)) - 0.5) / (noiseX);
- uv.y = uv.y + (rand(vec2(Time))-0.5) / (noiseY);
+ uv.y = uv.y + (rand(vec2(Time))-0.5) / (noiseY)
whiteNoise := rand(vec2(floor(uv.y*80.0),floor(uv.x*50.0))+vec2(Time,0))
off := 1.0 - mod(uv.y - NoiseOffset / 7, 1)
@@ -29,15 +29,15 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
if (whiteNoise > 11.5-30.0*(off)) || whiteNoise < 1.5-2.0*(off) {
// Sample the texture.
- offsetR := vec2(0.006 * sin(Time), 0.0) * colorOffsetIntensity;
- offsetG := vec2(0.0073 * (cos(Time * 0.97)), 0.0) * colorOffsetIntensity;
+ offsetR := vec2(0.006 * sin(Time), 0.0) * colorOffsetIntensity
+ offsetG := vec2(0.0073 * (cos(Time * 0.97)), 0.0) * colorOffsetIntensity
r := imageSrc0UnsafeAt((uv+offsetR) * imageSrc0Size()).r
g := imageSrc0UnsafeAt((uv+offsetG) * imageSrc0Size()).g
b := imageSrc0UnsafeAt(uv * imageSrc0Size()).b
return vec4(r, g, b, 1.0)
} else {
- col = imageSrc2UnsafeAt(uv * imageSrc0Size());
- return col + vec4(0.8);
+ col = imageSrc2UnsafeAt(uv * imageSrc0Size())
+ return col + vec4(0.8)
}
}