1#include "Shading/ShaderNodes/PBRMaterialNode.h"
7 GLSLFunction DistributionGGX(
"DistributionGGX",
"vec3 N, vec3 H, float roughness",
"float");
8 DistributionGGX.AddLine(
GLSLLine(
"float a = roughness * roughness;"));
9 DistributionGGX.AddLine(
GLSLLine(
"float a2 = a * a;"));
10 DistributionGGX.AddLine(
GLSLLine(
"float NdotH = max(dot(N, H), 0.0f);"));
11 DistributionGGX.AddLine(
GLSLLine(
"float NdotH2 = NdotH * NdotH;"));
12 DistributionGGX.AddLine(
GLSLLine(
"float denom = NdotH2 * (a2 - 1.0) + 1.0;"));
13 DistributionGGX.AddLine(
GLSLLine(
"return a2 / (PI * denom * denom);"));
14 handler->AddFunction(DistributionGGX);
15 GLSLFunction GeometrySchlickGGX(
"GeometrySchlickGGX",
"float NdotV, float roughness",
"float");
16 GeometrySchlickGGX.AddLine(
GLSLLine(
"float r = (roughness + 1.0);"));
17 GeometrySchlickGGX.AddLine(
GLSLLine(
"float k = (r*r) / 8.0;"));
18 GeometrySchlickGGX.AddLine(
GLSLLine(
""));
19 GeometrySchlickGGX.AddLine(
GLSLLine(
"float nom = NdotV;"));
20 GeometrySchlickGGX.AddLine(
GLSLLine(
"float denom = NdotV * (1.0 - k) + k;"));
21 GeometrySchlickGGX.AddLine(
GLSLLine(
""));
22 GeometrySchlickGGX.AddLine(
GLSLLine(
"return nom / denom;"));
23 handler->AddFunction(GeometrySchlickGGX);
24 GLSLFunction GeometrySmith(
"GeometrySmith",
"vec3 N, vec3 V, vec3 L, float roughness",
"float");
25 GeometrySmith.AddLine(
GLSLLine(
"float NdotV = max(dot(N, V), 0.0);"));
26 GeometrySmith.AddLine(
GLSLLine(
"float NdotL = max(dot(N, L), 0.0);"));
28 GeometrySmith.AddLine(
GLSLLine(
"float ggx2 = GeometrySchlickGGX(NdotV, roughness);"));
29 GeometrySmith.AddLine(
GLSLLine(
"float ggx1 = GeometrySchlickGGX(NdotL, roughness);"));
31 GeometrySmith.AddLine(
GLSLLine(
"return ggx1 * ggx2;"));
32 handler->AddFunction(GeometrySmith);
33 GLSLFunction frenselSchlick(
"fresnelSchlick",
"float cosTheta, vec3 F0",
"vec3");
34 frenselSchlick.AddLine(
GLSLLine(
"return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);"));
35 handler->AddFunction(frenselSchlick);
40 LoadPBRFunctions(handler);
41 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"albedo") +
" = vec3(1.0f);",
"The albedo color of the material."));
42 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"normal") +
" = vec3(1.0f);",
"The normal of the material."));
43 function->AddLine(
GLSLLine(
"float " + VAR(
"metallic") +
" = 1.0f;",
"The metalic of the material."));
44 function->AddLine(
GLSLLine(
"float " + VAR(
"roughness") +
" = 1.0f;",
"The roughness of the material."));
45 function->AddLine(
GLSLLine(
"float " + VAR(
"ao") +
" = 1.0f;",
"The ambient occlusion of the material."));
47 if(inputPins[0]->IsLinked())
50 inputPins[0]->other->Evaluate(GetParams(function, &tmp));
51 function->AddLine(
GLSLLine(
"if(" + SDATA(0) +
" == 1.0f)",
"If gamma corection is enabled adjust the texture accordingly."));
52 function->AddLine(
GLSLLine(
"\t" + VAR(
"albedo") +
" = pow(" + tmp.line +
", vec3(gamma));",
"The albedo color of the material."));
53 function->AddLine(
GLSLLine(
"else",
"If gamma corection is disabled just use the texture as it is."));
54 function->AddLine(
GLSLLine(
"\t" + VAR(
"albedo") +
" = " + tmp.line +
";",
"The albedo color of the material."));
57 if(inputPins[1]->IsLinked())
60 inputPins[1]->other->Evaluate(GetParams(function, &tmp));
61 function->AddLine(
GLSLLine(VAR(
"normal") +
" = " + tmp.line +
";",
"The normal map sampled for current fragment"));
62 function->AddLine(
GLSLLine(VAR(
"normal") +
" = TBN * (" + VAR(
"normal") +
" * 2.0f - 1.0f);",
"Scale the normal to -1.0f to 1.0f and transform to tangent space"));
65 if(inputPins[5]->IsLinked())
68 inputPins[5]->other->Evaluate(GetParams(function, &tmp));
69 function->AddLine(
GLSLLine(
"",
"Using the ARM texture for ao, roughness and metalic"));
70 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"tmp") +
" = " + tmp.line +
";",
"Temporatily storing the arm data."));
71 function->AddLine(
GLSLLine(VAR(
"ao") +
" = " + VAR(
"tmp") +
".x;",
"The ambient occlusion of the material."));
72 function->AddLine(
GLSLLine(VAR(
"roughness") +
" = " + VAR(
"tmp") +
".y;",
"The roughness of the material."));
73 function->AddLine(
GLSLLine(VAR(
"metallic") +
" = " + VAR(
"tmp") +
".z;",
"The metalic of the material."));
78 if(inputPins[2]->IsLinked())
81 inputPins[2]->other->Evaluate(GetParams(function, &tmp));
82 function->AddLine(
GLSLLine(VAR(
"metallic") +
" = " + tmp.line +
".x;",
"The metalic of the material."));
85 if(inputPins[3]->IsLinked())
88 inputPins[3]->other->Evaluate(GetParams(function, &tmp));
89 function->AddLine(
GLSLLine(VAR(
"roughness") +
" = " + tmp.line +
".x;",
"The roughness of the material."));
92 if(inputPins[4]->IsLinked())
95 inputPins[4]->other->Evaluate(GetParams(function, &tmp));
96 function->AddLine(
GLSLLine(VAR(
"ao") +
" = " + tmp.line +
".x;",
"The ambient occlusion of the material."));
100 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"N") +
" = " + VAR(
"normal") +
";",
"The normal vector"));
101 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"V") +
" = normalize(_CameraPos - FragPos.xyz);",
"The view vector"));
102 function->AddLine(
GLSLLine(
"",
""));
103 function->AddLine(
GLSLLine(
"",
"Calculate reflectance at normal incidence; if dia-electric (like plastic) use F0"));
104 function->AddLine(
GLSLLine(
"",
"of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)"));
105 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"F0") +
" = vec3(0.04f);",
""));
106 function->AddLine(
GLSLLine(VAR(
"F0") +
" = mix(" + VAR(
"F0") +
", " + VAR(
"albedo") +
", " + VAR(
"metallic") +
" );",
""));
107 function->AddLine(
GLSLLine(
"",
"Reflectance equation"));
108 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"Lo") +
" = vec3(0.0f);",
""));
109 function->AddLine(
GLSLLine(
"// for(int i = 0 ; i < _NumLights ; i++ )",
""));
110 function->AddLine(
GLSLLine(
"// {",
""));
111 function->AddLine(
GLSLLine(
"",
"Calculate per-light radiance"));
112 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"L") +
" = normalize(_LightPosition - FragPos.xyz);",
""));
113 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"H") +
" = normalize(" + VAR(
"V") +
" + " + VAR(
"L") +
");",
""));
114 function->AddLine(
GLSLLine(
"float " + VAR(
"distance") +
" = length( _LightPosition - FragPos.xyz );",
""));
115 function->AddLine(
GLSLLine(
"float " + VAR(
"attenuation") +
" = 1.0f / (" + VAR(
"distance") +
" * " + VAR(
"distance") +
");",
""));
116 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"radiance") +
" = _LightColor * _LightStrength * " + VAR(
"attenuation") +
";",
""));
117 function->AddLine(
GLSLLine(
"",
""));
118 function->AddLine(
GLSLLine(
"",
"Color-Torrance BRDF"));
119 function->AddLine(
GLSLLine(
"float " + VAR(
"NDF") +
" = DistributionGGX(" + VAR(
"N") +
", " + VAR(
"H") +
", " + VAR(
"roughness") +
");",
""));
120 function->AddLine(
GLSLLine(
"float " + VAR(
"G") +
" = GeometrySmith(" + VAR(
"N") +
", " + VAR(
"V") +
", " + VAR(
"L") +
", " + VAR(
"roughness") +
");",
""));
121 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"F") +
" = fresnelSchlick(max(dot(" + VAR(
"H") +
", " + VAR(
"V") +
"), 0.0f), " + VAR(
"F0") +
");",
""));
122 function->AddLine(
GLSLLine(
"",
""));
123 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"numerator") +
" = " + VAR(
"NDF") +
" * " + VAR(
"G") +
" * " + VAR(
"F") +
";",
""));
124 function->AddLine(
GLSLLine(
"float " + VAR(
"denominator") +
" = 4.0f * max(dot(" + VAR(
"N") +
", " + VAR(
"V") +
"), 0.0f) * max(dot(" + VAR(
"N") +
", " + VAR(
"L") +
"), 0.0f) + 0.0001f;",
"+ 0.0001f to prevent divide by zero"));
125 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"specular") +
" = " + VAR(
"numerator") +
" / " + VAR(
"denominator") +
";",
""));
126 function->AddLine(
GLSLLine(
"",
""));
127 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"kS") +
" = " + VAR(
"F") +
";",
"kS is equal to Fresnel"));
128 function->AddLine(
GLSLLine(
"",
""));
129 function->AddLine(
GLSLLine(
"",
"For energy conservation, the diffuse and specular light can't"));
130 function->AddLine(
GLSLLine(
"",
"be above 1.0 (unless the surface emits light); to preserve this"));
131 function->AddLine(
GLSLLine(
"",
"relationship the diffuse component (kD) should equal 1.0 - kS."));
132 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"kD") +
" = vec3(1.0f) - " + VAR(
"kS") +
";",
""));
133 function->AddLine(
GLSLLine(
"",
""));
134 function->AddLine(
GLSLLine(
"",
"Multiply kD by the inverse metalness such that only non-metals"));
135 function->AddLine(
GLSLLine(
"",
"have diffuse lighting, or a linear blend if partly metal (pure metals"));
136 function->AddLine(
GLSLLine(
"",
"have no diffuse light)."));
137 function->AddLine(
GLSLLine(VAR(
"kD") +
" *= 1.0 - " + VAR(
"metallic") +
";",
""));
138 function->AddLine(
GLSLLine(
"",
""));
139 function->AddLine(
GLSLLine(
"",
"Scale light by NdotL"));
140 function->AddLine(
GLSLLine(
"float " + VAR(
"NdotL") +
" = max(dot(" + VAR(
"N") +
", " + VAR(
"L") +
"), 0.0f); ",
""));
141 function->AddLine(
GLSLLine(
"",
""));
142 function->AddLine(
GLSLLine(
"",
"// Add to outgoing radiance Lo"));
143 function->AddLine(
GLSLLine(VAR(
"Lo") +
" += (" + VAR(
"kD") +
" * " + VAR(
"albedo") +
" / PI + " + VAR(
"specular") +
") * " + VAR(
"radiance") +
" * " + VAR(
"NdotL") +
";",
"Note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again"));
144 function->AddLine(
GLSLLine(
"",
""));
145 function->AddLine(
GLSLLine(
"// }",
""));
146 function->AddLine(
GLSLLine(
"",
""));
147 function->AddLine(
GLSLLine(
"",
"Ambient lighting (note that the next IBL tutorial will replace"));
148 function->AddLine(
GLSLLine(
"",
"this ambient lighting with environment lighting)."));
149 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"ambient") +
" = vec3(0.03f) * " + VAR(
"albedo") +
" * " + VAR(
"ao") +
";",
""));
150 function->AddLine(
GLSLLine(
"",
""));
151 function->AddLine(
GLSLLine(
"vec3 " + VAR(
"result") +
" = " + VAR(
"ambient") +
" + " + VAR(
"Lo") +
";",
""));
152 function->AddLine(
GLSLLine(
"",
""));
153 function->AddLine(
GLSLLine(
"if(" + SDATA(1) +
" == 1.0f)",
"If HDR Tonemapping is enable tonemap the result"));
154 function->AddLine(
GLSLLine(
"{",
""));
155 function->AddLine(
GLSLLine(
"\t" + VAR(
"result") +
" = " + VAR(
"result") +
" / (" + VAR(
"result") +
" + vec3(1.0f));",
""));
156 function->AddLine(
GLSLLine(
"}",
""));
157 function->AddLine(
GLSLLine(
"",
""));
158 function->AddLine(
GLSLLine(
"if(" + SDATA(0) +
" == 1.0f)",
"If Gamma Correction is enable gamma correct the result"));
159 function->AddLine(
GLSLLine(
"{",
""));
160 function->AddLine(
GLSLLine(
"\t" + VAR(
"result") +
" = pow(" + VAR(
"result") +
", vec3(1.0f/gamma));",
""));
161 function->AddLine(
GLSLLine(
"}",
""));
162 function->AddLine(
GLSLLine(
"",
""));
163 line->line = VAR(
"result");
168 gammaCorrection = data[
"gammaCorrection"];
169 hdrTonemapping = data[
"hdrTonemapping"];
175 data[
"type"] =
"PBRMaterial";
176 data[
"gammaCorrection"] = gammaCorrection;
177 data[
"hdrTonemapping"] = hdrTonemapping;
181void PBRMaterialNode::UpdateShaders()
183 sharedData->d0 = gammaCorrection ? 1.0f : 0.0f;
184 sharedData->d1 = hdrTonemapping ? 1.0f : 0.0f;
187void PBRMaterialNode::OnRender()
189 DrawHeader(
"PBR Material");
190 inputPins[0]->Render();
192 ImGui::Text(
"Albedo");
194 outputPins[0]->Render();
195 inputPins[1]->Render();
197 ImGui::Text(
"Normal");
198 inputPins[2]->Render();
200 ImGui::Text(
"Metallic");
201 inputPins[3]->Render();
203 ImGui::Text(
"Roughness");
204 inputPins[4]->Render();
207 inputPins[5]->Render();
211 if (ImGui::Checkbox(
"Gamma Correction", &gammaCorrection))
213 sharedData->d0 = gammaCorrection ? 1.0f : 0.0f;
216 if (ImGui::Checkbox(
"HDR Tonemapping", &hdrTonemapping))
218 sharedData->d1 = hdrTonemapping ? 1.0f : 0.0f;
222PBRMaterialNode::PBRMaterialNode(
GLSLHandler *handler)
225 name =
"PBR Material";
226 headerColor = ImColor(SHADER_MATERIAL_NODE_COLOR);
227 inputPins.push_back(
new SNEPin(NodeEditorPinType::Input, SNEPinType::SNEPinType_Float3));
228 inputPins.push_back(
new SNEPin(NodeEditorPinType::Input, SNEPinType::SNEPinType_Float3));
229 inputPins.push_back(
new SNEPin(NodeEditorPinType::Input, SNEPinType::SNEPinType_Float3));
230 inputPins.push_back(
new SNEPin(NodeEditorPinType::Input, SNEPinType::SNEPinType_Float3));
231 inputPins.push_back(
new SNEPin(NodeEditorPinType::Input, SNEPinType::SNEPinType_Float3));
232 inputPins.push_back(
new SNEPin(NodeEditorPinType::Input, SNEPinType::SNEPinType_Float3));
233 outputPins.push_back(
new SNEPin(NodeEditorPinType::Output, SNEPinType::SNEPinType_Float3));
237PBRMaterialNode::~PBRMaterialNode()
a class to store JSON values