185 lines
4.5 KiB
Go
185 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/go-gl/mathgl/mgl32"
|
|
|
|
"github.com/faiface/pixel"
|
|
"github.com/faiface/pixel/pixelgl"
|
|
"golang.org/x/image/colornames"
|
|
)
|
|
|
|
func run() {
|
|
// Set up window configs
|
|
cfg := pixelgl.WindowConfig{ // Default: 1024 x 768
|
|
Title: "Golang Seascape from Shadertoy",
|
|
Bounds: pixel.R(0, 0, 1024, 768),
|
|
VSync: true,
|
|
}
|
|
|
|
win, err := pixelgl.NewWindow(cfg)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
camVector := win.Bounds().Center()
|
|
|
|
bounds := win.Bounds()
|
|
bounds.Max = bounds.Max.ScaledXY(pixel.V(1.0, 1.0))
|
|
|
|
// I am putting all shader example initializing stuff here for
|
|
// easier reference to those learning to use this functionality
|
|
fragSource, err := LoadFileToString("shaders/seascape.glsl")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var uMouse mgl32.Vec4
|
|
var uTime float32
|
|
|
|
canvas := win.Canvas()
|
|
uResolution := mgl32.Vec2{float32(win.Bounds().W()), float32(win.Bounds().H())}
|
|
|
|
EasyBindUniforms(canvas,
|
|
"u_resolution", &uResolution,
|
|
"u_time", &uTime,
|
|
"u_mouse", &uMouse,
|
|
)
|
|
|
|
canvas.SetFragmentShader(fragSource)
|
|
|
|
start := time.Now()
|
|
|
|
// Game Loop
|
|
for !win.Closed() {
|
|
uTime = float32(time.Since(start).Seconds())
|
|
mpos := win.MousePosition()
|
|
uMouse[0] = float32(mpos.X)
|
|
uMouse[1] = float32(mpos.Y)
|
|
|
|
win.Clear(colornames.Black)
|
|
|
|
// Drawing to the screen
|
|
canvas.Draw(win, pixel.IM.Moved(camVector))
|
|
|
|
win.Update()
|
|
}
|
|
|
|
}
|
|
|
|
func main() {
|
|
pixelgl.Run(run)
|
|
}
|
|
|
|
var cloudsFragmentShader = `
|
|
#version 330 core
|
|
|
|
#ifdef GL_ES
|
|
precision highp float;
|
|
#endif
|
|
|
|
#define HOW_CLOUDY 0.2
|
|
#define SHADOW_THRESHOLD 0.4
|
|
#define SHADOW 0.3
|
|
#define SUBSURFACE 1.0
|
|
#define WIND_DIRECTION 0.3
|
|
#define TIME_SCALE 0.6
|
|
#define SCALE 0.1
|
|
//#define ENABLE_SHAFTS
|
|
in vec2 texcoords;
|
|
out vec4 fragColor;
|
|
mat2 RM = mat2(cos(WIND_DIRECTION), -sin(WIND_DIRECTION), sin(WIND_DIRECTION), cos(WIND_DIRECTION));
|
|
uniform float u_time;
|
|
uniform vec2 u_mouse;
|
|
//uniform vec2 u_resolution;
|
|
uniform vec4 u_texbounds;
|
|
uniform sampler2D u_texture;
|
|
uniform vec2 u_gopherpos;
|
|
|
|
float hash( float n )
|
|
{
|
|
return fract(sin(n)*758.5453);
|
|
}
|
|
|
|
float noise( in vec3 x )
|
|
{
|
|
vec3 p = floor(x);
|
|
vec3 f = fract(x);
|
|
float n = p.x + p.y*57.0 + p.z*800.0;
|
|
float res = mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
|
|
mix(mix( hash(n+800.0), hash(n+801.0),f.x), mix( hash(n+857.0), hash(n+858.0),f.x),f.y),f.z);
|
|
return res;
|
|
}
|
|
|
|
float fbm( vec3 p )
|
|
{
|
|
float f = 0.0;
|
|
f += 0.50000*noise( p ); p = p*2.02;
|
|
f -= 0.25000*noise( p ); p = p*2.03;
|
|
f += 0.12500*noise( p ); p = p*3.01;
|
|
f += 0.06250*noise( p ); p = p*3.04;
|
|
f += 0.03500*noise( p ); p = p*4.01;
|
|
f += 0.01250*noise( p ); p = p*4.04;
|
|
f -= 0.00125*noise( p );
|
|
return f/0.784375;
|
|
}
|
|
|
|
float cloud(vec3 p)
|
|
{
|
|
p-=fbm(vec3(p.x,p.y,0.0)*0.5)*1.25;
|
|
float a = min((fbm(p*3.0)*2.2-1.1), 0.0);
|
|
return a*a;
|
|
}
|
|
|
|
float shadow = 1.0;
|
|
|
|
|
|
float clouds(vec2 p){
|
|
float ic = cloud(vec3(p * 2.0, u_time*0.01 * TIME_SCALE)) / HOW_CLOUDY;
|
|
float init = smoothstep(0.1, 1.0, ic) * 5.0;
|
|
shadow = smoothstep(0.0, SHADOW_THRESHOLD, ic) * SHADOW + (1.0 - SHADOW);
|
|
init = (init * cloud(vec3(p * (6.0), u_time*0.01 * TIME_SCALE)) * ic);
|
|
init = (init * (cloud(vec3(p * (11.0), u_time*0.01 * TIME_SCALE))*0.5 + 0.4) * init);
|
|
return min(1.0, init);
|
|
}
|
|
//uniform sampler2D bb;
|
|
float cloudslowres(vec2 p){
|
|
return 1.0 - (texture(u_texture, p).a - 0.9) * 10.0;
|
|
}
|
|
|
|
vec2 ratio = vec2(1.0, 1.0);
|
|
|
|
vec4 getresult(){
|
|
vec2 uvmouse = (u_mouse/(texcoords - u_texbounds.xy));
|
|
vec2 t = (texcoords - u_texbounds.xy) / u_texbounds.zw;
|
|
//vec2 surfacePosition = ((( t ) * vec2(u_gopherpos.x , u_gopherpos.y)) * 2.0 - 1.0)*SCALE;
|
|
vec2 surfacePosition = t+u_gopherpos*10.0;
|
|
vec2 position = ( surfacePosition * SCALE);
|
|
vec2 sun = (uvmouse.xy * vec2(texcoords.x / texcoords.y, 1.0)*2.0-1.0) * SCALE;
|
|
|
|
float dst = distance(sun * ratio, position * ratio);
|
|
float suni = pow(dst + 1.0, -10.0);
|
|
float shaft =0.0;
|
|
float st = 0.05;
|
|
float w = 1.0;
|
|
vec2 dir = sun - position;
|
|
float c = clouds(position);
|
|
#ifdef ENABLE_SHAFTS
|
|
for(int i=0;i<50;i++){
|
|
float occl = cloudslowres(clamp((t) + dir * st, 0.0, 1.0));
|
|
w *= 0.99;
|
|
st *= 1.05;
|
|
shaft += max(0.0, (1.0 - occl)) * w;
|
|
}
|
|
#endif
|
|
shadow = min(1.0, shadow + suni * suni * 0.2 * SUBSURFACE);
|
|
suni *= (shaft * 0.03);
|
|
return vec4(pow(mix(vec3(shadow), pow(vec3(0.23, 0.33, 0.48), vec3(2.2)) + suni, c), vec3(1.0/2.2)), c*0.1 + 0.9);
|
|
}
|
|
|
|
void main( void ) {
|
|
fragColor = getresult().rgba;
|
|
}
|
|
`
|