(
name: "GLTFShader",
resources: [
(
name: "diffuseTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 0
),
(
name: "normalTexture",
kind: Texture(kind: Sampler2D, fallback: Normal),
binding: 1
),
(
name: "metallicRoughnessTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 2
),
(
name: "heightTexture",
kind: Texture(kind: Sampler2D, fallback: Black),
binding: 3
),
(
name: "emissionTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 4
),
(
name: "lightmapTexture",
kind: Texture(kind: Sampler2D, fallback: Black),
binding: 5
),
(
name: "aoTexture",
kind: Texture(kind: Sampler2D, fallback: White),
binding: 6
),
(
name: "blendShapesStorage",
kind: Texture(kind: Sampler3D, fallback: Volume),
binding: 7
),
(
name: "properties",
kind: PropertyGroup([
(
name: "texCoordScale",
kind: Vector2(value: (1.0, 1.0)),
),
(
name: "layerIndex",
kind: UInt(value: 0),
),
(
name: "emissionStrength",
kind: Vector3(value: (2.0, 2.0, 2.0)),
),
(
name: "diffuseColor",
kind: Color(r: 255, g: 255, b: 255, a: 255),
),
(
name: "parallaxCenter",
kind: Float(value: 0.0),
),
(
name: "parallaxScale",
kind: Float(value: 0.08),
),
(
name: "metallicFactor",
kind: Float(value: 1.0)
),
(
name: "roughnessFactor",
kind: Float(value: 1.0)
)
]),
binding: 0
),
(
name: "fyrox_instanceData",
kind: PropertyGroup([
// Autogenerated
]),
binding: 1
),
(
name: "fyrox_boneMatrices",
kind: PropertyGroup([
// Autogenerated
]),
binding: 2
),
(
name: "fyrox_graphicsSettings",
kind: PropertyGroup([
// Autogenerated
]),
binding: 3
),
(
name: "fyrox_cameraData",
kind: PropertyGroup([
// Autogenerated
]),
binding: 4
),
(
name: "fyrox_lightData",
kind: PropertyGroup([
// Autogenerated
]),
binding: 5
),
],
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: 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;
layout(location = 2) in vec3 vertexNormal;
layout(location = 3) in vec4 vertexTangent;
layout(location = 4) in vec4 boneWeights;
layout(location = 5) in vec4 boneIndices;
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()
{
vec4 localPosition = vec4(0);
vec3 localNormal = vec3(0);
vec3 localTangent = vec3(0);
vec4 inputPosition = vec4(vertexPosition, 1.0);
vec3 inputNormal = vertexNormal;
vec3 inputTangent = vertexTangent.xyz;
for (int i = 0; i < fyrox_instanceData.blendShapesCount; ++i) {
TBlendShapeOffsets offsets = S_FetchBlendShapeOffsets(blendShapesStorage, gl_VertexID, i);
float weight = fyrox_instanceData.blendShapesWeights[i / 4][i % 4];
inputPosition.xyz += offsets.position * weight;
inputNormal += offsets.normal * weight;
inputTangent += offsets.tangent * weight;
}
if (fyrox_instanceData.useSkeletalAnimation)
{
int i0 = int(boneIndices.x);
int i1 = int(boneIndices.y);
int i2 = int(boneIndices.z);
int i3 = int(boneIndices.w);
mat4 m0 = fyrox_boneMatrices.matrices[i0];
mat4 m1 = fyrox_boneMatrices.matrices[i1];
mat4 m2 = fyrox_boneMatrices.matrices[i2];
mat4 m3 = fyrox_boneMatrices.matrices[i3];
localPosition += m0 * inputPosition * boneWeights.x;
localPosition += m1 * inputPosition * boneWeights.y;
localPosition += m2 * inputPosition * boneWeights.z;
localPosition += m3 * inputPosition * boneWeights.w;
localNormal += mat3(m0) * inputNormal * boneWeights.x;
localNormal += mat3(m1) * inputNormal * boneWeights.y;
localNormal += mat3(m2) * inputNormal * boneWeights.z;
localNormal += mat3(m3) * inputNormal * boneWeights.w;
localTangent += mat3(m0) * inputTangent * boneWeights.x;
localTangent += mat3(m1) * inputTangent * boneWeights.y;
localTangent += mat3(m2) * inputTangent * boneWeights.z;
localTangent += mat3(m3) * inputTangent * boneWeights.w;
}
else
{
localPosition = inputPosition;
localNormal = inputNormal;
localTangent = inputTangent;
}
mat3 nm = mat3(fyrox_instanceData.worldMatrix);
normal = normalize(nm * localNormal);
tangent = normalize(nm * localTangent);
binormal = normalize(vertexTangent.w * cross(normal, tangent));
texCoord = vertexTexCoord;
position = vec3(fyrox_instanceData.worldMatrix * localPosition);
secondTexCoord = vertexSecondTexCoord;
gl_Position = fyrox_instanceData.worldViewProjection * localPosition;
}
"#,
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()
{
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);
// Alpha test.
if (outColor.a < 0.5) {
discard;
}
outColor.a = 1.0;
vec4 n = normalize(texture(normalTexture, tc) * 2.0 - 1.0);
outNormal = vec4(normalize(tangentSpace * n.xyz) * 0.5 + 0.5, 1.0);
outMaterial.x = properties.metallicFactor * texture(metallicRoughnessTexture, tc).b; // Metallic
outMaterial.y = properties.roughnessFactor * texture(metallicRoughnessTexture, tc).g; // Roughness
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;
}
"#,
),
(
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: Add
)
)),
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 = 4) in vec4 boneWeights;
layout(location = 5) in vec4 boneIndices;
out vec3 position;
out vec2 texCoord;
void main()
{
vec4 localPosition = vec4(0);
vec4 inputPosition = vec4(vertexPosition, 1.0);
for (int i = 0; i < fyrox_instanceData.blendShapesCount; ++i) {
TBlendShapeOffsets offsets = S_FetchBlendShapeOffsets(blendShapesStorage, gl_VertexID, i);
float weight = fyrox_instanceData.blendShapesWeights[i / 4][i % 4];
inputPosition.xyz += offsets.position * weight;
}
if (fyrox_instanceData.useSkeletalAnimation)
{
int i0 = int(boneIndices.x);
int i1 = int(boneIndices.y);
int i2 = int(boneIndices.z);
int i3 = int(boneIndices.w);
mat4 m0 = fyrox_boneMatrices.matrices[i0];
mat4 m1 = fyrox_boneMatrices.matrices[i1];
mat4 m2 = fyrox_boneMatrices.matrices[i2];
mat4 m3 = fyrox_boneMatrices.matrices[i3];
localPosition += m0 * inputPosition * boneWeights.x;
localPosition += m1 * inputPosition * boneWeights.y;
localPosition += m2 * inputPosition * boneWeights.z;
localPosition += m3 * inputPosition * boneWeights.w;
}
else
{
localPosition = inputPosition;
}
gl_Position = fyrox_instanceData.worldViewProjection * localPosition;
texCoord = vertexTexCoord;
}
"#,
fragment_shader:
r#"
out vec4 FragColor;
in vec2 texCoord;
void main()
{
FragColor = properties.diffuseColor * texture(diffuseTexture, texCoord);
}
"#,
),
(
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;
layout(location = 4) in vec4 boneWeights;
layout(location = 5) in vec4 boneIndices;
out vec2 texCoord;
void main()
{
vec4 localPosition = vec4(0);
vec4 inputPosition = vec4(vertexPosition, 1.0);
for (int i = 0; i < fyrox_instanceData.blendShapesCount; ++i) {
TBlendShapeOffsets offsets = S_FetchBlendShapeOffsets(blendShapesStorage, gl_VertexID, i);
float weight = fyrox_instanceData.blendShapesWeights[i / 4][i % 4];
inputPosition.xyz += offsets.position * weight;
}
if (fyrox_instanceData.useSkeletalAnimation)
{
vec4 vertex = vec4(vertexPosition, 1.0);
mat4 m0 = fyrox_boneMatrices.matrices[int(boneIndices.x)];
mat4 m1 = fyrox_boneMatrices.matrices[int(boneIndices.y)];
mat4 m2 = fyrox_boneMatrices.matrices[int(boneIndices.z)];
mat4 m3 = fyrox_boneMatrices.matrices[int(boneIndices.w)];
localPosition += m0 * inputPosition * boneWeights.x;
localPosition += m1 * inputPosition * boneWeights.y;
localPosition += m2 * inputPosition * boneWeights.z;
localPosition += m3 * inputPosition * boneWeights.w;
}
else
{
localPosition = inputPosition;
}
gl_Position = fyrox_instanceData.worldViewProjection * localPosition;
texCoord = vertexTexCoord;
}
"#,
fragment_shader:
r#"
in vec2 texCoord;
void main()
{
if (texture(diffuseTexture, texCoord).a < 0.2) discard;
}
"#,
),
(
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;
layout(location = 4) in vec4 boneWeights;
layout(location = 5) in vec4 boneIndices;
out vec2 texCoord;
void main()
{
vec4 localPosition = vec4(0);
vec4 inputPosition = vec4(vertexPosition, 1.0);
for (int i = 0; i < fyrox_instanceData.blendShapesCount; ++i) {
TBlendShapeOffsets offsets = S_FetchBlendShapeOffsets(blendShapesStorage, gl_VertexID, i);
float weight = fyrox_instanceData.blendShapesWeights[i / 4][i % 4];
inputPosition.xyz += offsets.position * weight;
}
if (fyrox_instanceData.useSkeletalAnimation)
{
vec4 vertex = vec4(vertexPosition, 1.0);
mat4 m0 = fyrox_boneMatrices.matrices[int(boneIndices.x)];
mat4 m1 = fyrox_boneMatrices.matrices[int(boneIndices.y)];
mat4 m2 = fyrox_boneMatrices.matrices[int(boneIndices.z)];
mat4 m3 = fyrox_boneMatrices.matrices[int(boneIndices.w)];
localPosition += m0 * inputPosition * boneWeights.x;
localPosition += m1 * inputPosition * boneWeights.y;
localPosition += m2 * inputPosition * boneWeights.z;
localPosition += m3 * inputPosition * boneWeights.w;
}
else
{
localPosition = inputPosition;
}
gl_Position = fyrox_instanceData.worldViewProjection * localPosition;
texCoord = vertexTexCoord;
}
"#,
fragment_shader:
r#"
in vec2 texCoord;
void main()
{
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;
layout(location = 4) in vec4 boneWeights;
layout(location = 5) in vec4 boneIndices;
out vec2 texCoord;
out vec3 worldPosition;
void main()
{
vec4 localPosition = vec4(0);
vec4 inputPosition = vec4(vertexPosition, 1.0);
for (int i = 0; i < fyrox_instanceData.blendShapesCount; ++i) {
TBlendShapeOffsets offsets = S_FetchBlendShapeOffsets(blendShapesStorage, gl_VertexID, i);
float weight = fyrox_instanceData.blendShapesWeights[i / 4][i % 4];
inputPosition.xyz += offsets.position * weight;
}
if (fyrox_instanceData.useSkeletalAnimation)
{
vec4 vertex = vec4(vertexPosition, 1.0);
mat4 m0 = fyrox_boneMatrices.matrices[int(boneIndices.x)];
mat4 m1 = fyrox_boneMatrices.matrices[int(boneIndices.y)];
mat4 m2 = fyrox_boneMatrices.matrices[int(boneIndices.z)];
mat4 m3 = fyrox_boneMatrices.matrices[int(boneIndices.w)];
localPosition += m0 * inputPosition * boneWeights.x;
localPosition += m1 * inputPosition * boneWeights.y;
localPosition += m2 * inputPosition * boneWeights.z;
localPosition += m3 * inputPosition * boneWeights.w;
}
else
{
localPosition = inputPosition;
}
gl_Position = fyrox_instanceData.worldViewProjection * localPosition;
worldPosition = (fyrox_instanceData.worldMatrix * localPosition).xyz;
texCoord = vertexTexCoord;
}
"#,
fragment_shader:
r#"
in vec2 texCoord;
in vec3 worldPosition;
layout(location = 0) out float depth;
void main()
{
if (texture(diffuseTexture, texCoord).a < 0.2) discard;
depth = length(fyrox_lightData.lightPosition - worldPosition);
}
"#,
)
],
)