Alright. Here's some code:
package main
import (
sf "bitbucket.org/krepa098/gosfml2"
"fmt"
)
const size = 500
func main() {
fmt.Println("Hello World")
wnd := sf.NewRenderWindow(sf.VideoMode{size, size, 32}, "Water", sf.Style_DefaultStyle, nil)
wnd.SetFramerateLimit(60)
firstBuffer := sf.NewRenderTexture(size, size, false)
secondBuffer := sf.NewRenderTexture(size, size, false)
finalBuffer := sf.NewRenderTexture(size, size, false)
//load shaders
waterShaderRaw, _ := sf.NewShaderFromFile("", "water_raw.glsl")
waterShaderRaw.SetFloatParameter("textureSize", size, size)
waterShaderHeightfield, _ := sf.NewShaderFromFile("", "water_heightfield.glsl")
secondSprite := sf.NewSprite(secondBuffer.GetTexture())
finalSprite := sf.NewSprite(finalBuffer.GetTexture())
//debug output
firstSpriteDbg := sf.NewSprite(firstBuffer.GetTexture())
firstSpriteDbg.SetScale(sf.Vector2f{0.25, 0.25})
//render states
rsRaw := sf.MakeRenderStates(sf.Blend_None, sf.TransformIdentity(), nil, waterShaderRaw)
rsHeightfield := sf.MakeRenderStates(sf.Blend_None, sf.TransformIdentity(), nil, waterShaderHeightfield)
for wnd.IsOpen() {
for ev := wnd.PollEvent(); ev != nil; ev = wnd.PollEvent() {
switch ev.(type) {
case sf.EventClosed:
wnd.Close()
}
}
//mouse input
waterShaderRaw.SetFloatParameter("mousePosition", -1, -1)
if sf.IsMouseButtonPressed(sf.MouseLeft) {
mousePos := sf.MouseGetPosition(wnd)
if mousePos.X < size && mousePos.Y < size {
mx := float32(mousePos.X) / size
my := 1.0 - float32(mousePos.Y)/size
waterShaderRaw.SetFloatParameter("mousePosition", mx, my)
}
}
waterShaderRaw.SetTextureParameter("textureTwoFramesAgo", firstBuffer.GetTexture())
waterShaderRaw.SetTextureParameter("textureOneFrameAgo", secondBuffer.GetTexture())
secondBuffer.Display()
finalBuffer.Clear(sf.ColorBlack())
finalBuffer.Draw(secondSprite, &rsRaw)
finalBuffer.Display()
secondSprite.SetTexture(secondBuffer.GetTexture(), false)
finalSprite.SetTexture(finalBuffer.GetTexture(), false)
wnd.Clear(sf.ColorBlack())
wnd.Draw(finalSprite, &rsHeightfield)
wnd.Draw(firstSpriteDbg, nil) // raw output
wnd.Display()
//swap buffers
firstBuffer, secondBuffer, finalBuffer = secondBuffer, finalBuffer, firstBuffer
}
}
Yeah it's written in Go. I'm sorry.
I didn't change much. Your rendering code is correct.
water_raw.glsl:
uniform sampler2D textureTwoFramesAgo;
uniform sampler2D textureOneFrameAgo;
uniform vec2 mousePosition;
uniform vec2 textureSize;
const float damping = 0.999;
void main()
{
// pixels position
vec2 position = gl_TexCoord[0].xy;
vec4 smoothed = (texture2D(textureOneFrameAgo, vec2(position.x - 1.0/textureSize.x, position.y)) +
texture2D(textureOneFrameAgo, vec2(position.x + 1.0/textureSize.x, position.y)) +
texture2D(textureOneFrameAgo, vec2(position.x, position.y + 1.0/textureSize.y)) +
texture2D(textureOneFrameAgo, vec2(position.x, position.y - 1.0/textureSize.y))) / 4.0;
float velocity = texture2D(textureTwoFramesAgo, position).g - texture2D(textureTwoFramesAgo, position).r; // <-- @FRex
smoothed.r = smoothed.r*2.0 + velocity;
smoothed.g = -smoothed.r;
smoothed.g *= damping;
smoothed.r *= damping;
// add new ripples
if(mousePosition.x > 0.0)
if(distance(position, mousePosition) < 1.0/textureSize.x * 5.0)
smoothed.r = 0.9;
gl_FragColor = vec4(smoothed.r, smoothed.g, 0.0, 1.0);
}
water_heightfield.glsl:
uniform sampler2D inputTex;
const vec4 baseColorL = vec4(0.0,0.0,0.0,1.0);
const vec4 baseColorH = vec4(1.0,1.0,1.0,1.0);
void main()
{
vec4 color = mix(baseColorL,baseColorH,(texture2D(inputTex,(gl_TexCoord[0].xy)).r+1.0)/2.0);
gl_FragColor = color;
}
This should generate a nice heightfield.
@FRex
Have a look at line 19. Your waves disappear because you're actually losing the negative part (correct me if I'm wrong) of the waves intensity which I store in the green channel.
@Foaly
Yes the output in red is the raw output. Though you can still apply whatever transformations you like.