Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SceneKit water like in Badger example

Tags:

scenekit

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.

like image 989
Nils Avatar asked Jan 04 '23 14:01

Nils


1 Answers

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.

Badger

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);
like image 52
mnuages Avatar answered Feb 15 '23 14:02

mnuages