Merge source files
This commit is contained in:
@@ -1,166 +0,0 @@
|
|||||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#if COMPILE_WITH_MATERIAL_GRAPH
|
|
||||||
|
|
||||||
#include "MaterialGenerator.h"
|
|
||||||
|
|
||||||
MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
|
||||||
{
|
|
||||||
ASSERT(texture && box);
|
|
||||||
|
|
||||||
// Cache data
|
|
||||||
const auto parent = box->GetParent<ShaderGraphNode<>>();
|
|
||||||
const bool isCubemap = texture->Type == MaterialParameterType::CubeTexture;
|
|
||||||
const bool isArray = texture->Type == MaterialParameterType::GPUTextureArray;
|
|
||||||
const bool isVolume = texture->Type == MaterialParameterType::GPUTextureVolume;
|
|
||||||
const bool isNormalMap = texture->Type == MaterialParameterType::NormalMap;
|
|
||||||
const bool canUseSample = CanUseSample(_treeType);
|
|
||||||
MaterialGraphBox* valueBox = parent->GetBox(1);
|
|
||||||
|
|
||||||
// Check if has variable assigned
|
|
||||||
if (texture->Type != MaterialParameterType::Texture
|
|
||||||
&& texture->Type != MaterialParameterType::NormalMap
|
|
||||||
&& texture->Type != MaterialParameterType::SceneTexture
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTexture
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTextureVolume
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTextureCube
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTextureArray
|
|
||||||
&& texture->Type != MaterialParameterType::CubeTexture)
|
|
||||||
{
|
|
||||||
OnError(caller, box, TEXT("No parameter for texture sample node."));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if it's 'Object' box that is using only texture object without sampling
|
|
||||||
if (box->ID == 6)
|
|
||||||
{
|
|
||||||
// Return texture object
|
|
||||||
value.Value = texture->ShaderName;
|
|
||||||
value.Type = VariantType::Object;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if hasn't been sampled during that tree eating
|
|
||||||
if (valueBox->Cache.IsInvalid())
|
|
||||||
{
|
|
||||||
// Check if use custom UVs
|
|
||||||
String uv;
|
|
||||||
MaterialGraphBox* uvBox = parent->GetBox(0);
|
|
||||||
bool useCustomUVs = uvBox->HasConnection();
|
|
||||||
bool use3dUVs = isCubemap || isArray || isVolume;
|
|
||||||
if (useCustomUVs)
|
|
||||||
{
|
|
||||||
// Get custom UVs
|
|
||||||
auto textureParamId = texture->ID;
|
|
||||||
ASSERT(textureParamId.IsValid());
|
|
||||||
MaterialValue v = tryGetValue(uvBox, getUVs);
|
|
||||||
uv = MaterialValue::Cast(v, use3dUVs ? VariantType::Float3 : VariantType::Float2).Value;
|
|
||||||
|
|
||||||
// Restore texture (during tryGetValue pointer could go invalid)
|
|
||||||
texture = findParam(textureParamId);
|
|
||||||
ASSERT(texture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use default UVs
|
|
||||||
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
|
|
||||||
if (isNormalMap)
|
|
||||||
{
|
|
||||||
const Char* format = canUseSample ? TEXT("{0}.Sample({1}, {2}).xyz") : TEXT("{0}.SampleLevel({1}, {2}, 0).xyz");
|
|
||||||
|
|
||||||
// Sample encoded normal map
|
|
||||||
const String sampledValue = String::Format(format, texture->ShaderName, sampler, uv);
|
|
||||||
const auto normalVector = writeLocal(VariantType::Float3, sampledValue, parent);
|
|
||||||
|
|
||||||
// Decode normal vector
|
|
||||||
_writer.Write(TEXT("\t{0}.xy = {0}.xy * 2.0 - 1.0;\n"), normalVector.Value);
|
|
||||||
_writer.Write(TEXT("\t{0}.z = sqrt(saturate(1.0 - dot({0}.xy, {0}.xy)));\n"), normalVector.Value);
|
|
||||||
valueBox->Cache = normalVector;
|
|
||||||
}
|
|
||||||
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}, 0)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sample texture
|
|
||||||
String sampledValue = String::Format(format, texture->ShaderName, sampler, uv, _ddx.Value, _ddy.Value);
|
|
||||||
valueBox->Cache = writeLocal(VariantType::Float4, sampledValue, parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &valueBox->Cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialGenerator::sampleTexture(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
|
||||||
{
|
|
||||||
const auto sample = sampleTextureRaw(caller, value, box, texture);
|
|
||||||
if (sample == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Set result values based on box ID
|
|
||||||
switch (box->ID)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
value = *sample;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
value.Value = sample->Value + _subs[0];
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
value.Value = sample->Value + _subs[1];
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
value.Value = sample->Value + _subs[2];
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
value.Value = sample->Value + _subs[3];
|
|
||||||
break;
|
|
||||||
default: CRASH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value.Type = box->Type.Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialGenerator::sampleSceneDepth(Node* caller, Value& value, Box* box)
|
|
||||||
{
|
|
||||||
// Sample depth buffer
|
|
||||||
auto param = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
|
|
||||||
const auto depthSample = sampleTextureRaw(caller, value, box, ¶m);
|
|
||||||
if (depthSample == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Linearize raw device depth
|
|
||||||
linearizeSceneDepth(caller, *depthSample, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialGenerator::linearizeSceneDepth(Node* caller, const Value& depth, Value& value)
|
|
||||||
{
|
|
||||||
value = writeLocal(VariantType::Float, String::Format(TEXT("ViewInfo.w / ({0}.x - ViewInfo.z)"), depth.Value), caller);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -4,6 +4,165 @@
|
|||||||
|
|
||||||
#include "MaterialGenerator.h"
|
#include "MaterialGenerator.h"
|
||||||
|
|
||||||
|
MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
||||||
|
{
|
||||||
|
ASSERT(texture && box);
|
||||||
|
|
||||||
|
// Cache data
|
||||||
|
const auto parent = box->GetParent<ShaderGraphNode<>>();
|
||||||
|
const bool isCubemap = texture->Type == MaterialParameterType::CubeTexture;
|
||||||
|
const bool isArray = texture->Type == MaterialParameterType::GPUTextureArray;
|
||||||
|
const bool isVolume = texture->Type == MaterialParameterType::GPUTextureVolume;
|
||||||
|
const bool isNormalMap = texture->Type == MaterialParameterType::NormalMap;
|
||||||
|
const bool canUseSample = CanUseSample(_treeType);
|
||||||
|
MaterialGraphBox* valueBox = parent->GetBox(1);
|
||||||
|
|
||||||
|
// Check if has variable assigned
|
||||||
|
if (texture->Type != MaterialParameterType::Texture
|
||||||
|
&& texture->Type != MaterialParameterType::NormalMap
|
||||||
|
&& texture->Type != MaterialParameterType::SceneTexture
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTexture
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTextureVolume
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTextureCube
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTextureArray
|
||||||
|
&& texture->Type != MaterialParameterType::CubeTexture)
|
||||||
|
{
|
||||||
|
OnError(caller, box, TEXT("No parameter for texture sample node."));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's 'Object' box that is using only texture object without sampling
|
||||||
|
if (box->ID == 6)
|
||||||
|
{
|
||||||
|
// Return texture object
|
||||||
|
value.Value = texture->ShaderName;
|
||||||
|
value.Type = VariantType::Object;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if hasn't been sampled during that tree eating
|
||||||
|
if (valueBox->Cache.IsInvalid())
|
||||||
|
{
|
||||||
|
// Check if use custom UVs
|
||||||
|
String uv;
|
||||||
|
MaterialGraphBox* uvBox = parent->GetBox(0);
|
||||||
|
bool useCustomUVs = uvBox->HasConnection();
|
||||||
|
bool use3dUVs = isCubemap || isArray || isVolume;
|
||||||
|
if (useCustomUVs)
|
||||||
|
{
|
||||||
|
// Get custom UVs
|
||||||
|
auto textureParamId = texture->ID;
|
||||||
|
ASSERT(textureParamId.IsValid());
|
||||||
|
MaterialValue v = tryGetValue(uvBox, getUVs);
|
||||||
|
uv = MaterialValue::Cast(v, use3dUVs ? VariantType::Float3 : VariantType::Float2).Value;
|
||||||
|
|
||||||
|
// Restore texture (during tryGetValue pointer could go invalid)
|
||||||
|
texture = findParam(textureParamId);
|
||||||
|
ASSERT(texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use default UVs
|
||||||
|
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
|
||||||
|
if (isNormalMap)
|
||||||
|
{
|
||||||
|
const Char* format = canUseSample ? TEXT("{0}.Sample({1}, {2}).xyz") : TEXT("{0}.SampleLevel({1}, {2}, 0).xyz");
|
||||||
|
|
||||||
|
// Sample encoded normal map
|
||||||
|
const String sampledValue = String::Format(format, texture->ShaderName, sampler, uv);
|
||||||
|
const auto normalVector = writeLocal(VariantType::Float3, sampledValue, parent);
|
||||||
|
|
||||||
|
// Decode normal vector
|
||||||
|
_writer.Write(TEXT("\t{0}.xy = {0}.xy * 2.0 - 1.0;\n"), normalVector.Value);
|
||||||
|
_writer.Write(TEXT("\t{0}.z = sqrt(saturate(1.0 - dot({0}.xy, {0}.xy)));\n"), normalVector.Value);
|
||||||
|
valueBox->Cache = normalVector;
|
||||||
|
}
|
||||||
|
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}, 0)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample texture
|
||||||
|
String sampledValue = String::Format(format, texture->ShaderName, sampler, uv, _ddx.Value, _ddy.Value);
|
||||||
|
valueBox->Cache = writeLocal(VariantType::Float4, sampledValue, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &valueBox->Cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialGenerator::sampleTexture(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
||||||
|
{
|
||||||
|
const auto sample = sampleTextureRaw(caller, value, box, texture);
|
||||||
|
if (sample == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set result values based on box ID
|
||||||
|
switch (box->ID)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
value = *sample;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value.Value = sample->Value + _subs[0];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value.Value = sample->Value + _subs[1];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value.Value = sample->Value + _subs[2];
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
value.Value = sample->Value + _subs[3];
|
||||||
|
break;
|
||||||
|
default: CRASH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value.Type = box->Type.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialGenerator::sampleSceneDepth(Node* caller, Value& value, Box* box)
|
||||||
|
{
|
||||||
|
// Sample depth buffer
|
||||||
|
auto param = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
|
||||||
|
const auto depthSample = sampleTextureRaw(caller, value, box, ¶m);
|
||||||
|
if (depthSample == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Linearize raw device depth
|
||||||
|
linearizeSceneDepth(caller, *depthSample, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialGenerator::linearizeSceneDepth(Node* caller, const Value& depth, Value& value)
|
||||||
|
{
|
||||||
|
value = writeLocal(VariantType::Float, String::Format(TEXT("ViewInfo.w / ({0}.x - ViewInfo.z)"), depth.Value), caller);
|
||||||
|
}
|
||||||
|
|
||||||
void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||||
{
|
{
|
||||||
switch (node->TypeID)
|
switch (node->TypeID)
|
||||||
|
|||||||
Reference in New Issue
Block a user