(
name: "StandardTerrainShader",
resources: [
(
name: "diffuseTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 0
),
(
name: "normalTexture",
kind: Texture(kind: Sampler2D, fallback: Normal),
binding: 1
),
(
name: "metallicTexture",
kind: Texture(kind: Sampler2D, fallback: Black),
binding: 2
),
(
name: "roughnessTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 3
),
(
name: "heightTexture",
kind: Texture(kind: Sampler2D, fallback: Black),
binding: 4
),
(
name: "emissionTexture",
kind: Texture(kind: Sampler2D, fallback: Black),
binding: 5
),
(
name: "lightmapTexture",
kind: Texture(kind: Sampler2D, fallback: Black),
binding: 6
),
(
name: "aoTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 7
),
(
name: "maskTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 8
),
(
name: "heightMapTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 9
),
(
name: "holeMaskTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 10
),
(
name: "properties",
kind: PropertyGroup([
(
name: "nodeUvOffsets",
kind: Vector4((0.0, 0.0, 0.0, 0.0)),
),
(
name: "texCoordScale",
kind: Vector2((1.0, 1.0)),
),
(
name: "layerIndex",
kind: UInt(0),
),
(
name: "emissionStrength",
kind: Vector3((2.0, 2.0, 2.0)),
),
(
name: "diffuseColor",
kind: Color(r: 255, g: 255, b: 255, a: 255),
),
(
name: "parallaxCenter",
kind: Float(0.0),
),
(
name: "parallaxScale",
kind: Float(0.08),
),
]),
binding: 0
),
(
name: "fyrox_instanceData",
kind: PropertyGroup([
// Autogenerated
]),
binding: 1
),
(
name: "fyrox_graphicsSettings",
kind: PropertyGroup([
// Autogenerated
]),
binding: 2
),
(
name: "fyrox_cameraData",
kind: PropertyGroup([
// Autogenerated
]),
binding: 3
),
(
name: "fyrox_lightData",
kind: PropertyGroup([
// Autogenerated
]),
binding: 4
),
],
passes: [
(
name: "GBuffer",
draw_parameters: DrawParameters(
cull_face: Some(Back),
color_write: ColorMask(
red: true,
green: true,
blue: true,
alpha: true,
),
depth_write: true,
stencil_test: None,
depth_test: Some(Less),
blend: Some(BlendParameters(
func: BlendFunc(
sfactor: SrcAlpha,
dfactor: OneMinusSrcAlpha,
alpha_sfactor: SrcAlpha,
alpha_dfactor: OneMinusSrcAlpha,
),
equation: BlendEquation(
rgb: Add,
alpha: Max
)
)),
stencil_op: StencilOp(
fail: Keep,
zfail: Keep,
zpass: Keep,
write_mask: 0xFFFF_FFFF,
),
scissor_box: None
),
vertex_shader:
r#"
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexTexCoord;
layout(location = 2) in vec3 vertexNormal;
layout(location = 3) in vec4 vertexTangent;
layout(location = 6) in vec2 vertexSecondTexCoord;
out vec3 position;
out vec3 normal;
out vec2 texCoord;
out vec3 tangent;
out vec3 binormal;
out vec2 secondTexCoord;
void main()
{
// Each node has tex coords in [0; 1] range, here we must scale and offset it
// to match the actual position.
vec2 actualTexCoords = vec2(vertexTexCoord * properties.nodeUvOffsets.zw + properties.nodeUvOffsets.xy);
vec2 heightSize = vec2(textureSize(heightMapTexture, 0));
vec2 innerSize = heightSize - 3.0;
vec2 pixelSize = 1.0 / heightSize;
vec2 heightCoords = (actualTexCoords * innerSize + 1.5) * pixelSize;
float height = texture(heightMapTexture, heightCoords).r;
vec4 finalVertexPosition = vec4(vertexPosition.x, height, vertexPosition.z, 1.0);
float hx0 = texture(heightMapTexture, heightCoords + vec2(-1.0, 0.0) * pixelSize).r;
float hx1 = texture(heightMapTexture, heightCoords + vec2(1.0, 0.0) * pixelSize).r;
float hy0 = texture(heightMapTexture, heightCoords + vec2(0.0, -1.0) * pixelSize).r;
float hy1 = texture(heightMapTexture, heightCoords + vec2(0.0, 1.0) * pixelSize).r;
vec3 n = vec3((hx0 - hx1) / 2.0, 1.0, (hy0 - hy1) / 2.0);
vec3 tan = vec3(n.y, -n.x, 0.0);
mat3 nm = mat3(fyrox_instanceData.worldMatrix);
normal = normalize(nm * n);
tangent = normalize(nm * tan);
binormal = normalize(-1.0 * cross(normal, tangent));
texCoord = actualTexCoords;
position = vec3(fyrox_instanceData.worldMatrix * finalVertexPosition);
secondTexCoord = vertexSecondTexCoord;
gl_Position = fyrox_instanceData.worldViewProjection * finalVertexPosition;
}
"#,
fragment_shader:
r#"
layout(location = 0) out vec4 outColor;
layout(location = 1) out vec4 outNormal;
layout(location = 2) out vec4 outAmbient;
layout(location = 3) out vec4 outMaterial;
layout(location = 4) out uint outDecalMask;
in vec3 position;
in vec3 normal;
in vec2 texCoord;
in vec3 tangent;
in vec3 binormal;
in vec2 secondTexCoord;
void main()
{
if (texture(holeMaskTexture, texCoord).r < 0.5) discard;
mat3 tangentSpace = mat3(tangent, binormal, normal);
vec3 toFragment = normalize(position - fyrox_cameraData.position);
vec2 tc;
if (fyrox_graphicsSettings.usePOM) {
vec3 toFragmentTangentSpace = normalize(transpose(tangentSpace) * toFragment);
tc = S_ComputeParallaxTextureCoordinates(
heightTexture,
toFragmentTangentSpace,
texCoord * properties.texCoordScale,
properties.parallaxCenter,
properties.parallaxScale
);
} else {
tc = texCoord * properties.texCoordScale;
}
outColor = properties.diffuseColor * texture(diffuseTexture, tc);
vec3 n = normalize(texture(normalTexture, tc).xyz * 2.0 - 1.0);
outNormal = vec4(normalize(tangentSpace * n) * 0.5 + 0.5, 1.0);
outMaterial.x = texture(metallicTexture, tc).r;
outMaterial.y = texture(roughnessTexture, tc).r;
outMaterial.z = texture(aoTexture, tc).r;
outMaterial.a = 1.0;
outAmbient.xyz = properties.emissionStrength * texture(emissionTexture, tc).rgb + texture(lightmapTexture, secondTexCoord).rgb;
outAmbient.a = 1.0;
outDecalMask = properties.layerIndex;
float mask = texture(maskTexture, texCoord).r;
outColor.a = mask;
outAmbient.a = mask;
outNormal.a = mask;
outMaterial.a = mask;
}
"#,
),
(
name: "Forward",
draw_parameters: DrawParameters(
cull_face: Some(Back),
color_write: ColorMask(
red: true,
green: true,
blue: true,
alpha: true,
),
depth_write: true,
stencil_test: None,
depth_test: Some(Less),
blend: Some(BlendParameters(
func: BlendFunc(
sfactor: SrcAlpha,
dfactor: OneMinusSrcAlpha,
alpha_sfactor: SrcAlpha,
alpha_dfactor: OneMinusSrcAlpha,
),
equation: BlendEquation(
rgb: Add,
alpha: Max
)
)),
stencil_op: StencilOp(
fail: Keep,
zfail: Keep,
zpass: Keep,
write_mask: 0xFFFF_FFFF,
),
scissor_box: None
),
vertex_shader:
r#"
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexTexCoord;
out vec3 position;
out vec2 texCoord;
void main()
{
vec2 actualTexCoords = vec2(vertexTexCoord * properties.nodeUvOffsets.zw + properties.nodeUvOffsets.xy);
vec2 heightSize = vec2(textureSize(heightMapTexture, 0));
vec2 innerSize = heightSize - 3.0;
vec2 pixelSize = 1.0 / heightSize;
vec2 heightCoords = (actualTexCoords * innerSize + 1.5) * pixelSize;
float height = texture(heightMapTexture, heightCoords).r;
vec4 finalVertexPosition = vec4(vertexPosition.x, height, vertexPosition.z, 1.0);
gl_Position = fyrox_instanceData.worldViewProjection * finalVertexPosition;
texCoord = actualTexCoords;
}
"#,
fragment_shader:
r#"
uniform vec4 diffuseColor;
out vec4 FragColor;
in vec2 texCoord;
void main()
{
if (texture(holeMaskTexture, texCoord).r < 0.5) discard;
FragColor = properties.diffuseColor * texture(diffuseTexture, texCoord);
}
"#,
),
(
name: "SpotShadow",
draw_parameters: DrawParameters (
cull_face: Some(Back),
color_write: ColorMask(
red: false,
green: false,
blue: false,
alpha: false,
),
depth_write: true,
stencil_test: None,
depth_test: Some(Less),
blend: None,
stencil_op: StencilOp(
fail: Keep,
zfail: Keep,
zpass: Keep,
write_mask: 0xFFFF_FFFF,
),
scissor_box: None
),
vertex_shader:
r#"
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexTexCoord;
out vec2 texCoord;
void main()
{
vec2 actualTexCoords = vec2(vertexTexCoord * properties.nodeUvOffsets.zw + properties.nodeUvOffsets.xy);
vec2 heightSize = vec2(textureSize(heightMapTexture, 0));
vec2 innerSize = heightSize - 3.0;
vec2 pixelSize = 1.0 / heightSize;
vec2 heightCoords = (actualTexCoords * innerSize + 1.5) * pixelSize;
float height = texture(heightMapTexture, heightCoords).r;
vec4 finalVertexPosition = vec4(vertexPosition.x, height, vertexPosition.z, 1.0);
gl_Position = fyrox_instanceData.worldViewProjection * finalVertexPosition;
texCoord = actualTexCoords;
}
"#,
fragment_shader:
r#"
in vec2 texCoord;
void main()
{
if (texture(holeMaskTexture, texCoord).r < 0.5) discard;
if (texture(diffuseTexture, texCoord).a < 0.2) discard;
}
"#,
),
(
name: "DirectionalShadow",
draw_parameters: DrawParameters (
cull_face: Some(Back),
color_write: ColorMask(
red: false,
green: false,
blue: false,
alpha: false,
),
depth_write: true,
stencil_test: None,
depth_test: Some(Less),
blend: None,
stencil_op: StencilOp(
fail: Keep,
zfail: Keep,
zpass: Keep,
write_mask: 0xFFFF_FFFF,
),
scissor_box: None
),
vertex_shader:
r#"
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexTexCoord;
out vec2 texCoord;
void main()
{
vec2 actualTexCoords = vec2(vertexTexCoord * properties.nodeUvOffsets.zw + properties.nodeUvOffsets.xy);
vec2 heightSize = vec2(textureSize(heightMapTexture, 0));
vec2 innerSize = heightSize - 3.0;
vec2 pixelSize = 1.0 / heightSize;
vec2 heightCoords = (actualTexCoords * innerSize + 1.5) * pixelSize;
float height = texture(heightMapTexture, heightCoords).r;
vec4 finalVertexPosition = vec4(vertexPosition.x, height, vertexPosition.z, 1.0);
gl_Position = fyrox_instanceData.worldViewProjection * finalVertexPosition;
texCoord = actualTexCoords;
}
"#,
fragment_shader:
r#"
in vec2 texCoord;
void main()
{
if (texture(holeMaskTexture, texCoord).r < 0.5) discard;
if (texture(diffuseTexture, texCoord).a < 0.2) discard;
}
"#,
),
(
name: "PointShadow",
draw_parameters: DrawParameters (
cull_face: Some(Back),
color_write: ColorMask(
red: true,
green: true,
blue: true,
alpha: true,
),
depth_write: true,
stencil_test: None,
depth_test: Some(Less),
blend: None,
stencil_op: StencilOp(
fail: Keep,
zfail: Keep,
zpass: Keep,
write_mask: 0xFFFF_FFFF,
),
scissor_box: None
),
vertex_shader:
r#"
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexTexCoord;
out vec2 texCoord;
out vec3 worldPosition;
void main()
{
vec2 actualTexCoords = vec2(vertexTexCoord * properties.nodeUvOffsets.zw + properties.nodeUvOffsets.xy);
vec2 heightSize = vec2(textureSize(heightMapTexture, 0));
vec2 innerSize = heightSize - 3.0;
vec2 pixelSize = 1.0 / heightSize;
vec2 heightCoords = (actualTexCoords * innerSize + 1.5) * pixelSize;
float height = texture(heightMapTexture, heightCoords).r;
vec4 finalVertexPosition = vec4(vertexPosition.x, height, vertexPosition.z, 1.0);
gl_Position = fyrox_instanceData.worldViewProjection * finalVertexPosition;
worldPosition = (fyrox_instanceData.worldMatrix * finalVertexPosition).xyz;
texCoord = actualTexCoords;
}
"#,
fragment_shader:
r#"
in vec2 texCoord;
in vec3 worldPosition;
layout(location = 0) out float depth;
void main()
{
if (texture(holeMaskTexture, texCoord).r < 0.5) discard;
if (texture(diffuseTexture, texCoord).a < 0.2) discard;
depth = length(fyrox_lightData.lightPosition - worldPosition);
}
"#,
)
],
)