78 lines
2.4 KiB
Plaintext
78 lines
2.4 KiB
Plaintext
// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Wind.gdshaderinc"
|
|
|
|
|
|
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc"
|
|
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc"
|
|
|
|
|
|
/*
|
|
uniform sampler2D terrainHeightMap;
|
|
uniform vec2 terrainCenterXZ = vec2( 0.0, 0.0 );
|
|
uniform vec2 terrainSizeXZ = vec2( 100.0, 100.0 );
|
|
uniform float terrainMinHeight = 0.0;
|
|
uniform float terrainMaxHeight = 100.0;
|
|
|
|
uniform sampler2D terrainNormalMap;
|
|
*/
|
|
|
|
void addTerrainOffset(
|
|
mat4 _MODEL_MATRIX,
|
|
inout vec3 _VERTEX,
|
|
|
|
sampler2D terrainHeightMap,
|
|
vec2 terrainCenterXZ,
|
|
vec2 terrainSizeXZ,
|
|
float terrainMinHeight,
|
|
float terrainMaxHeight
|
|
|
|
)
|
|
{
|
|
vec3 worldVertex = localToWorld( _VERTEX, _MODEL_MATRIX );
|
|
|
|
vec2 mapOffset = terrainCenterXZ - terrainSizeXZ/2.0;
|
|
|
|
vec2 uv = ( worldVertex.xz - mapOffset ) / terrainSizeXZ;
|
|
|
|
float height = mix( terrainMinHeight, terrainMaxHeight, texture( terrainHeightMap, uv ).r );
|
|
|
|
worldVertex.y += height;
|
|
|
|
_VERTEX = worldToLocal( worldVertex, _MODEL_MATRIX );
|
|
|
|
}
|
|
|
|
/** The world-space normal HeightMapGenerator baked into terrainNormalMap.
|
|
|
|
Stored encoded, n * 0.5 + 0.5, so the map also works in an 8-bit format - see
|
|
Procedural/HeightMaps/Shaders/HeightMapNormals.gdshader. World space, not
|
|
tangent space: a heightfield over world XZ has no tangent frame to be
|
|
relative to.
|
|
|
|
This replaces taking a central difference per fragment. Besides being
|
|
cheaper, it is the only way the smoothing can exist at all - a consumer
|
|
sampling its own two neighbours has nothing to widen the stencil with, and a
|
|
clipmap's triangles are far coarser than the map, so a vertex normal is not
|
|
an option either.
|
|
*/
|
|
vec3 getTerrainNormal(
|
|
sampler2D terrainNormalMap,
|
|
vec3 worldPosition,
|
|
vec2 terrainCenterXZ,
|
|
vec2 terrainSizeXZ
|
|
)
|
|
{
|
|
// An unassigned sampler is Godot's 1x1 default and reads black, and
|
|
// normalize( black * 2 - 1 ) is a diagonal rather than up - so a material
|
|
// whose generator has no normalMapTarget would get wrong lighting instead of
|
|
// flat lighting. A real normal map is never 1x1, so the size is a safe test.
|
|
if ( textureSize( terrainNormalMap, 0 ).x <= 1 )
|
|
{
|
|
return vec3( 0.0, 1.0, 0.0 );
|
|
}
|
|
|
|
vec2 mapOffset = terrainCenterXZ - terrainSizeXZ/2.0;
|
|
|
|
vec2 uv = ( worldPosition.xz - mapOffset ) / terrainSizeXZ;
|
|
|
|
return normalize( texture( terrainNormalMap, uv ).rgb * 2.0 - 1.0 );
|
|
} |