Does enybody know how to create water material like in badger example from Apple?
There is a "geotherm_01" object in "scene.scn" and this object got materials "_1_terrasses_orange_water" and "_1_terrasses_eau" which creates water with slow animation that looks realistic.
I've tried to repeat same materials in my testing project but can't get the same result.
This water effect was achieved using shader modifiers as shown in the SceneKit Scene Editor within Xcode. The most important material property is the normal map that will be used to affect lighting in order to simulate wavelets on a perfectly flat geometry.
More specifically the modifier for the .surface
entry point is
float waterSpeed = u_time * -0.1;vec2 uvs = _surface.normalTexcoord;uvs.x *= 2;vec3 tn = texture2D(u_normalTexture, vec2(uvs.x, uvs.y + waterSpeed)).xyz;tn = tn * 2 - 1;vec3 tn2 = texture2D(u_normalTexture, vec2(uvs.x + 0.35 , uvs.y + 0.35 + (waterSpeed * 1.3))).xyz;tn2 = tn2 * 2 - 1;vec3 rn = (tn + tn2) * 0.5;mat3 ts = mat3(_surface.tangent, _surface.bitangent, _surface.geometryNormal);_surface.normal = normalize(ts * rn);
Here's a commented version of the code:
// Elapsed time in seconds
float waterSpeed = u_time * -0.1;
// Texture coordinates that will be used to sample the normal map
vec2 uvs = _surface.normalTexcoord;
uvs.x *= 2;
// Sample the normal map
vec3 tn = texture2D(u_normalTexture, vec2(uvs.x, uvs.y + waterSpeed)).xyz;
// The texture stores values in the [0, 1] range
// Express the coordinates of the normal vector in the [-1, +1] range
tn = tn * 2 - 1;
// Sample the normal map again, using the `waterSpeed` offset this time
// in order to produce the animation effect
vec3 tn2 = texture2D(u_normalTexture, vec2(uvs.x + 0.35 , uvs.y + 0.35 + (waterSpeed * 1.3))).xyz;
tn2 = tn2 * 2 - 1;
// Combine the two normals (static and animated) to produce a richer (more complex and less uniform) effect
vec3 rn = (tn + tn2) * 0.5;
// Normals in the normal map are expressed in tangent space
// Convert them to object space and override the surface normal to simulate wavelets
mat3 ts = mat3(_surface.tangent, _surface.bitangent, _surface.geometryNormal);
_surface.normal = normalize(ts * rn);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With