I’m very interested on making rivers, lakes and such so I’m just experimenting with shaders and filters. What I really learned is that this subjects are enourmous beasts xD. Well, however I could tweak the default waterfilter to support rectangles too (so it supports now circles, squares and rectangles). I could find that @Ben1 made it to work with any polygon but it’s not the easiest nor the better way for regular shapes.
Ok, here is the code (just as easy as adding another parameter to the shader xD):
First of all we modify the filter:
WaterFilter.java
We’ll use the radius as the height (x-axis) and we’ll add a new variable: the width (z-axis):
@Override
protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
....
if (center != null) {
material.setVector3("Center", center);
material.setFloat("Radius", radius * radius);
material.setFloat("Width", width * width);
material.setBoolean("SquareArea", shapeType==AreaShape.Square);
material.setBoolean("RectangleArea", shapeType==AreaShape.Rectangle);
}
....
}
/**
* Set the width of the effect.
* By default the water will extent to the entire scene.
* By setting a center, a radius (x-axis in this case) and a width (z-axis) you can restrain it to a rectangular portion of the scene.
* @param width the width (z-axis) of the effect
*/
public void setWidth(float width) {
this.width = width;
if (material != null) {
material.setFloat("Width", width * width);
}
}
....
....
/**
* Set the shape of the water area (Circular (default), Square or Rectangular).
* if the shape is square or rectangular the radius is considered as an extent.
* If rectangular the radius is considered the x-axis dimension and the width the z-axis dimension.
* @param shapeType the shape type
*/
public void setShapeType(AreaShape shapeType) {
this.shapeType = shapeType;
if (material != null) {
material.setBoolean("SquareArea", shapeType==AreaShape.Square);
material.setBoolean("RectangleArea", shapeType==AreaShape.Rectangle);
}
}
Now is the time of the material definition:
Water.j3md:
Add the material width parameter (for the height we are using the already set radius):
MaterialParameters {
....
Float Radius
Float Width
Vector3 Center
....
}
Modify the defines for both techniques to add the “RECTANGLE_AREA”:
Defines {
...
SQUARE_AREA : SquareArea
RECTANGLE_AREA : RectangleArea
...
}
WaterUtil.glsl:
#ifdef ENABLE_AREA
#ifdef RECTANGLE_AREA
bool isOverExtent(vec3 position,vec3 center,float height,float width){
vec2 dist = position.xz-center.xz;
return dist.x*dist.x >height || dist.y*dist.y >width;
}
#else
bool isOverExtent(vec3 position,vec3 center,float radius){
vec2 dist = position.xz-center.xz;
#ifdef SQUARE_AREA
return dist.x*dist.x >radius || dist.y*dist.y >radius;
#else
return dot(dist,dist)>radius;
#endif
}
#endif
#endif
WaterX.frag:
First add the width uniform:
#ifdef ENABLE_AREA
uniform vec3 m_Center;
uniform float m_Radius;
#ifdef RECTANGLE_AREA
uniform float m_Width;
#endif
#endif
Wherever there was:
#ifdef ENABLE_AREA
if(isOverExtent(...)){
.....
}
#endif
just replace with:
#ifdef ENABLE_AREA
#ifdef RECTANGLE_AREA
if(isOverExtent(..., m_Width)){
.....
}
#else
if(isOverExtent(...)){
.....
}
#endif
#endif
As you can see is just as efficient as the square and circular but helpful for rivers when no having strong “lateral limitations”.