*
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
#include "shaders/IShaderFactorySource.h"
|
||||
#include "shaders/IShaderGraphNodeFactory.h"
|
||||
#include <Property.h>
|
||||
#include <math/LifeMath.h>
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
#define NEW_NODE(_NodeName, _NodeType) \
|
||||
IShaderGraphNode* ##_NodeName## = new IShaderGraphNode(); \
|
||||
_NodeName##->Name = STR(#_NodeName); \
|
||||
_NodeName##->NodeType = ##_NodeType;
|
||||
|
||||
#define NEW_NODE_IN(_NodeName, _DataType, _InName) \
|
||||
IShaderGraphNodePort* in_a##_InName##_DataType## = new IShaderGraphNodePort(##_NodeName##); \
|
||||
in_a##_InName##_DataType##->DataType = _DataType; \
|
||||
in_a##_InName##_DataType##->Name = STR(#_InName); \
|
||||
_NodeName##->Inputs.push_back(in_a##_InName##_DataType##);
|
||||
|
||||
#define NEW_NODE_OUT(_NodeName, _DataType, _OutName) \
|
||||
IShaderGraphNodePort* out_a##_OutName##_DataType## = new IShaderGraphNodePort(##_NodeName##); \
|
||||
out_a##_OutName##_DataType##->DataType = _DataType; \
|
||||
out_a##_OutName##_DataType##->Name = STR(#_OutName); \
|
||||
_NodeName##->Outputs.push_back(out_a##_OutName##_DataType##);
|
||||
|
||||
void IShaderFactorySource::Register(IShaderGraphNodeFactory* factory)
|
||||
{
|
||||
factory->RegisterNode(STR("Material"), &IShaderFactorySource::node_mat_std);
|
||||
factory->RegisterNode(STR("OpAdd"), &IShaderFactorySource::node_op_add);
|
||||
factory->RegisterNode(STR("OpLerp"), &IShaderFactorySource::node_op_lerp);
|
||||
factory->RegisterNode(STR("OpSub"), &IShaderFactorySource::node_op_sub);
|
||||
factory->RegisterNode(STR("OpMul"), &IShaderFactorySource::node_op_mul);
|
||||
factory->RegisterNode(STR("OpDiv"), &IShaderFactorySource::node_op_div);
|
||||
factory->RegisterNode(STR("OpDot"), &IShaderFactorySource::node_op_dot);
|
||||
factory->RegisterNode(STR("ConstFloat1"), &IShaderFactorySource::node_const_f1);
|
||||
factory->RegisterNode(STR("ConstFloat2"), &IShaderFactorySource::node_const_f2);
|
||||
factory->RegisterNode(STR("ConstFloat3"), &IShaderFactorySource::node_const_f3);
|
||||
factory->RegisterNode(STR("ConstFloat4"), &IShaderFactorySource::node_const_f4);
|
||||
|
||||
factory->RegisterNode(STR("OpNormalize"), &IShaderFactorySource::node_op_normalize);
|
||||
factory->RegisterNode(STR("SrcTex2D"), &IShaderFactorySource::node_src_sam_2d);
|
||||
factory->RegisterNode(STR("SrcUV"), &IShaderFactorySource::node_src_uv);
|
||||
|
||||
factory->RegisterNode(STR("DecodeNormal"), &IShaderFactorySource::node_op_decode_normal);
|
||||
factory->RegisterNode(STR("Time"), &IShaderFactorySource::node_val_time);
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_mat_std()
|
||||
{
|
||||
NEW_NODE(Material, NT_MATERIAL);
|
||||
NEW_NODE_IN(Material, DT_FLOAT3, Diffuse);
|
||||
NEW_NODE_IN(Material, DT_FLOAT3, Specular);
|
||||
NEW_NODE_IN(Material, DT_FLOAT, SpecularPower);
|
||||
NEW_NODE_IN(Material, DT_FLOAT3, Normal);
|
||||
return Material;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_add()
|
||||
{
|
||||
NEW_NODE(Add, NT_OP);
|
||||
NEW_NODE_IN(Add, DT_ANY, A);
|
||||
NEW_NODE_IN(Add, DT_ANY, B);
|
||||
NEW_NODE_OUT(Add, DT_ANY, C);
|
||||
return Add;
|
||||
}
|
||||
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_lerp()
|
||||
{
|
||||
NEW_NODE(Lerp, NT_OP);
|
||||
NEW_NODE_IN(Lerp, DT_ANY, A);
|
||||
NEW_NODE_IN(Lerp, DT_ANY, B);
|
||||
NEW_NODE_IN(Lerp, DT_FLOAT, Factor);
|
||||
NEW_NODE_OUT(Lerp, DT_ANY, C);
|
||||
return Lerp;
|
||||
}
|
||||
|
||||
IShaderGraphNode* IShaderFactorySource::node_val_time()
|
||||
{
|
||||
NEW_NODE(Time, NT_CONST);
|
||||
NEW_NODE_OUT(Time, DT_FLOAT4, RGBA);
|
||||
NEW_NODE_OUT(Time, DT_FLOAT, R);
|
||||
return Time;
|
||||
}
|
||||
|
||||
IShaderGraphNode* IShaderFactorySource::node_const_f1()
|
||||
{
|
||||
IShaderGraphNode* node = new IShaderGraphNode();
|
||||
node->Name = STR("ConstFloat1");
|
||||
node->NodeType = NT_CONST;
|
||||
|
||||
IShaderGraphNodePort* out_a = new IShaderGraphNodePort(node);
|
||||
out_a->DataType = DT_FLOAT;
|
||||
out_a->Name = STR("A");
|
||||
|
||||
node->Outputs.push_back(out_a);
|
||||
|
||||
LifeCore::Property<float>* valueProperty = new LifeCore::Property<float>();
|
||||
(*valueProperty) = 0.5f;
|
||||
valueProperty->AddAttribute(STR("Name"), STR("Value"));
|
||||
valueProperty->AddAttribute(STR("DisplayName"), STR("Value"));
|
||||
node->RegisterProperty(valueProperty);
|
||||
|
||||
return node;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_const_f2()
|
||||
{
|
||||
IShaderGraphNode* node = new IShaderGraphNode();
|
||||
node->Name = STR("ConstFloat2");
|
||||
node->NodeType = NT_CONST;
|
||||
|
||||
IShaderGraphNodePort* out_a = new IShaderGraphNodePort(node);
|
||||
out_a->DataType = DT_FLOAT2;
|
||||
out_a->Name = STR("A");
|
||||
|
||||
LifeCore::Property<LifeMath::float2>* valueProperty = new LifeCore::Property<LifeMath::float2>();
|
||||
(*valueProperty) = LifeMath::float2(0.0f, 0.0f);
|
||||
valueProperty->AddAttribute(STR("Name"), STR("Value"));
|
||||
valueProperty->AddAttribute(STR("DisplayName"), STR("Value"));
|
||||
node->RegisterProperty(valueProperty);
|
||||
|
||||
|
||||
node->Outputs.push_back(out_a);
|
||||
return node;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_const_f3()
|
||||
{
|
||||
IShaderGraphNode* node = new IShaderGraphNode();
|
||||
node->Name = STR("ConstFloat3");
|
||||
node->NodeType = NT_CONST;
|
||||
|
||||
IShaderGraphNodePort* out_a = new IShaderGraphNodePort(node);
|
||||
out_a->DataType = DT_FLOAT3;
|
||||
out_a->Name = STR("A");
|
||||
|
||||
LifeCore::Property<LifeMath::float3>* valueProperty = new LifeCore::Property<LifeMath::float3>();
|
||||
(*valueProperty) = LifeMath::float3(0.0f, 0.0f, 0.0f);
|
||||
valueProperty->AddAttribute(STR("Name"), STR("Value"));
|
||||
valueProperty->AddAttribute(STR("DisplayName"), STR("Value"));
|
||||
node->RegisterProperty(valueProperty);
|
||||
|
||||
node->Outputs.push_back(out_a);
|
||||
return node;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_const_f4()
|
||||
{
|
||||
IShaderGraphNode* node = new IShaderGraphNode();
|
||||
node->Name = STR("ConstFloat4");
|
||||
node->NodeType = NT_CONST;
|
||||
|
||||
IShaderGraphNodePort* out_a = new IShaderGraphNodePort(node);
|
||||
out_a->DataType = DT_FLOAT4;
|
||||
out_a->Name = STR("A");
|
||||
|
||||
LifeCore::Property<LifeMath::float4>* valueProperty = new LifeCore::Property<LifeMath::float4>();
|
||||
(*valueProperty) = LifeMath::float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
valueProperty->AddAttribute(STR("Name"), STR("Value"));
|
||||
valueProperty->AddAttribute(STR("DisplayName"), STR("Value"));
|
||||
node->RegisterProperty(valueProperty);
|
||||
|
||||
|
||||
|
||||
node->Outputs.push_back(out_a);
|
||||
return node;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_sub()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_mul()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_div()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_dot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_cross()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_normalize()
|
||||
{
|
||||
IShaderGraphNode* node = new IShaderGraphNode();
|
||||
node->Name = STR("Normalize");
|
||||
node->NodeType = NT_OP;
|
||||
|
||||
|
||||
IShaderGraphNodePort* in_a = new IShaderGraphNodePort(node);
|
||||
in_a->DataType = DT_ANY;
|
||||
in_a->Name = STR("A");
|
||||
|
||||
IShaderGraphNodePort* out_a = new IShaderGraphNodePort(node);
|
||||
out_a->DataType = DT_ANY;
|
||||
out_a->Name = STR("B");
|
||||
|
||||
node->Inputs.push_back(in_a);
|
||||
node->Outputs.push_back(out_a);
|
||||
|
||||
return node;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_saturate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_cmp_le()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_cmp_l()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_cmp_ge()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_cmp_g()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_cmp_e()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_decode_g()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_op_decode_normal()
|
||||
{
|
||||
NEW_NODE(DecodeNormal, NT_OP);
|
||||
NEW_NODE_IN(DecodeNormal, DT_ANY, TexNormal);
|
||||
NEW_NODE_OUT(DecodeNormal, DT_FLOAT3, Normal);
|
||||
return DecodeNormal;
|
||||
}
|
||||
|
||||
IShaderGraphNode* IShaderFactorySource::node_src_uv()
|
||||
{
|
||||
NEW_NODE(UV, NT_RES);
|
||||
NEW_NODE_OUT(UV, DT_FLOAT2, UV);
|
||||
|
||||
LifeCore::Property<uint32>* channelProperty = new LifeCore::Property<uint32>();
|
||||
(*channelProperty) = 0;
|
||||
channelProperty->AddAttribute(STR("Name"), STR("Channel"));
|
||||
channelProperty->AddAttribute(STR("DisplayName"), STR("UV Channel ID"));
|
||||
UV->RegisterProperty(channelProperty);
|
||||
|
||||
return UV;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_src_sam_2d()
|
||||
{
|
||||
IShaderGraphNode* node = new IShaderGraphNode();
|
||||
node->Name = STR("Sam2D");
|
||||
node->NodeType = NT_RES;
|
||||
|
||||
IShaderGraphNodePort* in_a = new IShaderGraphNodePort(node);
|
||||
in_a->DataType = DT_FLOAT2;
|
||||
in_a->Name = STR("UV");
|
||||
|
||||
IShaderGraphNodePort* out_a = new IShaderGraphNodePort(node);
|
||||
out_a->DataType = DT_FLOAT4;
|
||||
out_a->Name = STR("RGBA");
|
||||
|
||||
IShaderGraphNodePort* out_b = new IShaderGraphNodePort(node);
|
||||
out_b->DataType = DT_FLOAT;
|
||||
out_b->Name = STR("R");
|
||||
|
||||
IShaderGraphNodePort* out_c = new IShaderGraphNodePort(node);
|
||||
out_c->DataType = DT_FLOAT;
|
||||
out_c->Name = STR("G");
|
||||
|
||||
IShaderGraphNodePort* out_d = new IShaderGraphNodePort(node);
|
||||
out_d->DataType = DT_FLOAT;
|
||||
out_d->Name = STR("B");
|
||||
|
||||
IShaderGraphNodePort* out_e = new IShaderGraphNodePort(node);
|
||||
out_e->DataType = DT_FLOAT;
|
||||
out_e->Name = STR("A");
|
||||
|
||||
node->Inputs.push_back(in_a);
|
||||
node->Outputs.push_back(out_a);
|
||||
node->Outputs.push_back(out_b);
|
||||
node->Outputs.push_back(out_c);
|
||||
node->Outputs.push_back(out_d);
|
||||
node->Outputs.push_back(out_e);
|
||||
|
||||
|
||||
LifeCore::Property<String>* filename = new LifeCore::Property<String>();
|
||||
(*filename) = STR("");
|
||||
filename->AddAttribute(STR("Name"), STR("FilePath"));
|
||||
filename->AddAttribute(STR("DisplayName"), STR("FilePath"));
|
||||
filename->AddAttribute(STR("ValueEditor"), STR("FilePath"));
|
||||
node->RegisterProperty(filename);
|
||||
|
||||
return node;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_src_sam_3d()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
IShaderGraphNode* IShaderFactorySource::node_src_sam_cube()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef IShaderFactorySource_h__
|
||||
#define IShaderFactorySource_h__
|
||||
|
||||
#include "shaders/IShaderGraphNode.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class IShaderGraphNodeFactory;
|
||||
class IShaderFactorySource
|
||||
{
|
||||
public:
|
||||
static void Register(IShaderGraphNodeFactory* factory);
|
||||
static IShaderGraphNode* node_mat_std();
|
||||
static IShaderGraphNode* node_op_add();
|
||||
static IShaderGraphNode* node_op_lerp();
|
||||
static IShaderGraphNode* node_op_sub();
|
||||
static IShaderGraphNode* node_op_mul();
|
||||
static IShaderGraphNode* node_op_div();
|
||||
static IShaderGraphNode* node_op_dot();
|
||||
static IShaderGraphNode* node_op_cross();
|
||||
static IShaderGraphNode* node_op_normalize();
|
||||
static IShaderGraphNode* node_op_saturate();
|
||||
static IShaderGraphNode* node_op_cmp_le();
|
||||
static IShaderGraphNode* node_op_cmp_l();
|
||||
static IShaderGraphNode* node_op_cmp_ge();
|
||||
static IShaderGraphNode* node_op_cmp_g();
|
||||
static IShaderGraphNode* node_op_cmp_e();
|
||||
|
||||
static IShaderGraphNode* node_op_decode_g();
|
||||
static IShaderGraphNode* node_op_decode_normal();
|
||||
|
||||
static IShaderGraphNode* node_src_uv();
|
||||
static IShaderGraphNode* node_src_sam_2d();
|
||||
static IShaderGraphNode* node_src_sam_3d();
|
||||
static IShaderGraphNode* node_src_sam_cube();
|
||||
|
||||
static IShaderGraphNode* node_const_f1();
|
||||
static IShaderGraphNode* node_const_f2();
|
||||
static IShaderGraphNode* node_const_f3();
|
||||
static IShaderGraphNode* node_const_f4();
|
||||
|
||||
static IShaderGraphNode* node_val_time();
|
||||
};
|
||||
}
|
||||
#endif // IShaderFactorySource_h__
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "shaders/IShaderGraph.h"
|
||||
#include <Types.h>
|
||||
#include "XML.h"
|
||||
|
||||
#define NAME_LENGTH 64
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
IShaderGraph::IShaderGraph(IShaderGraphNodeFactory* factory)
|
||||
:last_id(0)
|
||||
{
|
||||
pFactory = factory;
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
texture_slots[i] = -1;
|
||||
}
|
||||
}
|
||||
IShaderGraph::~IShaderGraph()
|
||||
{
|
||||
}
|
||||
int IShaderGraph::GrabTextureSlot()
|
||||
{
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
if(texture_slots[i] == -1)
|
||||
{
|
||||
texture_slots[i] = 1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
IShaderGraphNode* IShaderGraph::AddNode(const String& name)
|
||||
{
|
||||
IShaderGraphNode* node = pFactory->Build(name);
|
||||
node->id = GetID();
|
||||
Nodes.push_back(node);
|
||||
|
||||
if(name == STR("SrcTex2D"))
|
||||
{
|
||||
node->resource_id = GrabTextureSlot();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
bool IShaderGraph::DeleteNode(int id)
|
||||
{
|
||||
for(NodeCollectionIt it = Nodes.begin(); it != Nodes.end(); ++it)
|
||||
{
|
||||
IShaderGraphNode* n = (*it);
|
||||
if(n->id == id) {
|
||||
|
||||
//deactivate output links
|
||||
for(int j = 0; j < n->Outputs.size(); j++){
|
||||
IShaderGraphNodePort* port = n->Outputs[j];
|
||||
port->BreakLink();
|
||||
delete port;
|
||||
}
|
||||
|
||||
//deactivate input links
|
||||
for(int j = 0; j < n->Inputs.size(); j++){
|
||||
IShaderGraphNodePort* port = n->Inputs[j];
|
||||
port->BreakLink();
|
||||
delete port;
|
||||
}
|
||||
|
||||
|
||||
delete (*it);
|
||||
Nodes.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
IShaderGraphNode* IShaderGraph::GetNodeByID(int id)
|
||||
{
|
||||
int nc = Nodes.size();
|
||||
for(int i = 0; i < nc; i++)
|
||||
{
|
||||
if(Nodes[i]->id == id)
|
||||
return Nodes[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void IShaderGraph::Clear()
|
||||
{
|
||||
int nc = Nodes.size();
|
||||
for(int i = 0; i < nc; i++)
|
||||
{
|
||||
delete Nodes[i];
|
||||
}
|
||||
Nodes.clear();
|
||||
}
|
||||
IShaderGraphNode* IShaderGraph::GetNodeByArrayID(int id)
|
||||
{
|
||||
int nc = Nodes.size();
|
||||
if(id < nc)
|
||||
{
|
||||
return Nodes[id];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t IShaderGraph::GetNodeCount()
|
||||
{
|
||||
return Nodes.size();
|
||||
}
|
||||
void IShaderGraph::SerializeXML(LifeCore::IMemoryStream* stm)
|
||||
{
|
||||
/*int node_count = Nodes.size();
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_node rootNode = doc.append_child("ShaderGraph");
|
||||
rootNode.append_attribute("NodeCount") = node_count;
|
||||
rootNode.append_attribute("LastID") = last_id;
|
||||
|
||||
//write node info
|
||||
for(int i = 0; i < node_count; i++)
|
||||
{
|
||||
IShaderGraphNode* n = Nodes[i];
|
||||
pugi::xml_node node = rootNode.append_child("Node");
|
||||
node.append_attribute("Name") = n->Name;
|
||||
node.append_attribute("ID") = n->id;
|
||||
|
||||
}*/
|
||||
}
|
||||
bool IShaderGraph::DeserializeXML(LifeCore::IMemoryStream* stm)
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
void IShaderGraph::Serialize(LifeCore::IMemoryStream* stm)
|
||||
{
|
||||
|
||||
int node_count = Nodes.size();
|
||||
//write total nodes count
|
||||
stm->Write(node_count);
|
||||
//write last id value
|
||||
stm->Write(last_id);
|
||||
|
||||
//write basic node info
|
||||
for(int i = 0; i < node_count; i++){
|
||||
IShaderGraphNode* n = Nodes[i];
|
||||
StringSerialize(n->Name, stm);
|
||||
stm->Write(n->id);
|
||||
}
|
||||
|
||||
//write advanced node info
|
||||
for(int i = 0; i < node_count; i++){
|
||||
IShaderGraphNode* n = Nodes[i];
|
||||
n->Serialize(stm); //serialize properties
|
||||
for(int j = 0; j < n->Inputs.size(); j++){
|
||||
IShaderGraphNodePort* port = n->Inputs[j];
|
||||
int val = -1;
|
||||
int parent = -1;
|
||||
if(port->GetLinkCount()){
|
||||
val = port->GetLink(0)->Parent->GetOutputID(port->GetLink(0));
|
||||
parent = port->GetLink(0)->Parent->id;
|
||||
}
|
||||
//write attached node ID
|
||||
stm->Write(parent);
|
||||
//write attached node port ID
|
||||
stm->Write(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IShaderGraph::Deserialize(LifeCore::IMemoryStream* stm)
|
||||
{
|
||||
int node_count;
|
||||
stm->ReadInt32(node_count);
|
||||
stm->ReadInt32(last_id);
|
||||
|
||||
//read basic info and create nodes
|
||||
for(int i = 0; i < node_count; i++){
|
||||
//get node name
|
||||
String name = StringDeserialize(stm);
|
||||
IShaderGraphNode* n = pFactory->Build(name);
|
||||
//get node ID
|
||||
stm->ReadInt32(n->id);
|
||||
Nodes.push_back(n);
|
||||
}
|
||||
|
||||
//read extended info
|
||||
for(int i = 0; i < node_count; i++){
|
||||
IShaderGraphNode* n = Nodes[i];
|
||||
n->Deserialize(stm); //deserialize properties
|
||||
int pc = n->Inputs.size();
|
||||
|
||||
//read ports info
|
||||
for(int j = 0; j < pc; j++){
|
||||
int nid, pid;
|
||||
//read attached node id
|
||||
stm->ReadInt32(nid);
|
||||
//read attached port id
|
||||
stm->ReadInt32(pid);
|
||||
//if attached - make link
|
||||
if(pid != -1){
|
||||
//current node
|
||||
IShaderGraphNode* cn = Nodes[i];
|
||||
//attachment node
|
||||
IShaderGraphNode* an = GetNodeByID(nid);
|
||||
cn->Inputs[j]->MakeLink(cn->Inputs[j], an->Outputs[pid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef IShaderGraph_h__
|
||||
#define IShaderGraph_h__
|
||||
|
||||
#include "shaders/IShaderGraphNodeFactory.h"
|
||||
#include "delegate/Delegate.h"
|
||||
#include <vector>
|
||||
#include <IMemoryStream.h>
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class IShaderGraph
|
||||
{
|
||||
public:
|
||||
EVENT1(GraphEvent, IShaderGraphNode*);
|
||||
GraphEvent Event_AddNode;
|
||||
|
||||
IShaderGraph(IShaderGraphNodeFactory* factory);
|
||||
~IShaderGraph();
|
||||
IShaderGraphNode* AddNode(const String& name);
|
||||
bool DeleteNode(int id);
|
||||
void Serialize(LifeCore::IMemoryStream* stm);
|
||||
bool Deserialize(LifeCore::IMemoryStream* stm);
|
||||
void SerializeXML(LifeCore::IMemoryStream* stm);
|
||||
bool DeserializeXML(LifeCore::IMemoryStream* stm);
|
||||
IShaderGraphNode* GetNodeByID(int id);
|
||||
IShaderGraphNode* GetNodeByArrayID(int id);
|
||||
size_t GetNodeCount();
|
||||
void Clear();
|
||||
private:
|
||||
int texture_slots[16];
|
||||
int last_id;
|
||||
int GrabTextureSlot();
|
||||
int GetID(){return last_id++;}
|
||||
IShaderGraphNodeFactory* pFactory;
|
||||
typedef std::vector<IShaderGraphNode*> NodeCollection;
|
||||
typedef std::vector<IShaderGraphNode*>::iterator NodeCollectionIt;
|
||||
NodeCollection Nodes;
|
||||
};
|
||||
}
|
||||
#endif // IShaderGraph_h__
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef IShaderGraphCompiler_h__
|
||||
#define IShaderGraphCompiler_h__
|
||||
|
||||
#include "shaders/IShaderGraphNode.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
enum IShaderCompilerFlags
|
||||
{
|
||||
SCF_NONE = 0,
|
||||
SCF_SKINNING = 1,
|
||||
};
|
||||
|
||||
static int ShaderTypeToChannelCount(IShaderDataType t)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case DT_ANY:
|
||||
return 0;
|
||||
case DT_FLOAT:
|
||||
return 1;
|
||||
case DT_FLOAT2:
|
||||
return 2;
|
||||
case DT_FLOAT3:
|
||||
return 3;
|
||||
case DT_FLOAT4:
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static IShaderDataType MaxType(IShaderDataType t1, IShaderDataType t2)
|
||||
{
|
||||
return ShaderTypeToChannelCount(t1) > ShaderTypeToChannelCount(t2) ? t1 : t2;
|
||||
}
|
||||
|
||||
struct ShaderTextureMapping
|
||||
{
|
||||
int reg;
|
||||
int nodeId;
|
||||
String name;
|
||||
};
|
||||
struct ShaderConstantMapping
|
||||
{
|
||||
String name;
|
||||
IShaderDataType DataType;
|
||||
int size;
|
||||
int offset;
|
||||
};
|
||||
struct ShaderConstantTable
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct ShaderInputInfo
|
||||
{
|
||||
std::vector<ShaderTextureMapping> Textures;
|
||||
void Clear()
|
||||
{
|
||||
Textures.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class IShaderGraphCompiler
|
||||
{
|
||||
public:
|
||||
virtual void CompileNode(IShaderGraphNode* rootNode, int flags, String& ps, String& vs, ShaderInputInfo* info) = 0;
|
||||
};
|
||||
}
|
||||
#endif // IShaderGraphCompiler_h__
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <shaders/IShaderGraphNode.h>
|
||||
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
IShaderGraphNode::IShaderGraphNode()
|
||||
:checked(false), resource_id(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool IShaderGraphNode::Serialize(LifeCore::IMemoryStream* stm)
|
||||
{
|
||||
return IPropertyHolder::Serialize(stm);
|
||||
}
|
||||
bool IShaderGraphNode::Deserialize(LifeCore::IMemoryStream* stm)
|
||||
{
|
||||
return IPropertyHolder::Deserialize(stm);
|
||||
}
|
||||
IShaderGraphNodePort* IShaderGraphNode::GetInputPort(size_t id)
|
||||
{
|
||||
return Inputs[id];
|
||||
}
|
||||
IShaderGraphNodePort* IShaderGraphNode::GetInputPortByName(const String& name)
|
||||
{
|
||||
size_t cnt = Inputs.size();
|
||||
|
||||
for(size_t i = 0; i < cnt; i++){
|
||||
if(Inputs[i]->Name == name)
|
||||
return Inputs[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IShaderGraphNodePort* IShaderGraphNode::GetOutputPortByName(const String& name)
|
||||
{
|
||||
size_t cnt = Outputs.size();
|
||||
|
||||
for(size_t i = 0; i < cnt; i++){
|
||||
if(Outputs[i]->Name == name)
|
||||
return Outputs[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
IShaderGraphNodePort* IShaderGraphNode::GetOutputPortByID(size_t id){
|
||||
size_t cnt = Outputs.size();
|
||||
if(id < cnt){
|
||||
return Outputs[id];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
size_t IShaderGraphNode::GetOutputID(IShaderGraphNodePort* port)
|
||||
{
|
||||
for(size_t i = 0; i < Outputs.size(); i++){
|
||||
if(Outputs[i] == port)
|
||||
return i;
|
||||
}
|
||||
return 100500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef IShaderGraphNode_h__
|
||||
#define IShaderGraphNode_h__
|
||||
|
||||
#include <LString.h>
|
||||
#include "IShaderTypes.h"
|
||||
#include <vector>
|
||||
#include "IPropertyHolder.h"
|
||||
#include <delegate/Delegate.h>
|
||||
#include "shaders/IShaderGraphNodePort.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class IShaderGraphNode : public LifeCore::IPropertyHolder
|
||||
{
|
||||
public:
|
||||
int resource_id;
|
||||
ShaderNodeType NodeType;
|
||||
String Name;
|
||||
bool checked;
|
||||
int id;
|
||||
typedef std::vector<IShaderGraphNodePort*> PortCollection;
|
||||
typedef std::vector<IShaderGraphNodePort*>::iterator PortCollectionItr;
|
||||
PortCollection Inputs;
|
||||
PortCollection Outputs;
|
||||
IShaderGraphNode();
|
||||
IShaderGraphNodePort* GetInputPortByName(const String& name);
|
||||
IShaderGraphNodePort* GetInputPort(size_t id);
|
||||
IShaderGraphNodePort* GetOutputPortByName(const String& name);
|
||||
IShaderGraphNodePort* GetOutputPortByID(size_t id);
|
||||
bool Serialize(LifeCore::IMemoryStream* stm);
|
||||
bool Deserialize(LifeCore::IMemoryStream* stm);
|
||||
size_t GetOutputID(IShaderGraphNodePort* port);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // IShaderGraphNode_h__
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "shaders/IShaderGraphNodeFactory.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
void IShaderGraphNodeFactory::RegisterNode(const String& name, NodeFactoryFunc func)
|
||||
{
|
||||
if(FactoryFuncs.find(name) != FactoryFuncs.end())
|
||||
return;
|
||||
FactoryFuncs[name] = func;
|
||||
}
|
||||
IShaderGraphNode* IShaderGraphNodeFactory::Build(const String& name)
|
||||
{
|
||||
if(FactoryFuncs.find(name) == FactoryFuncs.end())
|
||||
return 0;
|
||||
IShaderGraphNode* n = FactoryFuncs[name]();
|
||||
n->Name = name;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef IShaderGraphNodeFactory_h__
|
||||
#define IShaderGraphNodeFactory_h__
|
||||
|
||||
#include "shaders/IShaderGraphNode.h"
|
||||
#include <hash_map>
|
||||
#include <Singleton.h>
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class IShaderGraphNodeFactory;
|
||||
class IShaderGraphNodeFactory : public Singleton<IShaderGraphNodeFactory>
|
||||
{
|
||||
public:
|
||||
friend class Singleton<IShaderGraphNodeFactory>;
|
||||
typedef IShaderGraphNode* (*NodeFactoryFunc)();
|
||||
void RegisterNode(const String& name, NodeFactoryFunc func);
|
||||
IShaderGraphNode* Build(const String& name);
|
||||
private:
|
||||
IShaderGraphNodeFactory(){}
|
||||
typedef std::hash_map<String, NodeFactoryFunc> FactoryArray;
|
||||
FactoryArray FactoryFuncs;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // IShaderGraphNodeFactory_h__
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "shaders/IShaderGraphNodePort.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
IShaderGraphNodePort::IShaderGraphNodePort(IShaderGraphNode* parent)
|
||||
:Parent(parent)
|
||||
{
|
||||
assert(parent != nullptr && "Shader graph node port parent is nullptr!");
|
||||
}
|
||||
|
||||
IShaderGraphNodePort* IShaderGraphNodePort::GetLink(size_t id)
|
||||
{
|
||||
return links[id];
|
||||
}
|
||||
size_t IShaderGraphNodePort::GetLinkCount()
|
||||
{
|
||||
return links.size();
|
||||
}
|
||||
void IShaderGraphNodePort::MakeLink(IShaderGraphNodePort* input, IShaderGraphNodePort* output)
|
||||
{
|
||||
// assert(target != nullptr && "Failed on add link on IShaderGraphNodePort");
|
||||
if(!input->IsLinkExists(output))
|
||||
input->links.push_back(output);
|
||||
|
||||
if(!output->IsLinkExists(input))
|
||||
output->links.push_back(input);
|
||||
}
|
||||
bool IShaderGraphNodePort::IsLinkExists(IShaderGraphNodePort* target)
|
||||
{
|
||||
for(LinkCollectonItr it = links.begin(); it != links.end(); ++it)
|
||||
{
|
||||
if(*it == target)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void IShaderGraphNodePort::BreakLink()
|
||||
{
|
||||
//remove self from remote ports
|
||||
for(LinkCollectonItr it = links.begin(); it != links.end(); ++it) {
|
||||
(*it)->RemoveLink(this);
|
||||
}
|
||||
//clear list of remote ports
|
||||
links.clear();
|
||||
}
|
||||
void IShaderGraphNodePort::RemoveLink(IShaderGraphNodePort* target)
|
||||
{
|
||||
for(LinkCollectonItr it = links.begin(); it != links.end(); ++it)
|
||||
{
|
||||
IShaderGraphNodePort* lnk = *it;
|
||||
if(lnk == target){
|
||||
links.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef IShaderGraphNodePort_h__
|
||||
#define IShaderGraphNodePort_h__
|
||||
|
||||
#include "IShaderTypes.h"
|
||||
#include <vector>
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class IShaderGraphNode;
|
||||
class IShaderGraphNodePort
|
||||
{
|
||||
public:
|
||||
void MakeLink(IShaderGraphNodePort* input, IShaderGraphNodePort* output);
|
||||
IShaderGraphNodePort* GetLink(size_t id);
|
||||
size_t GetLinkCount();
|
||||
bool IsLinkExists(IShaderGraphNodePort* target);
|
||||
void BreakLink();
|
||||
IShaderGraphNodePort(IShaderGraphNode* parent);
|
||||
IShaderGraphNode* Parent;
|
||||
String Name;
|
||||
String Value;
|
||||
IShaderDataType DataType;
|
||||
private:
|
||||
void RemoveLink(IShaderGraphNodePort* target);
|
||||
typedef std::vector<IShaderGraphNodePort*> LinkCollecton;
|
||||
typedef std::vector<IShaderGraphNodePort*>::iterator LinkCollectonItr;
|
||||
LinkCollecton links;
|
||||
};
|
||||
}
|
||||
#endif // IShaderGraphNodePort_h__
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef IShaderTypes_h__
|
||||
#define IShaderTypes_h__
|
||||
|
||||
#include <Types.h>
|
||||
|
||||
enum IShaderDataType
|
||||
{
|
||||
DT_ANY,
|
||||
DT_FLOAT,
|
||||
DT_FLOAT2,
|
||||
DT_FLOAT3,
|
||||
DT_FLOAT4,
|
||||
};
|
||||
|
||||
enum ShaderNodeType
|
||||
{
|
||||
NT_CONST,
|
||||
NT_OP,
|
||||
NT_RES,
|
||||
NT_MATERIAL
|
||||
};
|
||||
#endif // IShaderTypes_h__
|
||||
@@ -0,0 +1,520 @@
|
||||
#include "shaders/ShaderGraphCompilerHLSL.h"
|
||||
#include <IProperty.h>
|
||||
#include <Property.h>
|
||||
#include <math/LifeMath.h>
|
||||
#include <Utils.h>
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
ShaderGraphCompilerHLSL::ShaderGraphCompilerHLSL()
|
||||
:var_id(0)
|
||||
{
|
||||
}
|
||||
String ShaderGraphCompilerHLSL::NewVarName(const String& baseName)
|
||||
{
|
||||
char tmp[32];
|
||||
itoa(var_id, &tmp[0], 10);
|
||||
var_id++;
|
||||
return baseName + String(tmp);
|
||||
}
|
||||
String ShaderGraphCompilerHLSL::TypeToStr(IShaderDataType t)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case DT_FLOAT:
|
||||
return STR("float");
|
||||
case DT_FLOAT2:
|
||||
return STR("float2");
|
||||
case DT_FLOAT3:
|
||||
return STR("float3");
|
||||
case DT_FLOAT4:
|
||||
return STR("float4");
|
||||
default:
|
||||
return STR("ERROR_TYPE");
|
||||
}
|
||||
}
|
||||
void ShaderGraphCompilerHLSL::ExposeNode(String& shader, String& resources, IShaderGraphNode* node)
|
||||
{
|
||||
if(node->checked)
|
||||
return;
|
||||
|
||||
node->checked = true;
|
||||
//TCHAR* tmp = new TCHAR[128];
|
||||
TCHAR tmp[1024];
|
||||
//constant values
|
||||
if(node->NodeType == NT_CONST)
|
||||
{
|
||||
if(node->Name == STR("ConstFloat1"))
|
||||
{
|
||||
String constName = NewVarName(node->Name);
|
||||
node->Outputs[0]->Value = constName;
|
||||
|
||||
LifeCore::IProperty* valueProp;
|
||||
if(!node->GetPropertyByAttribute(STR("Name"), STR("Value"), &valueProp))
|
||||
{
|
||||
printf("Failed to get \"Value\" Property from Float1 node!\n");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
String s = valueProp->ToString();
|
||||
sprintf(&tmp[0], "float %s = %sf;\n", constName.c_str(), s.c_str());
|
||||
shader = String(tmp) + shader;
|
||||
}
|
||||
else if(node->Name == STR("ConstFloat2"))
|
||||
{
|
||||
String constName = NewVarName(node->Name);
|
||||
node->Outputs[0]->Value = constName;
|
||||
|
||||
LifeCore::IProperty* valueProp;
|
||||
if(!node->GetPropertyByAttribute(STR("Name"), STR("Value"), &valueProp))
|
||||
{
|
||||
printf("Failed to get \"Value\" Property from Float1 node!\n");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
LifeCore::Property<LifeMath::float2>* prop_src = (LifeCore::Property<LifeMath::float2>*)valueProp;
|
||||
|
||||
sprintf(&tmp[0], "float2 %s = float2(%ff, %ff);\n", constName.c_str(), (*prop_src)().X, (*prop_src)().Y);
|
||||
shader = String(tmp) + shader;
|
||||
}
|
||||
else if(node->Name == STR("ConstFloat3"))
|
||||
{
|
||||
String constName = NewVarName(node->Name);
|
||||
node->Outputs[0]->Value = constName;
|
||||
|
||||
LifeCore::IProperty* valueProp;
|
||||
if(!node->GetPropertyByAttribute(STR("Name"), STR("Value"), &valueProp))
|
||||
{
|
||||
printf("Failed to get \"Value\" Property from Float1 node!\n");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
LifeCore::Property<LifeMath::Vec3f>* prop_src = (LifeCore::Property<LifeMath::Vec3f>*)valueProp;
|
||||
|
||||
|
||||
sprintf(&tmp[0], "float3 %s = float3(%ff, %ff, %ff);\n", constName.c_str(), (*prop_src)().X, (*prop_src)().Y, (*prop_src)().Z);
|
||||
shader = String(tmp) + shader;
|
||||
}
|
||||
else if(node->Name == STR("ConstFloat4"))
|
||||
{
|
||||
String constName = NewVarName(node->Name);
|
||||
node->Outputs[0]->Value = constName;
|
||||
|
||||
LifeCore::IProperty* valueProp;
|
||||
if(!node->GetPropertyByAttribute(STR("Name"), STR("Value"), &valueProp))
|
||||
{
|
||||
printf("Failed to get \"Value\" Property from Float1 node!\n");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
LifeCore::Property<LifeMath::Vec4f>* prop_src = (LifeCore::Property<LifeMath::Vec4f>*)valueProp;
|
||||
|
||||
|
||||
sprintf(&tmp[0], "float4 %s = float4(%ff, %ff, %ff, %ff);\n", constName.c_str(), (*prop_src)().X, (*prop_src)().Y, (*prop_src)().Z, (*prop_src)().W);
|
||||
shader = String(tmp) + shader;
|
||||
}
|
||||
else if(node->Name == STR("Time"))
|
||||
{
|
||||
String constName = NewVarName(node->Name);
|
||||
node->Outputs[0]->Value = STR("sceneTime.xxxx");
|
||||
node->Outputs[1]->Value = STR("sceneTime.x");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(node->Name == STR("OpAdd"))
|
||||
{
|
||||
if(!node->Inputs[0]->GetLinkCount() || !node->Inputs[1]->GetLinkCount()){
|
||||
shader = String("ERROR_EXPRESSION") + shader; return;}
|
||||
|
||||
String top1;
|
||||
String top2;
|
||||
//Exposing connected nodes
|
||||
ExposeNode(top1, resources, node->Inputs[0]->GetLink(0)->Parent);
|
||||
ExposeNode(top2, resources, node->Inputs[1]->GetLink(0)->Parent);
|
||||
|
||||
String tn = TypeToStr(MaxType(node->Inputs[0]->GetLink(0)->DataType, node->Inputs[1]->GetLink(0)->DataType));
|
||||
String cn = NewVarName(node->Name);
|
||||
sprintf(&tmp[0], "%s %s = ((%s) + (%s));", tn.c_str(), cn.c_str(), node->Inputs[0]->GetLink(0)->Value.c_str(),
|
||||
node->Inputs[1]->GetLink(0)->Value.c_str());
|
||||
node->Outputs[0]->DataType = MaxType(node->Inputs[0]->GetLink(0)->DataType, node->Inputs[1]->GetLink(0)->DataType);
|
||||
shader = top1 + top2 + String(tmp) + shader;
|
||||
|
||||
node->Outputs[0]->Value = cn;
|
||||
}
|
||||
else if(node->Name == STR("OpLerp"))
|
||||
{
|
||||
if(!node->Inputs[0]->GetLinkCount() || !node->Inputs[1]->GetLinkCount() || !node->Inputs[2]->GetLinkCount()){
|
||||
shader = String("ERROR_EXPRESSION") + shader; return;}
|
||||
|
||||
String top1;
|
||||
String top2;
|
||||
String top3;
|
||||
//Exposing connected nodes
|
||||
ExposeNode(top1, resources, node->Inputs[0]->GetLink(0)->Parent);
|
||||
ExposeNode(top2, resources, node->Inputs[1]->GetLink(0)->Parent);
|
||||
ExposeNode(top3, resources, node->Inputs[2]->GetLink(0)->Parent);
|
||||
|
||||
String tn = TypeToStr(MaxType(node->Inputs[0]->GetLink(0)->DataType, node->Inputs[1]->GetLink(0)->DataType));
|
||||
String cn = NewVarName(node->Name);
|
||||
sprintf(&tmp[0], "%s %s = lerp((%s),(%s),(%s));", tn.c_str(), cn.c_str(), node->Inputs[0]->GetLink(0)->Value.c_str(),
|
||||
node->Inputs[1]->GetLink(0)->Value.c_str(), node->Inputs[2]->GetLink(0)->Value.c_str());
|
||||
node->Outputs[0]->DataType = MaxType(node->Inputs[0]->GetLink(0)->DataType, node->Inputs[1]->GetLink(0)->DataType);
|
||||
shader = top1 + top2 + top3 + String(tmp) + shader;
|
||||
|
||||
node->Outputs[0]->Value = cn;
|
||||
}
|
||||
else if(node->Name == STR("SrcTex2D"))
|
||||
{
|
||||
//check UV input slot
|
||||
if(!node->Inputs[0]->GetLinkCount()){
|
||||
shader = String("ERROR_EXPRESSION") + shader; return;}
|
||||
|
||||
String top1;
|
||||
ExposeNode(top1, resources, node->Inputs[0]->GetLink(0)->Parent);
|
||||
//String tn = TypeToStr(node->Inputs[0]->Link->DataType);
|
||||
String cn = NewVarName(node->Name);
|
||||
node->resource_id = lastTexSlot;
|
||||
|
||||
//generate header's texture definition
|
||||
sprintf(&tmp[0], "Texture2D SrcTexture2D%i : register(t%i);\n", lastTexSlot, lastTexSlot);
|
||||
//write texture definition to the shader's header
|
||||
ShaderTextureMapping mapping;
|
||||
mapping.reg = node->resource_id;
|
||||
mapping.name = String("SrcTexture2D") + Int32ToString(node->resource_id);
|
||||
mapping.nodeId = node->id;
|
||||
inputInfo.Textures.push_back(mapping);
|
||||
|
||||
resources += String(tmp);
|
||||
|
||||
sprintf(&tmp[0], "float4 %s = SrcTexture2D%i.Sample(linearSampler, %s);\n", cn.c_str(), node->resource_id, node->Inputs[0]->GetLink(0)->Value.c_str());
|
||||
shader = top1 + String(tmp) + shader;
|
||||
|
||||
node->Outputs[0]->Value = cn + STR(".xyzw");
|
||||
node->Outputs[1]->Value = cn + STR(".xxxx");
|
||||
node->Outputs[2]->Value = cn + STR(".yyyy");
|
||||
node->Outputs[3]->Value = cn + STR(".zzzz");
|
||||
node->Outputs[4]->Value = cn + STR(".wwww");
|
||||
|
||||
lastTexSlot++;
|
||||
}
|
||||
else if(node->Name == STR("SrcUV"))
|
||||
{
|
||||
LifeCore::IProperty* channelProp;
|
||||
if(!node->GetPropertyByAttribute(STR("Name"), STR("Channel"), &channelProp))
|
||||
{
|
||||
printf("Failed to get \"Channel\" Property from UV node!\n");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
node->Outputs[0]->Value = STR("Input.Texcoord") + channelProp->ToString() + STR(".xy");
|
||||
}
|
||||
else if(node->Name == STR("DecodeNormal"))
|
||||
{
|
||||
String top1;
|
||||
ExposeNode(top1, resources, node->Inputs[0]->GetLink(0)->Parent);
|
||||
|
||||
String cn = NewVarName(node->Name);
|
||||
sprintf(&tmp[0], "float3 %s = normalize(((%s).xyz * 2.0f) - 1.0f);", cn.c_str(), node->Inputs[0]->GetLink(0)->Value.c_str());
|
||||
String src1(tmp);
|
||||
|
||||
sprintf(&tmp[0], "%s = normalize((%s).x * normalize(Input.Tangent) + (%s).y * normalize(Input.Binormal) + (%s).z * normalize(Input.Normal.xyz));", cn.c_str(), cn.c_str(),cn.c_str(),cn.c_str());
|
||||
String src2(tmp);
|
||||
|
||||
sprintf(&tmp[0], "%s = (%s).xyz * 0.5f + 0.5f;", cn.c_str(), cn.c_str());
|
||||
|
||||
String src3(tmp);
|
||||
|
||||
shader = top1 + src1 + src2 + src3 + shader;
|
||||
|
||||
node->Outputs[0]->Value = cn;
|
||||
/*
|
||||
float3 n = normalize(nn.x * normalize(Input.Tangent) + nn.y * normalize(Input.Binormal) + nn.z * normalize(Input.Normal.xyz));
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = String("ERROR_EXPRESSION") + shader;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// delete[] tmp;
|
||||
}
|
||||
void ShaderGraphCompilerHLSL::RemoveChecked(IShaderGraphNode* node)
|
||||
{
|
||||
node->checked = false;
|
||||
for(IShaderGraphNode::PortCollectionItr it = node->Inputs.begin(); it != node->Inputs.end(); ++it)
|
||||
{
|
||||
IShaderGraphNodePort* port = *it; //my input port
|
||||
|
||||
|
||||
if(port->GetLinkCount())
|
||||
{
|
||||
RemoveChecked(port->GetLink(0)->Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ShaderGraphCompilerHLSL::CompileNode(IShaderGraphNode* rootNode, int flags, String& ps, String& vs, ShaderInputInfo* info)
|
||||
{
|
||||
//remove "checked" flag from all nodes
|
||||
lastTexSlot = 0;
|
||||
|
||||
inputInfo.Clear();
|
||||
RemoveChecked(rootNode);
|
||||
|
||||
String per_object_cb = "cbuffer perObjectData : register(b0){row_major matrix mWorld;};\n";
|
||||
String per_camera_cb =
|
||||
"cbuffer perCameraData : register(b1)\n" \
|
||||
"{\n" \
|
||||
" row_major matrix matView;\n" \
|
||||
" row_major matrix matProjection;\n" \
|
||||
" row_major matrix matVP;\n" \
|
||||
" float4 camPos;\n" \
|
||||
" float4 camDir;\n" \
|
||||
" float4 camNearFarVPWH;\n" \
|
||||
" float4 corners[4];\n" \
|
||||
"};\n";
|
||||
|
||||
/*per_camera_cb +=
|
||||
"cbuffer materialData : register(b2){\n" \
|
||||
"float shininess : packoffset(c0.x);\n" \
|
||||
"float specularPower : packoffset(c0.y);\n" \
|
||||
"float2 materialDummy : packoffset(c0.z);};\n";*/
|
||||
|
||||
per_camera_cb +=
|
||||
"cbuffer sceneData : register(b3){\n" \
|
||||
"float sceneTime : packoffset(c0.x);\n" \
|
||||
"float3 sceneAmbient : packoffset(c0.y);};\n";
|
||||
|
||||
String shader;
|
||||
String resources;
|
||||
|
||||
resources +=
|
||||
"SamplerState linearSampler : register(s0);\n" \
|
||||
"SamplerState pointSampler : register(s1);\n";
|
||||
|
||||
if(rootNode->Name != STR("Material"))
|
||||
return;
|
||||
|
||||
int inSlotCount = rootNode->Inputs.size();
|
||||
|
||||
String diffuse_code;
|
||||
String normal_code;
|
||||
String specular_code;
|
||||
String specular_power_code;
|
||||
|
||||
for(int i = 0; i < inSlotCount; i++)
|
||||
{
|
||||
String shader_tmp;
|
||||
IShaderGraphNodePort* port = rootNode->Inputs[i];
|
||||
|
||||
if(port->Name == STR("Diffuse"))
|
||||
{
|
||||
if(port->GetLinkCount())
|
||||
{
|
||||
ExposeNode(shader_tmp, resources, port->GetLink(0)->Parent);
|
||||
diffuse_code = port->GetLink(0)->Value;
|
||||
}
|
||||
}
|
||||
else if(port->Name == STR("Normal"))
|
||||
{
|
||||
if(port->GetLinkCount())
|
||||
{
|
||||
ExposeNode(shader_tmp, resources, port->GetLink(0)->Parent);
|
||||
normal_code = port->GetLink(0)->Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
normal_code = "(Input.Normal * 0.5f + 0.5f)";
|
||||
}
|
||||
}
|
||||
else if(port->Name == STR("Specular"))
|
||||
{
|
||||
if(port->GetLinkCount())
|
||||
{
|
||||
ExposeNode(shader_tmp, resources, port->GetLink(0)->Parent);
|
||||
specular_code = port->GetLink(0)->Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
specular_code = STR("0.0f");
|
||||
}
|
||||
}
|
||||
else if(port->Name == STR("SpecularPower"))
|
||||
{
|
||||
if(port->GetLinkCount())
|
||||
{
|
||||
ExposeNode(shader_tmp, resources, port->GetLink(0)->Parent);
|
||||
specular_power_code = port->GetLink(0)->Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
specular_power_code = STR("0.0f");
|
||||
}
|
||||
}
|
||||
|
||||
shader = shader + shader_tmp + STR("\n");
|
||||
}
|
||||
|
||||
String ps_input_struct =
|
||||
"struct PS_INPUT \n" \
|
||||
"{\n"\
|
||||
" float4 Position : SV_Position;\n"\
|
||||
" float2 Texcoord0 : TEXCOORD0;\n"\
|
||||
" float4 Normal : TEXCOORD1;\n"\
|
||||
" float3 wPos : TEXCOORD2;\n"\
|
||||
" float3 Tangent : TEXCOORD3;\n"\
|
||||
" float3 Binormal : TEXCOORD4;\n"\
|
||||
" float4 ePos : TEXCOORD5;\n"\
|
||||
"};\n";
|
||||
|
||||
String ps_output_struct =
|
||||
"struct PS_OUT\n" \
|
||||
"{\n" \
|
||||
" float4 color0 : SV_Target0;\n" \
|
||||
" float4 color1 : SV_Target1;\n" \
|
||||
" float2 color2 : SV_Target2;\n" \
|
||||
"};\n";
|
||||
|
||||
String final;
|
||||
|
||||
String func =
|
||||
"PS_OUT main_PS( PS_INPUT Input )\n{\n"\
|
||||
"PS_OUT output;\nfloat dist = length(Input.wPos - camPos);\nfloat ez = Input.Normal.w / camNearFarVPWH.y;\n";
|
||||
func +=
|
||||
"Input.Tangent.x*=-1; Input.Binormal.x*=-1;\n";
|
||||
|
||||
String out_albedo_refl =
|
||||
"//albedo and reflection\noutput.color0 = float4((";
|
||||
out_albedo_refl = out_albedo_refl + diffuse_code + STR(").xyz,") + specular_code + STR(");\n");
|
||||
|
||||
String out_normal_gloss =
|
||||
"//normal and glossiness\noutput.color1 = float4((";
|
||||
out_normal_gloss = out_normal_gloss + normal_code + STR(").xyz,") + specular_power_code + STR(");\n");
|
||||
|
||||
String out_depth =
|
||||
"//depth info\noutput.color2 = float2(dist, ez);\n";
|
||||
|
||||
final = resources + per_object_cb + per_camera_cb + ps_input_struct + ps_output_struct + func + shader + out_albedo_refl + out_normal_gloss + out_depth + String("return output;\n}\n");
|
||||
|
||||
ps = final;
|
||||
|
||||
//generate vertex shader
|
||||
String shader_vs;
|
||||
|
||||
//per object constant buffer
|
||||
|
||||
shader_vs += per_object_cb;
|
||||
|
||||
//per camera constant buffer
|
||||
|
||||
shader_vs += per_camera_cb;
|
||||
|
||||
//bones constant buffer (only for skinned meshes)
|
||||
if((flags & SCF_SKINNING) != 0)
|
||||
{
|
||||
shader_vs +=
|
||||
"cbuffer skinData : register(b5)\n" \
|
||||
"{row_major matrix boneMatrix[MAX_BONES_COUNT];};\n";
|
||||
}
|
||||
|
||||
//vertex shader input data structure
|
||||
shader_vs +=
|
||||
"struct VS_INPUT {\n" \
|
||||
"float4 Position : POSITION;\n" \
|
||||
"float2 Texcoord : TEXCOORD;\n" \
|
||||
"float3 Normal : NORMAL;\n" \
|
||||
"float3 Tangent : TANGENT;\n" \
|
||||
"float3 Binormal : BINORMAL;\n";
|
||||
|
||||
//add skinning info
|
||||
if((flags & SCF_SKINNING) != 0)
|
||||
{
|
||||
shader_vs +=
|
||||
"float4 BlendIndices : BLENDINDICES;\n" \
|
||||
"float4 BlendWeights : BLENDWEIGHT;\n";
|
||||
}
|
||||
//close structure
|
||||
shader_vs += "};\n";
|
||||
|
||||
//shader output data structure
|
||||
shader_vs +=
|
||||
"struct VS_OUTPUT \n" \
|
||||
"{\n" \
|
||||
" float4 Position : SV_Position;\n" \
|
||||
" float2 Texcoord : TEXCOORD0;\n" \
|
||||
" float4 Normal : TEXCOORD1;\n" \
|
||||
" float3 wPos : TEXCOORD2;\n" \
|
||||
" float3 Tangent : TEXCOORD3;\n" \
|
||||
" float3 Binormal : TEXCOORD4;\n" \
|
||||
" float4 ePos : TEXCOORD5;\n" \
|
||||
"};\n";
|
||||
|
||||
//add skinning function for skinned meshes
|
||||
if((flags & SCF_SKINNING) != 0)
|
||||
{
|
||||
shader_vs +=
|
||||
"float4 SkinVertex(float4 position, float4 index, float4 weight)\n" \
|
||||
"{\n" \
|
||||
" float4 pos = float4(0,0,0,0);\n" \
|
||||
" int IndexArray[4] = (int[4])(index);\n" \
|
||||
" float WeightArray[4] = (float[4])(weight);\n" \
|
||||
" float LastWeight = 0.0f;\n" \
|
||||
" int nb = 0;\n" \
|
||||
" for(int i = 0; i < 4;i++)\n" \
|
||||
" {\n" \
|
||||
" if(WeightArray[i]==0)\n" \
|
||||
" {\n" \
|
||||
" nb = i;\n" \
|
||||
" }\n" \
|
||||
" LastWeight = LastWeight + WeightArray[i];\n" \
|
||||
" pos = pos + mul(position, boneMatrix[IndexArray[i]] * WeightArray[i]);\n" \
|
||||
" }\n" \
|
||||
" pos = pos + mul(position, boneMatrix[IndexArray[nb]]* (1.0f - LastWeight));\n" \
|
||||
" return pos;\n" \
|
||||
"}\n";
|
||||
}
|
||||
|
||||
//main vertex shader function
|
||||
|
||||
//function header
|
||||
shader_vs +=
|
||||
"VS_OUTPUT main_VS( VS_INPUT Input ){\n" \
|
||||
"VS_OUTPUT Output = (VS_OUTPUT)0;\n";
|
||||
|
||||
//vertex transformation (skinned/not skinned)
|
||||
if((flags & SCF_SKINNING) != 0) //skinned
|
||||
{
|
||||
shader_vs +=
|
||||
"Output.Position = SkinVertex(Input.Position, Input.BlendIndices, Input.BlendWeights);\n" \
|
||||
"Output.wPos = mul(float4(Output.Position.xyz, 1.0f), mWorld);\n" \
|
||||
"Output.Position = mul(float4(Output.wPos.xyz, 1.0f), matVP);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_vs +=
|
||||
"Output.wPos = mul(float4(Input.Position.xyz, 1.0f), mWorld); \n" \
|
||||
"Output.Position = mul(float4(Output.wPos.xyz, 1.0f), matVP); \n";
|
||||
}
|
||||
|
||||
//tail
|
||||
shader_vs +=
|
||||
"Output.Texcoord = Input.Texcoord;\n" \
|
||||
"float3x3 mWorldNT = (float3x3)mWorld;\n" \
|
||||
"Output.ePos = Output.Position;\n" \
|
||||
"Output.Normal = float4(mul(Input.Normal, mWorldNT), mul(float4(Output.wPos, 1.0f), matView).z);\n" \
|
||||
"Output.Tangent = mul(Input.Tangent, mWorldNT);\n" \
|
||||
"Output.Binormal = mul(Input.Binormal, mWorldNT);\n" \
|
||||
|
||||
"return Output;\n" \
|
||||
"}\n";
|
||||
|
||||
vs = shader_vs;
|
||||
|
||||
|
||||
*info = inputInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef ShaderGraphCompilerHLSL_h__
|
||||
#define ShaderGraphCompilerHLSL_h__
|
||||
|
||||
#include "shaders/IShaderGraphCompiler.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class ShaderGraphCompilerHLSL : public IShaderGraphCompiler
|
||||
{
|
||||
public:
|
||||
ShaderGraphCompilerHLSL();
|
||||
void CompileNode(IShaderGraphNode* rootNode, int flags, String& ps, String& vs, ShaderInputInfo* info);
|
||||
private:
|
||||
ShaderInputInfo inputInfo;
|
||||
int lastTexSlot;
|
||||
void RemoveChecked(IShaderGraphNode* node);
|
||||
String NewVarName(const String& baseName);
|
||||
int var_id;
|
||||
void ExposeNode(String& shader, String& resources, IShaderGraphNode* node);
|
||||
String TypeToStr(IShaderDataType t);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ShaderGraphCompilerHLSL_h__
|
||||
Reference in New Issue
Block a user