Add MaterialTextureMipBias to control texture mip bias in materials for better frame upscaling
This commit is contained in:
@@ -24,7 +24,7 @@ namespace
|
||||
};
|
||||
};
|
||||
|
||||
MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
||||
MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture, bool useGlobalMipBias)
|
||||
{
|
||||
ASSERT(texture && box);
|
||||
const auto parent = box->GetParent<ShaderGraphNode<>>();
|
||||
@@ -60,15 +60,27 @@ MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, B
|
||||
// Check if hasn't been sampled during that tree eating
|
||||
if (valueBox->Cache.IsInvalid())
|
||||
{
|
||||
bool canUseSample = CanUseSample(_treeType);
|
||||
bool useLevel = !CanUseSample(_treeType), useBias = false;
|
||||
String mipLevel = TEXT("0");
|
||||
const auto layer = GetRootLayer();
|
||||
if (layer && layer->Domain == MaterialDomain::Decal && _treeType == MaterialTreeType::PixelShader)
|
||||
{
|
||||
// Decals use computed mip level due to ddx/ddy being unreliable
|
||||
canUseSample = false;
|
||||
useLevel = true;
|
||||
mipLevel = String::Format(TEXT("CalculateTextureMipmap(input, {})"), texture->ShaderName);
|
||||
}
|
||||
if (useGlobalMipBias)
|
||||
{
|
||||
if (useLevel)
|
||||
{
|
||||
mipLevel += TEXT(" + MaterialTextureMipBias");
|
||||
}
|
||||
else
|
||||
{
|
||||
useBias = true;
|
||||
mipLevel = TEXT("MaterialTextureMipBias");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if use custom UVs
|
||||
String uv;
|
||||
@@ -93,12 +105,8 @@ MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, B
|
||||
uv = use3dUVs ? TEXT("float3(input.TexCoord.xy, 0)") : TEXT("input.TexCoord.xy");
|
||||
}
|
||||
|
||||
// Select sampler
|
||||
// TODO: add option for texture groups and per texture options like wrap mode etc.
|
||||
// TODO: changing texture sampler option
|
||||
const Char* sampler = TEXT("SamplerLinearWrap");
|
||||
|
||||
// Sample texture
|
||||
const Char* sampler = TEXT("SamplerLinearWrap");
|
||||
if (texture->AsInteger == (int32)MaterialSceneTextures::SceneDepth)
|
||||
{
|
||||
// Sample depth buffer
|
||||
@@ -107,9 +115,8 @@ MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, B
|
||||
}
|
||||
else if (isNormalMap)
|
||||
{
|
||||
const Char* format = canUseSample ? TEXT("{0}.Sample({1}, {2}).xyz") : TEXT("{0}.SampleLevel({1}, {2}, {3}).xyz");
|
||||
|
||||
// Sample encoded normal map
|
||||
const Char* format = useLevel ? TEXT("{0}.SampleLevel({1}, {2}, {3}).xyz") : (useBias ? TEXT("{0}.SampleBias({1}, {2}, {3}).xyz") : TEXT("{0}.Sample({1}, {2}).xyz"));
|
||||
const String sampledValue = String::Format(format, texture->ShaderName, sampler, uv, mipLevel);
|
||||
const auto normalVector = writeLocal(VariantType::Float3, sampledValue, parent);
|
||||
|
||||
@@ -120,27 +127,8 @@ MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, B
|
||||
}
|
||||
else
|
||||
{
|
||||
// Select format string based on texture type
|
||||
const Char* format;
|
||||
/*if (isCubemap)
|
||||
{
|
||||
MISSING_CODE("sampling cube maps and 3d texture in material generator");
|
||||
//format = TEXT("SAMPLE_CUBEMAP({0}, {1})");
|
||||
}
|
||||
else*/
|
||||
{
|
||||
/*if (useCustomUVs)
|
||||
{
|
||||
createGradients(writer, parent);
|
||||
format = TEXT("SAMPLE_TEXTURE_GRAD({0}, {1}, {2}, {3})");
|
||||
}
|
||||
else*/
|
||||
{
|
||||
format = canUseSample ? TEXT("{0}.Sample({1}, {2})") : TEXT("{0}.SampleLevel({1}, {2}, {3})");
|
||||
}
|
||||
}
|
||||
|
||||
// Sample texture
|
||||
const Char* format = useLevel ? TEXT("{0}.SampleLevel({1}, {2}, {3})") : (useBias ? TEXT("{0}.SampleBias({1}, {2}, {3})") : TEXT("{0}.Sample({1}, {2})"));
|
||||
String sampledValue = String::Format(format, texture->ShaderName, sampler, uv, mipLevel);
|
||||
valueBox->Cache = writeLocal(VariantType::Float4, sampledValue, parent);
|
||||
}
|
||||
@@ -149,9 +137,9 @@ MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, B
|
||||
return &valueBox->Cache;
|
||||
}
|
||||
|
||||
void MaterialGenerator::sampleTexture(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
||||
void MaterialGenerator::sampleTexture(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture, bool useGlobalMipBias)
|
||||
{
|
||||
const auto sample = sampleTextureRaw(caller, value, box, texture);
|
||||
const auto sample = sampleTextureRaw(caller, value, box, texture, useGlobalMipBias);
|
||||
if (sample == nullptr)
|
||||
return;
|
||||
|
||||
@@ -202,16 +190,26 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||
{
|
||||
// Texture
|
||||
case 1:
|
||||
// Cube Texture
|
||||
case 3:
|
||||
// Normal Map
|
||||
case 4:
|
||||
{
|
||||
// Check if texture has been selected
|
||||
Guid textureId = (Guid)node->Values[0];
|
||||
if (textureId.IsValid())
|
||||
{
|
||||
// Get or create parameter for that texture
|
||||
auto param = findOrAddTexture(textureId);
|
||||
SerializedMaterialParam param;
|
||||
if (node->TypeID == 1) // Texture
|
||||
param = findOrAddTexture(textureId);
|
||||
else if (node->TypeID == 3) // Cube Texture
|
||||
param = findOrAddCubeTexture(textureId);
|
||||
else if (node->TypeID == 4) // Normal Map
|
||||
param = findOrAddNormalMap(textureId);
|
||||
|
||||
// Sample texture
|
||||
sampleTexture(node, value, box, ¶m);
|
||||
sampleTexture(node, value, box, ¶m, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -236,46 +234,6 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Cube Texture
|
||||
case 3:
|
||||
{
|
||||
// Check if texture has been selected
|
||||
Guid textureId = (Guid)node->Values[0];
|
||||
if (textureId.IsValid())
|
||||
{
|
||||
// Get or create parameter for that cube texture
|
||||
auto param = findOrAddCubeTexture(textureId);
|
||||
|
||||
// Sample texture
|
||||
sampleTexture(node, value, box, ¶m);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use default value
|
||||
value = Value::Zero;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Normal Map
|
||||
case 4:
|
||||
{
|
||||
// Check if texture has been selected
|
||||
Guid textureId = (Guid)node->Values[0];
|
||||
if (textureId.IsValid())
|
||||
{
|
||||
// Get or create parameter for that texture
|
||||
auto param = findOrAddNormalMap(textureId);
|
||||
|
||||
// Sample texture
|
||||
sampleTexture(node, value, box, ¶m);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use default value
|
||||
value = Value::Zero;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Parallax Occlusion Mapping
|
||||
case 5:
|
||||
{
|
||||
@@ -327,10 +285,11 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||
" float currRayHeight = 1.0;\n"
|
||||
" float lastSampledHeight = 1;\n"
|
||||
" int currSample = 0;\n"
|
||||
" float mipBiasDerivScale = pow(2, MaterialTextureMipBias);\n"
|
||||
|
||||
" while (currSample < (int)numSamples)\n"
|
||||
" {{\n"
|
||||
" float currSampledHeight = {1}.SampleGrad(SamplerLinearWrap, {10} + currOffset, {5}, {6}){7};\n"
|
||||
" float currSampledHeight = {1}.SampleGrad(SamplerLinearWrap, {10} + currOffset, {5} * mipBiasDerivScale, {6} * mipBiasDerivScale){7};\n"
|
||||
|
||||
" if (currSampledHeight > currRayHeight)\n"
|
||||
" {{\n"
|
||||
@@ -584,6 +543,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||
const bool isVolume = textureParam->Type == MaterialParameterType::GPUTextureVolume;
|
||||
const bool isNormalMap = textureParam->Type == MaterialParameterType::NormalMap;
|
||||
const bool use3dUVs = isCubemap || isArray || isVolume;
|
||||
const bool useGlobalMipBias = true; // Could be exposed as node option (separate check or within new set of CommonSamplerType values)
|
||||
uvs = Value::Cast(uvs, use3dUVs ? VariantType::Float3 : VariantType::Float2);
|
||||
|
||||
// Get other inputs
|
||||
@@ -613,7 +573,16 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||
{
|
||||
// Sample Texture
|
||||
const Char* format;
|
||||
if (useLevel || !canUseSample)
|
||||
if (useGlobalMipBias)
|
||||
{
|
||||
if (useLevel && useOffset)
|
||||
format = TEXT("{0}.SampleLevel({1}, {2}, {3} + MaterialTextureMipBias, {4})");
|
||||
else if (useOffset)
|
||||
format = TEXT("{0}.SampleBias({1}, {2}, MaterialTextureMipBias, {4})");
|
||||
else
|
||||
format = TEXT("{0}.SampleBias({1}, {2}, MaterialTextureMipBias)");
|
||||
}
|
||||
else if (useLevel || !canUseSample)
|
||||
{
|
||||
if (useOffset)
|
||||
format = TEXT("{0}.SampleLevel({1}, {2}, {3}, {4})");
|
||||
@@ -662,8 +631,9 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||
" 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"
|
||||
" float2 fdx = ddx({0});\n"
|
||||
" float2 fdy = ddy({0});\n"
|
||||
" float mipBiasDerivScale = pow(2, MaterialTextureMipBias);\n"
|
||||
" float2 fdx = ddx({0}) * mipBiasDerivScale;\n"
|
||||
" float2 fdy = ddy({0}) * mipBiasDerivScale;\n"
|
||||
" float4 tex1 = {1}.SampleGrad({2}, uv1, fdx, fdy, {4}) * weights.x;\n"
|
||||
" float4 tex2 = {1}.SampleGrad({2}, uv2, fdx, fdy, {4}) * weights.y;\n"
|
||||
" float4 tex3 = {1}.SampleGrad({2}, uv3, fdx, fdy, {4}) * weights.z;\n"
|
||||
|
||||
Reference in New Issue
Block a user