Added Stochastic Sampling material node
This commit is contained in:
@@ -405,6 +405,24 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.Output(0, "Color", typeof(Float3), 3)
|
NodeElementArchetype.Factory.Output(0, "Color", typeof(Float3), 3)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new NodeArchetype
|
||||||
|
{
|
||||||
|
TypeID = 17,
|
||||||
|
Title = "Stochastic Sample Texture",
|
||||||
|
Description = "Projects a texture using world-space coordinates instead of UVs.",
|
||||||
|
Flags = NodeFlags.MaterialGraph,
|
||||||
|
Size = new Float2(240, 60),
|
||||||
|
DefaultValues = new object[]
|
||||||
|
{
|
||||||
|
new Float2(1.0f, 1.0f),
|
||||||
|
},
|
||||||
|
Elements = new[]
|
||||||
|
{
|
||||||
|
NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0),
|
||||||
|
NodeElementArchetype.Factory.Input(1, "UV", true, typeof(Float2), 1, 0),
|
||||||
|
NodeElementArchetype.Factory.Output(0, "Color", typeof(Float4), 2),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -669,6 +669,115 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
|||||||
_writer.Write(*triplanarTexture);
|
_writer.Write(*triplanarTexture);
|
||||||
value = result;
|
value = result;
|
||||||
}
|
}
|
||||||
|
case 17:
|
||||||
|
{
|
||||||
|
auto textureBox = node->GetBox(0);
|
||||||
|
auto uvsBox = node->GetBox(1);
|
||||||
|
|
||||||
|
Value uvs;
|
||||||
|
const bool useCustomUVs = uvsBox->HasConnection();
|
||||||
|
if (useCustomUVs)
|
||||||
|
{
|
||||||
|
// Get custom UVs
|
||||||
|
uvs = eatBox(uvsBox->GetParent<Node>(), uvsBox->FirstConnection());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use default UVs
|
||||||
|
uvs = getUVs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textureBox->HasConnection())
|
||||||
|
{
|
||||||
|
// No texture to sample
|
||||||
|
value = Value::Zero;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CanUseSample(_treeType))
|
||||||
|
{
|
||||||
|
// Must sample texture in pixel shader
|
||||||
|
value = Value::Zero;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto texture = eatBox(textureBox->GetParent<Node>(), textureBox->FirstConnection());
|
||||||
|
const auto textureParam = findParam(texture.Value);
|
||||||
|
const bool isNormalMap = textureParam->Type == MaterialParameterType::NormalMap;
|
||||||
|
|
||||||
|
auto result = writeLocal(Value::InitForZero(ValueType::Float4), node);
|
||||||
|
createGradients(node);
|
||||||
|
|
||||||
|
auto proceduralSample = String::Format(TEXT(
|
||||||
|
" {{\n"
|
||||||
|
" float W1, W2, W3;\n"
|
||||||
|
" float2 vertex1, vertex2, vertex3;\n"
|
||||||
|
" float2 uv = {0} * 3.464; // 2 * sqrt (3);\n"
|
||||||
|
" float2 UV1, UV2, UV3;\n"
|
||||||
|
" const float2x2 gridToSkewedGrid = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 );\n"
|
||||||
|
" float2 skewedCoord = mul( gridToSkewedGrid, uv );\n"
|
||||||
|
" int2 baseId = int2( floor( skewedCoord ) );\n"
|
||||||
|
" float3 temp = float3( frac( skewedCoord ), 0 );\n"
|
||||||
|
" temp.z = 1.0 - temp.x - temp.y;\n"
|
||||||
|
" if ( temp.z > 0.0 )\n"
|
||||||
|
" {{\n"
|
||||||
|
" W1 = temp.z;\n"
|
||||||
|
" W2 = temp.y;\n"
|
||||||
|
" W3 = temp.x;\n"
|
||||||
|
" vertex1 = baseId;\n"
|
||||||
|
" vertex2 = baseId + int2( 0, 1 );\n"
|
||||||
|
" vertex3 = baseId + int2( 1, 0 );\n"
|
||||||
|
" }}\n"
|
||||||
|
" else\n"
|
||||||
|
" {{\n"
|
||||||
|
" W1 = -temp.z;\n"
|
||||||
|
" W2 = 1.0 - temp.y;\n"
|
||||||
|
" W3 = 1.0 - temp.x;\n"
|
||||||
|
" vertex1 = baseId + int2( 1, 1 );\n"
|
||||||
|
" vertex2 = baseId + int2( 1, 0 );\n"
|
||||||
|
" vertex3 = baseId + int2( 0, 1 );\n"
|
||||||
|
" }}\n"
|
||||||
|
" UV1 = {0} + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 );\n"
|
||||||
|
" UV2 = {0} + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 );\n"
|
||||||
|
" UV3 = {0} + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 );\n"
|
||||||
|
" float4 tex1 = {1}.SampleGrad(SamplerLinearWrap, UV1, {2}, {3});\n"
|
||||||
|
" float4 tex2 = {1}.SampleGrad(SamplerLinearWrap, UV2, {2}, {3});\n"
|
||||||
|
" float4 tex3 = {1}.SampleGrad(SamplerLinearWrap, UV3, {2}, {3});\n"
|
||||||
|
),
|
||||||
|
uvs.Value, // {0}
|
||||||
|
texture.Value, // {1}
|
||||||
|
_ddx.Value, // {2}
|
||||||
|
_ddy.Value // {3}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Decode normal map vector
|
||||||
|
if (isNormalMap)
|
||||||
|
{
|
||||||
|
proceduralSample += String::Format(TEXT(
|
||||||
|
" tex1.xy = tex1.xy * 2.0 - 1.0;\n"
|
||||||
|
" tex1.z = sqrt(saturate(1.0 - dot(tex1.xy, tex1.xy))); \n"
|
||||||
|
" tex2.xy = tex2.xy * 2.0 - 1.0;\n"
|
||||||
|
" tex2.z = sqrt(saturate(1.0 - dot(tex2.xy, tex2.xy))); \n"
|
||||||
|
" tex3.xy = tex3.xy * 2.0 - 1.0;\n"
|
||||||
|
" tex3.z = sqrt(saturate(1.0 - dot(tex3.xy, tex3.xy))); \n"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
proceduralSample += String::Format(TEXT(
|
||||||
|
" tex1 *= W1;\n"
|
||||||
|
" tex2 *= W2;\n"
|
||||||
|
" tex3 *= W3;\n"
|
||||||
|
" {0} = tex1 + tex2 + tex3;\n"
|
||||||
|
" }}\n"
|
||||||
|
),
|
||||||
|
result.Value // {0}
|
||||||
|
);
|
||||||
|
|
||||||
|
_writer.Write(*proceduralSample);
|
||||||
|
value = result;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user