diff --git a/.gitignore b/.gitignore
index d2bcfb5c..ae0d3acd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@ Build/
imgui.ini
*.aps
*.vcxproj*
-*.sln
\ No newline at end of file
+*.sln
+*.vcxitems*
\ No newline at end of file
diff --git a/Resources/Editor/Icons/puzzle.png b/Resources/Editor/Icons/puzzle.png
new file mode 100644
index 00000000..8b014d0c
Binary files /dev/null and b/Resources/Editor/Icons/puzzle.png differ
diff --git a/Resources/Editor/Shaders/Billboard.glsl b/Resources/Editor/Shaders/Billboard.ovfx
similarity index 100%
rename from Resources/Editor/Shaders/Billboard.glsl
rename to Resources/Editor/Shaders/Billboard.ovfx
diff --git a/Resources/Editor/Shaders/Gizmo.glsl b/Resources/Editor/Shaders/Gizmo.ovfx
similarity index 100%
rename from Resources/Editor/Shaders/Gizmo.glsl
rename to Resources/Editor/Shaders/Gizmo.ovfx
diff --git a/Resources/Editor/Shaders/Grid.glsl b/Resources/Editor/Shaders/Grid.ovfx
similarity index 100%
rename from Resources/Editor/Shaders/Grid.glsl
rename to Resources/Editor/Shaders/Grid.ovfx
diff --git a/Resources/Engine/Materials/Default.ovmat b/Resources/Engine/Materials/Default.ovmat
index 92306d74..74058ed2 100644
--- a/Resources/Engine/Materials/Default.ovmat
+++ b/Resources/Engine/Materials/Default.ovmat
@@ -1,5 +1,5 @@
- :Shaders\Standard.glsl
+ :Shaders\Standard.ovfx
false
true
diff --git a/Resources/Engine/Shaders/Common/Buffers/EngineUBO.ovfxh b/Resources/Engine/Shaders/Common/Buffers/EngineUBO.ovfxh
new file mode 100644
index 00000000..fd9f776b
--- /dev/null
+++ b/Resources/Engine/Shaders/Common/Buffers/EngineUBO.ovfxh
@@ -0,0 +1,9 @@
+layout (std140) uniform EngineUBO
+{
+ mat4 ubo_Model;
+ mat4 ubo_View;
+ mat4 ubo_Projection;
+ vec3 ubo_ViewPos;
+ float ubo_Time;
+ mat4 ubo_UserMatrix;
+};
diff --git a/Resources/Engine/Shaders/Common/Buffers/LightsSSBO.ovfxh b/Resources/Engine/Shaders/Common/Buffers/LightsSSBO.ovfxh
new file mode 100644
index 00000000..77e94946
--- /dev/null
+++ b/Resources/Engine/Shaders/Common/Buffers/LightsSSBO.ovfxh
@@ -0,0 +1,4 @@
+layout(std430, binding = 0) buffer LightSSBO
+{
+ mat4 ssbo_Lights[];
+};
diff --git a/Resources/Engine/Shaders/Common/Constants.ovfxh b/Resources/Engine/Shaders/Common/Constants.ovfxh
new file mode 100644
index 00000000..a3a5308e
--- /dev/null
+++ b/Resources/Engine/Shaders/Common/Constants.ovfxh
@@ -0,0 +1 @@
+const float PI = 3.14159265359;
diff --git a/Resources/Engine/Shaders/Common/Physics.ovfxh b/Resources/Engine/Shaders/Common/Physics.ovfxh
new file mode 100644
index 00000000..66d55996
--- /dev/null
+++ b/Resources/Engine/Shaders/Common/Physics.ovfxh
@@ -0,0 +1,12 @@
+bool IsPointInAABB(vec3 point, vec3 aabbCenter, vec3 aabbHalfSize)
+{
+ return
+ point.x > aabbCenter.x - aabbHalfSize.x && point.x < aabbCenter.x + aabbHalfSize.x &&
+ point.y > aabbCenter.y - aabbHalfSize.y && point.y < aabbCenter.y + aabbHalfSize.y &&
+ point.z > aabbCenter.z - aabbHalfSize.z && point.z < aabbCenter.z + aabbHalfSize.z;
+}
+
+bool IsPointInSphere(vec3 point, vec3 sphereCenter, float sphereRadius)
+{
+ return distance(point, sphereCenter) <= sphereRadius;
+}
\ No newline at end of file
diff --git a/Resources/Engine/Shaders/Common/Utils.ovfxh b/Resources/Engine/Shaders/Common/Utils.ovfxh
new file mode 100644
index 00000000..1ed35a10
--- /dev/null
+++ b/Resources/Engine/Shaders/Common/Utils.ovfxh
@@ -0,0 +1,54 @@
+vec3 UnPack(float target)
+{
+ return vec3 (
+ float((uint(target) >> 24) & 0xff) * 0.003921568627451,
+ float((uint(target) >> 16) & 0xff) * 0.003921568627451,
+ float((uint(target) >> 8) & 0xff) * 0.003921568627451
+ );
+}
+
+vec2 TileAndOffsetTexCoords(vec2 texCoords, vec2 tiling, vec2 offset)
+{
+ return vec2(mod(texCoords.x * tiling.x, 1), mod(texCoords.y * tiling.y, 1)) + offset;
+}
+
+vec2 ApplyParallaxMapping(vec2 texCoords, sampler2D heightMap, vec3 tangentViewPos, vec3 tangentFragPos, float heightScale)
+{
+ if (heightScale > 0)
+ {
+ const vec3 viewDir = normalize(tangentViewPos - tangentFragPos);
+ const vec2 parallax = viewDir.xy * heightScale * texture(heightMap, texCoords).r;
+ return texCoords - vec2(parallax.x, 1.0 - parallax.y);
+ }
+
+ return texCoords;
+}
+
+bool IsMasked(sampler2D maskMap, vec2 texCoords)
+{
+ return texture(maskMap, texCoords).r == 0.0;
+}
+
+mat3 ConstructTBN(mat4 model, vec3 normal, vec3 tangent, vec3 bitangent)
+{
+ return mat3(
+ normalize(vec3(model * vec4(tangent, 0.0))),
+ normalize(vec3(model * vec4(bitangent, 0.0))),
+ normalize(vec3(model * vec4(normal, 0.0)))
+ );
+}
+
+vec3 ComputeNormal(bool enableNormalMapping, vec2 texCoords, vec3 normal, sampler2D normalMap, mat3 TBN)
+{
+ if (enableNormalMapping)
+ {
+ normal = texture(normalMap, texCoords).rgb;
+ normal = normalize(normal * 2.0 - 1.0);
+ normal = normalize(TBN * normal);
+ return normal;
+ }
+ else
+ {
+ return normalize(normal);
+ }
+}
diff --git a/Resources/Engine/Shaders/Lambert.glsl b/Resources/Engine/Shaders/Lambert.glsl
deleted file mode 100644
index debb5ba4..00000000
--- a/Resources/Engine/Shaders/Lambert.glsl
+++ /dev/null
@@ -1,64 +0,0 @@
-#shader vertex
-#version 430 core
-
-layout (location = 0) in vec3 geo_Pos;
-layout (location = 1) in vec2 geo_TexCoords;
-layout (location = 2) in vec3 geo_Normal;
-
-layout (std140) uniform EngineUBO
-{
- mat4 ubo_Model;
- mat4 ubo_View;
- mat4 ubo_Projection;
- vec3 ubo_ViewPos;
- float ubo_Time;
-};
-
-out VS_OUT
-{
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
-} vs_out;
-
-void main()
-{
- vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
- vs_out.Normal = normalize(mat3(transpose(inverse(ubo_Model))) * geo_Normal);
- vs_out.TexCoords = geo_TexCoords;
-
- gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
-}
-
-#shader fragment
-#version 430 core
-
-out vec4 FRAGMENT_COLOR;
-
-in VS_OUT
-{
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
-} fs_in;
-
-uniform vec4 u_Diffuse = vec4(1.0, 1.0, 1.0, 1.0);
-uniform sampler2D u_DiffuseMap;
-uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
-uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
-
-const vec3 c_lightPosition = vec3(-9000.0, 10000.0, 11000.0);
-const vec3 c_lightDiffuse = vec3(1.0, 1.0, 1.0);
-const vec3 c_lightAmbient = vec3(0.3, 0.3, 0.3);
-
-vec3 Lambert(vec3 p_fragPos, vec3 p_normal)
-{
- const float diffuse = max(dot(p_normal, normalize(c_lightPosition - p_fragPos)), 0.0);
- return clamp(c_lightDiffuse * diffuse + c_lightAmbient, 0.0, 1.0);
-}
-
-void main()
-{
- const vec4 diffuse = texture(u_DiffuseMap, u_TextureOffset + vec2(mod(fs_in.TexCoords.x * u_TextureTiling.x, 1), mod(fs_in.TexCoords.y * u_TextureTiling.y, 1))) * u_Diffuse;
- FRAGMENT_COLOR = vec4(Lambert(fs_in.FragPos, fs_in.Normal) * diffuse.rgb, diffuse.a);
-}
\ No newline at end of file
diff --git a/Resources/Engine/Shaders/Lambert.ovfx b/Resources/Engine/Shaders/Lambert.ovfx
new file mode 100644
index 00000000..4a65a625
--- /dev/null
+++ b/Resources/Engine/Shaders/Lambert.ovfx
@@ -0,0 +1,58 @@
+#shader vertex
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+
+layout (location = 0) in vec3 geo_Pos;
+layout (location = 1) in vec2 geo_TexCoords;
+layout (location = 2) in vec3 geo_Normal;
+
+out VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+ vec3 Normal;
+} vs_out;
+
+void main()
+{
+ vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
+ vs_out.TexCoords = geo_TexCoords;
+ vs_out.Normal = normalize(mat3(transpose(inverse(ubo_Model))) * geo_Normal);
+
+ gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
+}
+
+#shader fragment
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+#include ":Shaders/Lighting/Lambert.ovfxh"
+
+in VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+ vec3 Normal;
+} fs_in;
+
+uniform vec4 u_Diffuse = vec4(1.0, 1.0, 1.0, 1.0);
+uniform sampler2D u_DiffuseMap;
+uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
+uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
+
+out vec4 FRAGMENT_COLOR;
+
+void main()
+{
+ vec2 texCoords = TileAndOffsetTexCoords(fs_in.TexCoords, u_TextureTiling, u_TextureOffset);
+
+ const vec3 kLightPosition = vec3(-9000.0, 10000.0, 11000.0);
+ const vec3 kLightDiffuse = vec3(1.0);
+ const vec3 kLightAmbient = vec3(0.3);
+ const vec3 lambert = ComputeLambertLighting(fs_in.FragPos, fs_in.Normal, kLightPosition, kLightDiffuse, kLightAmbient);
+
+ FRAGMENT_COLOR = texture(u_DiffuseMap, texCoords) * u_Diffuse * vec4(lambert, 1.0);
+}
diff --git a/Resources/Engine/Shaders/Lighting/BlinnPhong.ovfxh b/Resources/Engine/Shaders/Lighting/BlinnPhong.ovfxh
new file mode 100644
index 00000000..f62ccdb4
--- /dev/null
+++ b/Resources/Engine/Shaders/Lighting/BlinnPhong.ovfxh
@@ -0,0 +1,98 @@
+#include ":Shaders/Common/Physics.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+#include ":Shaders/Lighting/Shared.ovfxh"
+#include ":Shaders/Common/Buffers/LightsSSBO.ovfxh"
+
+vec3 BlinnPhong(vec3 lightDir, vec3 lightColor, float luminosity, vec4 diffuseTexel, vec4 specularTexel, vec3 normal, vec3 viewDir, float shininess)
+{
+ const vec3 halfwayDir = normalize(lightDir + viewDir);
+ const float diffuseCoefficient = max(dot(normal, lightDir), 0.0);
+ const float specularCoefficient = pow(max(dot(normal, halfwayDir), 0.0), shininess * 2.0);
+
+ return lightColor * diffuseTexel.rgb * diffuseCoefficient * luminosity + ((luminosity > 0.0) ? (lightColor * specularTexel.rgb * specularCoefficient * luminosity) : vec3(0.0));
+}
+
+vec3 ComputePointLight(mat4 light, vec3 fragPos, vec4 diffuseTexel, vec4 specularTexel, vec3 normal, vec3 viewDir, float shininess)
+{
+ /* Extract light information from light mat4 */
+ const vec3 lightPosition = light[0].rgb;
+ const vec3 lightColor = UnPack(light[2][0]);
+ const float intensity = light[3][3];
+
+ const vec3 lightDirection = normalize(lightPosition - fragPos);
+ const float luminosity = LuminosityFromAttenuation(light, fragPos);
+
+ return BlinnPhong(lightDirection, lightColor, intensity * luminosity, diffuseTexel, specularTexel, normal, viewDir, shininess);
+}
+
+vec3 ComputeDirectionalLight(mat4 light, vec4 diffuseTexel, vec4 specularTexel, vec3 normal, vec3 viewDir, float shininess)
+{
+ return BlinnPhong(-light[1].rgb, UnPack(light[2][0]), light[3][3], diffuseTexel, specularTexel, normal, viewDir, shininess);
+}
+
+vec3 ComputeSpotLight(mat4 light, vec3 fragPos, vec4 diffuseTexel, vec4 specularTexel, vec3 normal, vec3 viewDir, float shininess)
+{
+ /* Extract light information from light mat4 */
+ const vec3 lightPosition = light[0].rgb;
+ const vec3 lightForward = light[1].rgb;
+ const vec3 lightColor = UnPack(light[2][0]);
+ const float intensity = light[3][3];
+ const float cutOff = cos(radians(light[3][1]));
+ const float outerCutOff = cos(radians(light[3][1] + light[3][2]));
+
+ const vec3 lightDirection = normalize(lightPosition - fragPos);
+ const float luminosity = LuminosityFromAttenuation(light, fragPos);
+
+ /* Calculate the spot intensity */
+ const float theta = dot(lightDirection, normalize(-lightForward));
+ const float epsilon = cutOff - outerCutOff;
+ const float spotIntensity = clamp((theta - outerCutOff) / epsilon, 0.0, 1.0);
+
+ return BlinnPhong(lightDirection, lightColor, intensity * spotIntensity * luminosity, diffuseTexel, specularTexel, normal, viewDir, shininess);
+}
+
+vec3 ComputeAmbientBoxLight(mat4 light, vec3 fragPos, vec4 diffuseTexel)
+{
+ const vec3 lightPosition = light[0].rgb;
+ const vec3 lightColor = UnPack(light[2][0]);
+ const float intensity = light[3][3];
+ const vec3 size = vec3(light[0][3], light[1][3], light[2][3]);
+
+ return IsPointInAABB(fragPos, lightPosition, size) ? diffuseTexel.rgb * lightColor * intensity : vec3(0.0);
+}
+
+vec3 ComputeAmbientSphereLight(mat4 light, vec3 fragPos, vec4 diffuseTexel)
+{
+ const vec3 lightPosition = light[0].rgb;
+ const vec3 lightColor = UnPack(light[2][0]);
+ const float intensity = light[3][3];
+ const float radius = light[0][3];
+
+ return IsPointInSphere(fragPos, lightPosition, radius) ? diffuseTexel.rgb * lightColor * intensity : vec3(0.0);
+}
+
+vec4 ComputeBlinnPhongLighting(vec2 texCoords, vec3 normal, vec3 viewPos, vec3 fragPos, vec4 diffuse, vec3 specular, sampler2D diffuseMap, sampler2D specularMap, float shininess)
+{
+ vec3 viewDir = normalize(viewPos - fragPos);
+ vec4 diffuseTexel = texture(diffuseMap, texCoords) * diffuse;
+ vec4 specularTexel = texture(specularMap, texCoords) * vec4(specular, 1.0);
+
+ vec3 lightAccumulation = vec3(0.0);
+
+ for (int i = 0; i < ssbo_Lights.length(); ++i)
+ {
+ const mat4 light = ssbo_Lights[i];
+ const int lightType = int(light[3][0]);
+
+ switch(lightType)
+ {
+ case 0: lightAccumulation += ComputePointLight(light, fragPos, diffuseTexel, specularTexel, normal, viewDir, shininess); break;
+ case 1: lightAccumulation += ComputeDirectionalLight(light, diffuseTexel, specularTexel, normal, viewDir, shininess); break;
+ case 2: lightAccumulation += ComputeSpotLight(light, fragPos, diffuseTexel, specularTexel, normal, viewDir, shininess); break;
+ case 3: lightAccumulation += ComputeAmbientBoxLight(light, fragPos, diffuseTexel); break;
+ case 4: lightAccumulation += ComputeAmbientSphereLight(light, fragPos, diffuseTexel); break;
+ }
+ }
+
+ return vec4(lightAccumulation, diffuseTexel.a);
+}
diff --git a/Resources/Engine/Shaders/Lighting/Lambert.ovfxh b/Resources/Engine/Shaders/Lighting/Lambert.ovfxh
new file mode 100644
index 00000000..223c5280
--- /dev/null
+++ b/Resources/Engine/Shaders/Lighting/Lambert.ovfxh
@@ -0,0 +1,5 @@
+vec3 ComputeLambertLighting(vec3 fragPos, vec3 normal, vec3 lightPos, vec3 lightDiffuse, vec3 lightAmbient)
+{
+ const float diffuse = max(dot(normal, normalize(lightPos - fragPos)), 0.0);
+ return clamp(lightDiffuse * diffuse + lightAmbient, 0.0, 1.0);
+}
diff --git a/Resources/Engine/Shaders/Lighting/PBR.ovfxh b/Resources/Engine/Shaders/Lighting/PBR.ovfxh
new file mode 100644
index 00000000..4df6c21b
--- /dev/null
+++ b/Resources/Engine/Shaders/Lighting/PBR.ovfxh
@@ -0,0 +1,160 @@
+#include ":Shaders/Common/Physics.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+#include ":Shaders/Common/Constants.ovfxh"
+#include ":Shaders/Common/Buffers/LightsSSBO.ovfxh"
+#include ":Shaders/Lighting/Shared.ovfxh"
+
+float DistributionGGX(vec3 N, vec3 H, float roughness)
+{
+ float a = roughness * roughness;
+ float a2 = a * a;
+ float NdotH = max(dot(N, H), 0.0);
+ float NdotH2 = NdotH * NdotH;
+
+ float num = a2;
+ float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+ denom = PI * denom * denom;
+
+ return num / denom;
+}
+
+float GeometrySchlickGGX(float NdotV, float roughness)
+{
+ float r = (roughness + 1.0);
+ float k = (r * r) / 8.0;
+
+ float num = NdotV;
+ float denom = NdotV * (1.0 - k) + k;
+
+ return num / denom;
+}
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
+{
+ float NdotV = max(dot(N, V), 0.0);
+ float NdotL = max(dot(N, L), 0.0);
+ float ggx2 = GeometrySchlickGGX(NdotV, roughness);
+ float ggx1 = GeometrySchlickGGX(NdotL, roughness);
+
+ return ggx1 * ggx2;
+}
+
+vec3 FresnelSchlick(float cosTheta, vec3 F0)
+{
+ return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
+}
+
+vec3 ComputeAmbientBoxLight(mat4 light, vec3 fragPos)
+{
+ const vec3 lightPosition = light[0].rgb;
+ const vec3 lightColor = UnPack(light[2][0]);
+ const float intensity = light[3][3];
+ const vec3 size = vec3(light[0][3], light[1][3], light[2][3]);
+
+ return IsPointInAABB(fragPos, lightPosition, size) ? lightColor * intensity : vec3(0.0);
+}
+
+vec3 ComputeAmbientSphereLight(mat4 light, vec3 fragPos)
+{
+ const vec3 lightPosition = light[0].rgb;
+ const vec3 lightColor = UnPack(light[2][0]);
+ const float intensity = light[3][3];
+ const float radius = light[0][3];
+
+ return IsPointInSphere(fragPos, lightPosition, radius) ? lightColor * intensity : vec3(0.0);
+}
+
+vec4 ComputePBRLighting(vec2 texCoords, vec3 normal, vec3 viewPos, vec3 fragPos, vec4 inAlbedo, float inMetallic, float inRoughness, sampler2D albedoMap, sampler2D metallicMap, sampler2D roughnessMap, sampler2D aoMap)
+{
+ vec4 albedoRGBA = texture(albedoMap, texCoords) * inAlbedo;
+ vec3 albedo = pow(albedoRGBA.rgb, vec3(2.2));
+ float metallic = texture(metallicMap, texCoords).r * inMetallic;
+ float roughness = texture(roughnessMap, texCoords).r * inRoughness;
+ float ao = texture(aoMap, texCoords).r;
+
+ vec3 N = normalize(normal);
+ vec3 V = normalize(viewPos - fragPos);
+
+ vec3 F0 = vec3(0.04);
+ F0 = mix(F0, albedo, metallic);
+
+ // reflectance equation
+ vec3 Lo = vec3(0.0);
+ vec3 ambientSum = vec3(0.0);
+
+ for (int i = 0; i < ssbo_Lights.length(); ++i)
+ {
+ const mat4 light = ssbo_Lights[i];
+ const int lightType = int(light[3][0]);
+
+ if (lightType == 3)
+ {
+ ambientSum += ComputeAmbientBoxLight(light, fragPos);
+ }
+ else if (lightType == 4)
+ {
+ ambientSum += ComputeAmbientSphereLight(light, fragPos);
+ }
+ else
+ {
+ // calculate per-light radiance
+ vec3 L = lightType == 1 ? -light[1].rgb : normalize(light[0].rgb - fragPos);
+ vec3 H = normalize(V + L);
+ float distance = length(light[0].rgb - fragPos);
+ float lightCoeff = 0.0;
+
+ switch(int(light[3][0]))
+ {
+ case 0:
+ lightCoeff = LuminosityFromAttenuation(light, fragPos) * light[3][3];
+ break;
+
+ case 1:
+ lightCoeff = light[3][3];
+ break;
+
+ case 2:
+ const vec3 lightForward = light[1].rgb;
+ const float cutOff = cos(radians(light[3][1]));
+ const float outerCutOff = cos(radians(light[3][1] + light[3][2]));
+
+ const vec3 lightDirection = normalize(light[0].rgb - fragPos);
+ const float luminosity = LuminosityFromAttenuation(light, fragPos);
+
+ /* Calculate the spot intensity */
+ const float theta = dot(lightDirection, normalize(-lightForward));
+ const float epsilon = cutOff - outerCutOff;
+ const float spotIntensity = clamp((theta - outerCutOff) / epsilon, 0.0, 1.0);
+
+ lightCoeff = luminosity * spotIntensity * light[3][3];
+ break;
+ }
+
+ vec3 radiance = UnPack(light[2][0]) * lightCoeff;
+
+ // cook-torrance brdf
+ float NDF = DistributionGGX(N, H, roughness);
+ float G = GeometrySmith(N, V, L, roughness);
+ vec3 F = FresnelSchlick(max(dot(H, V), 0.0), F0);
+
+ vec3 kS = F;
+ vec3 kD = vec3(1.0) - kS;
+ kD *= 1.0 - metallic;
+
+ vec3 numerator = NDF * G * F;
+ float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
+ vec3 specular = numerator / max(denominator, 0.001);
+
+ // add to outgoing radiance Lo
+ float NdotL = max(dot(N, L), 0.0);
+ Lo += (kD * albedo / PI + specular) * radiance * NdotL;
+ }
+ }
+
+ vec3 ambient = ambientSum * albedo * ao;
+ vec3 color = ambient + Lo;
+
+ color = color / (color + vec3(1.0));
+ color = pow(color, vec3(1.0/2.2));
+
+ return vec4(color, albedoRGBA.a);
+}
\ No newline at end of file
diff --git a/Resources/Engine/Shaders/Lighting/Shared.ovfxh b/Resources/Engine/Shaders/Lighting/Shared.ovfxh
new file mode 100644
index 00000000..7c8dd53e
--- /dev/null
+++ b/Resources/Engine/Shaders/Lighting/Shared.ovfxh
@@ -0,0 +1,12 @@
+float LuminosityFromAttenuation(mat4 light, vec3 fragPos)
+{
+ const vec3 lightPosition = light[0].rgb;
+ const float constant = light[0][3];
+ const float linear = light[1][3];
+ const float quadratic = light[2][3];
+
+ const float distanceToLight = length(lightPosition - fragPos);
+ const float attenuation = (constant + linear * distanceToLight + quadratic * (distanceToLight * distanceToLight));
+
+ return 1.0 / attenuation;
+}
diff --git a/Resources/Engine/Shaders/Standard.glsl b/Resources/Engine/Shaders/Standard.glsl
deleted file mode 100644
index 36ba7843..00000000
--- a/Resources/Engine/Shaders/Standard.glsl
+++ /dev/null
@@ -1,258 +0,0 @@
-#shader vertex
-#version 430 core
-
-layout (location = 0) in vec3 geo_Pos;
-layout (location = 1) in vec2 geo_TexCoords;
-layout (location = 2) in vec3 geo_Normal;
-layout (location = 3) in vec3 geo_Tangent;
-layout (location = 4) in vec3 geo_Bitangent;
-
-/* Global information sent by the engine */
-layout (std140) uniform EngineUBO
-{
- mat4 ubo_Model;
- mat4 ubo_View;
- mat4 ubo_Projection;
- vec3 ubo_ViewPos;
- float ubo_Time;
-};
-
-/* Information passed to the fragment shader */
-out VS_OUT
-{
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- mat3 TBN;
- flat vec3 TangentViewPos;
- vec3 TangentFragPos;
-} vs_out;
-
-void main()
-{
- vs_out.TBN = mat3
- (
- normalize(vec3(ubo_Model * vec4(geo_Tangent, 0.0))),
- normalize(vec3(ubo_Model * vec4(geo_Bitangent, 0.0))),
- normalize(vec3(ubo_Model * vec4(geo_Normal, 0.0)))
- );
-
- mat3 TBNi = transpose(vs_out.TBN);
-
- vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
- vs_out.Normal = normalize(mat3(transpose(inverse(ubo_Model))) * geo_Normal);
- vs_out.TexCoords = geo_TexCoords;
- vs_out.TangentViewPos = TBNi * ubo_ViewPos;
- vs_out.TangentFragPos = TBNi * vs_out.FragPos;
-
- gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
-}
-
-#shader fragment
-#version 430 core
-
-/* Global information sent by the engine */
-layout (std140) uniform EngineUBO
-{
- mat4 ubo_Model;
- mat4 ubo_View;
- mat4 ubo_Projection;
- vec3 ubo_ViewPos;
- float ubo_Time;
-};
-
-/* Information passed from the fragment shader */
-in VS_OUT
-{
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- mat3 TBN;
- flat vec3 TangentViewPos;
- vec3 TangentFragPos;
-} fs_in;
-
-/* Light information sent by the engine */
-layout(std430, binding = 0) buffer LightSSBO
-{
- mat4 ssbo_Lights[];
-};
-
-/* Uniforms (Tweakable from the material editor) */
-uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
-uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
-uniform vec4 u_Diffuse = vec4(1.0, 1.0, 1.0, 1.0);
-uniform vec3 u_Specular = vec3(1.0, 1.0, 1.0);
-uniform float u_Shininess = 100.0;
-uniform float u_HeightScale = 0.0;
-uniform bool u_EnableNormalMapping = false;
-uniform sampler2D u_DiffuseMap;
-uniform sampler2D u_SpecularMap;
-uniform sampler2D u_NormalMap;
-uniform sampler2D u_HeightMap;
-uniform sampler2D u_MaskMap;
-
-/* Global variables */
-vec3 g_Normal;
-vec2 g_TexCoords;
-vec3 g_ViewDir;
-vec4 g_DiffuseTexel;
-vec4 g_SpecularTexel;
-vec4 g_HeightTexel;
-vec4 g_NormalTexel;
-
-out vec4 FRAGMENT_COLOR;
-
-vec3 UnPack(float p_Target)
-{
- return vec3
- (
- float((uint(p_Target) >> 24) & 0xff) * 0.003921568627451,
- float((uint(p_Target) >> 16) & 0xff) * 0.003921568627451,
- float((uint(p_Target) >> 8) & 0xff) * 0.003921568627451
- );
-}
-
-bool PointInAABB(vec3 p_Point, vec3 p_AabbCenter, vec3 p_AabbHalfSize)
-{
- return
- (
- p_Point.x > p_AabbCenter.x - p_AabbHalfSize.x && p_Point.x < p_AabbCenter.x + p_AabbHalfSize.x &&
- p_Point.y > p_AabbCenter.y - p_AabbHalfSize.y && p_Point.y < p_AabbCenter.y + p_AabbHalfSize.y &&
- p_Point.z > p_AabbCenter.z - p_AabbHalfSize.z && p_Point.z < p_AabbCenter.z + p_AabbHalfSize.z
- );
-}
-
-vec2 ParallaxMapping(vec3 p_ViewDir)
-{
- const vec2 parallax = p_ViewDir.xy * u_HeightScale * texture(u_HeightMap, g_TexCoords).r;
- return g_TexCoords - vec2(parallax.x, 1.0 - parallax.y);
-}
-
-vec3 BlinnPhong(vec3 p_LightDir, vec3 p_LightColor, float p_Luminosity)
-{
- const vec3 halfwayDir = normalize(p_LightDir + g_ViewDir);
- const float diffuseCoefficient = max(dot(g_Normal, p_LightDir), 0.0);
- const float specularCoefficient = pow(max(dot(g_Normal, halfwayDir), 0.0), u_Shininess * 2.0);
-
- return p_LightColor * g_DiffuseTexel.rgb * diffuseCoefficient * p_Luminosity + ((p_Luminosity > 0.0) ? (p_LightColor * g_SpecularTexel.rgb * specularCoefficient * p_Luminosity) : vec3(0.0));
-}
-
-float LuminosityFromAttenuation(mat4 p_Light)
-{
- const vec3 lightPosition = p_Light[0].rgb;
- const float constant = p_Light[0][3];
- const float linear = p_Light[1][3];
- const float quadratic = p_Light[2][3];
-
- const float distanceToLight = length(lightPosition - fs_in.FragPos);
- const float attenuation = (constant + linear * distanceToLight + quadratic * (distanceToLight * distanceToLight));
- return 1.0 / attenuation;
-}
-
-vec3 CalcPointLight(mat4 p_Light)
-{
- /* Extract light information from light mat4 */
- const vec3 lightPosition = p_Light[0].rgb;
- const vec3 lightColor = UnPack(p_Light[2][0]);
- const float intensity = p_Light[3][3];
-
- const vec3 lightDirection = normalize(lightPosition - fs_in.FragPos);
- const float luminosity = LuminosityFromAttenuation(p_Light);
-
- return BlinnPhong(lightDirection, lightColor, intensity * luminosity);
-}
-
-vec3 CalcDirectionalLight(mat4 light)
-{
- return BlinnPhong(-light[1].rgb, UnPack(light[2][0]), light[3][3]);
-}
-
-vec3 CalcSpotLight(mat4 p_Light)
-{
- /* Extract light information from light mat4 */
- const vec3 lightPosition = p_Light[0].rgb;
- const vec3 lightForward = p_Light[1].rgb;
- const vec3 lightColor = UnPack(p_Light[2][0]);
- const float intensity = p_Light[3][3];
- const float cutOff = cos(radians(p_Light[3][1]));
- const float outerCutOff = cos(radians(p_Light[3][1] + p_Light[3][2]));
-
- const vec3 lightDirection = normalize(lightPosition - fs_in.FragPos);
- const float luminosity = LuminosityFromAttenuation(p_Light);
-
- /* Calculate the spot intensity */
- const float theta = dot(lightDirection, normalize(-lightForward));
- const float epsilon = cutOff - outerCutOff;
- const float spotIntensity = clamp((theta - outerCutOff) / epsilon, 0.0, 1.0);
-
- return BlinnPhong(lightDirection, lightColor, intensity * spotIntensity * luminosity);
-}
-
-vec3 CalcAmbientBoxLight(mat4 p_Light)
-{
- const vec3 lightPosition = p_Light[0].rgb;
- const vec3 lightColor = UnPack(p_Light[2][0]);
- const float intensity = p_Light[3][3];
- const vec3 size = vec3(p_Light[0][3], p_Light[1][3], p_Light[2][3]);
-
- return PointInAABB(fs_in.FragPos, lightPosition, size) ? g_DiffuseTexel.rgb * lightColor * intensity : vec3(0.0);
-}
-
-vec3 CalcAmbientSphereLight(mat4 p_Light)
-{
- const vec3 lightPosition = p_Light[0].rgb;
- const vec3 lightColor = UnPack(p_Light[2][0]);
- const float intensity = p_Light[3][3];
- const float radius = p_Light[0][3];
-
- return distance(lightPosition, fs_in.FragPos) <= radius ? g_DiffuseTexel.rgb * lightColor * intensity : vec3(0.0);
-}
-
-void main()
-{
- g_TexCoords = u_TextureOffset + vec2(mod(fs_in.TexCoords.x * u_TextureTiling.x, 1), mod(fs_in.TexCoords.y * u_TextureTiling.y, 1));
-
- /* Apply parallax mapping */
- if (u_HeightScale > 0)
- g_TexCoords = ParallaxMapping(normalize(fs_in.TangentViewPos - fs_in.TangentFragPos));
-
- /* Apply color mask */
- if (texture(u_MaskMap, g_TexCoords).r != 0.0)
- {
- g_ViewDir = normalize(ubo_ViewPos - fs_in.FragPos);
- g_DiffuseTexel = texture(u_DiffuseMap, g_TexCoords) * u_Diffuse;
- g_SpecularTexel = texture(u_SpecularMap, g_TexCoords) * vec4(u_Specular, 1.0);
-
- if (u_EnableNormalMapping)
- {
- g_Normal = texture(u_NormalMap, g_TexCoords).rgb;
- g_Normal = normalize(g_Normal * 2.0 - 1.0);
- g_Normal = normalize(fs_in.TBN * g_Normal);
- }
- else
- {
- g_Normal = normalize(fs_in.Normal);
- }
-
- vec3 lightSum = vec3(0.0);
-
- for (int i = 0; i < ssbo_Lights.length(); ++i)
- {
- switch(int(ssbo_Lights[i][3][0]))
- {
- case 0: lightSum += CalcPointLight(ssbo_Lights[i]); break;
- case 1: lightSum += CalcDirectionalLight(ssbo_Lights[i]); break;
- case 2: lightSum += CalcSpotLight(ssbo_Lights[i]); break;
- case 3: lightSum += CalcAmbientBoxLight(ssbo_Lights[i]); break;
- case 4: lightSum += CalcAmbientSphereLight(ssbo_Lights[i]); break;
- }
- }
-
- FRAGMENT_COLOR = vec4(lightSum, g_DiffuseTexel.a);
- }
- else
- {
- FRAGMENT_COLOR = vec4(0.0);
- }
-}
\ No newline at end of file
diff --git a/Resources/Engine/Shaders/Standard.ovfx b/Resources/Engine/Shaders/Standard.ovfx
new file mode 100644
index 00000000..7cfdd69f
--- /dev/null
+++ b/Resources/Engine/Shaders/Standard.ovfx
@@ -0,0 +1,80 @@
+#shader vertex
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+
+layout (location = 0) in vec3 geo_Pos;
+layout (location = 1) in vec2 geo_TexCoords;
+layout (location = 2) in vec3 geo_Normal;
+layout (location = 3) in vec3 geo_Tangent;
+layout (location = 4) in vec3 geo_Bitangent;
+
+out VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+ vec3 Normal;
+ mat3 TBN;
+ flat vec3 TangentViewPos;
+ vec3 TangentFragPos;
+} vs_out;
+
+void main()
+{
+ vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
+ vs_out.TexCoords = geo_TexCoords;
+ vs_out.Normal = normalize(mat3(transpose(inverse(ubo_Model))) * geo_Normal);
+ vs_out.TBN = ConstructTBN(ubo_Model, geo_Normal, geo_Tangent, geo_Bitangent);
+ vs_out.TangentViewPos = transpose(vs_out.TBN) * ubo_ViewPos;
+ vs_out.TangentFragPos = transpose(vs_out.TBN) * vs_out.FragPos;
+
+ gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
+}
+
+#shader fragment
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Lighting/BlinnPhong.ovfxh"
+
+in VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+ vec3 Normal;
+ mat3 TBN;
+ flat vec3 TangentViewPos;
+ vec3 TangentFragPos;
+} fs_in;
+
+uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
+uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
+uniform vec4 u_Diffuse = vec4(1.0, 1.0, 1.0, 1.0);
+uniform vec3 u_Specular = vec3(1.0, 1.0, 1.0);
+uniform float u_Shininess = 100.0;
+uniform float u_HeightScale = 0.0;
+uniform bool u_EnableNormalMapping = false;
+uniform sampler2D u_DiffuseMap;
+uniform sampler2D u_SpecularMap;
+uniform sampler2D u_NormalMap;
+uniform sampler2D u_HeightMap;
+uniform sampler2D u_MaskMap;
+
+out vec4 FRAGMENT_COLOR;
+
+void main()
+{
+ vec2 texCoords = TileAndOffsetTexCoords(fs_in.TexCoords, u_TextureTiling, u_TextureOffset);
+ texCoords = ApplyParallaxMapping(texCoords, u_HeightMap, fs_in.TangentViewPos, fs_in.TangentFragPos, u_HeightScale);
+
+ if (!IsMasked(u_MaskMap, texCoords))
+ {
+ vec3 normal = ComputeNormal(u_EnableNormalMapping, texCoords, fs_in.Normal, u_NormalMap, fs_in.TBN);
+ FRAGMENT_COLOR = ComputeBlinnPhongLighting(texCoords, normal, ubo_ViewPos, fs_in.FragPos, u_Diffuse, u_Specular, u_DiffuseMap, u_SpecularMap, u_Shininess);
+ }
+ else
+ {
+ FRAGMENT_COLOR = vec4(0.0);
+ }
+}
diff --git a/Resources/Engine/Shaders/StandardPBR.glsl b/Resources/Engine/Shaders/StandardPBR.glsl
deleted file mode 100644
index c0bd2e7d..00000000
--- a/Resources/Engine/Shaders/StandardPBR.glsl
+++ /dev/null
@@ -1,294 +0,0 @@
-#shader vertex
-#version 430 core
-
-layout (location = 0) in vec3 geo_Pos;
-layout (location = 1) in vec2 geo_TexCoords;
-layout (location = 2) in vec3 geo_Normal;
-layout (location = 3) in vec3 geo_Tangent;
-layout (location = 4) in vec3 geo_Bitangent;
-
-/* Global information sent by the engine */
-layout (std140) uniform EngineUBO
-{
- mat4 ubo_Model;
- mat4 ubo_View;
- mat4 ubo_Projection;
- vec3 ubo_ViewPos;
- float ubo_Time;
-};
-
-/* Information passed to the fragment shader */
-out VS_OUT
-{
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- mat3 TBN;
- flat vec3 TangentViewPos;
- vec3 TangentFragPos;
-} vs_out;
-
-void main()
-{
- vs_out.TBN = mat3
- (
- normalize(vec3(ubo_Model * vec4(geo_Tangent, 0.0))),
- normalize(vec3(ubo_Model * vec4(geo_Bitangent, 0.0))),
- normalize(vec3(ubo_Model * vec4(geo_Normal, 0.0)))
- );
-
- mat3 TBNi = transpose(vs_out.TBN);
-
- vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
- vs_out.Normal = normalize(mat3(transpose(inverse(ubo_Model))) * geo_Normal);
- vs_out.TexCoords = geo_TexCoords;
- vs_out.TangentViewPos = TBNi * ubo_ViewPos;
- vs_out.TangentFragPos = TBNi * vs_out.FragPos;
-
- gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
-}
-
-#shader fragment
-#version 430 core
-
-/* Global information sent by the engine */
-layout (std140) uniform EngineUBO
-{
- mat4 ubo_Model;
- mat4 ubo_View;
- mat4 ubo_Projection;
- vec3 ubo_ViewPos;
- float ubo_Time;
-};
-
-/* Information passed from the fragment shader */
-in VS_OUT
-{
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- mat3 TBN;
- flat vec3 TangentViewPos;
- vec3 TangentFragPos;
-} fs_in;
-
-/* Light information sent by the engine */
-layout(std430, binding = 0) buffer LightSSBO
-{
- mat4 ssbo_Lights[];
-};
-
-out vec4 FRAGMENT_COLOR;
-
-uniform sampler2D u_AlbedoMap;
-uniform sampler2D u_MetallicMap;
-uniform sampler2D u_RoughnessMap;
-uniform sampler2D u_AmbientOcclusionMap;
-uniform sampler2D u_NormalMap;
-uniform vec4 u_Albedo = vec4(1.0);
-uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
-uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
-uniform bool u_EnableNormalMapping = false;
-uniform float u_HeightScale = 0.0;
-uniform float u_Metallic = 1.0;
-uniform float u_Roughness = 1.0;
-
-const float PI = 3.14159265359;
-
-float DistributionGGX(vec3 N, vec3 H, float roughness)
-{
- float a = roughness*roughness;
- float a2 = a*a;
- float NdotH = max(dot(N, H), 0.0);
- float NdotH2 = NdotH*NdotH;
-
- float num = a2;
- float denom = (NdotH2 * (a2 - 1.0) + 1.0);
- denom = PI * denom * denom;
-
- return num / denom;
-}
-
-float GeometrySchlickGGX(float NdotV, float roughness)
-{
- float r = (roughness + 1.0);
- float k = (r*r) / 8.0;
-
- float num = NdotV;
- float denom = NdotV * (1.0 - k) + k;
-
- return num / denom;
-}
-float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
-{
- float NdotV = max(dot(N, V), 0.0);
- float NdotL = max(dot(N, L), 0.0);
- float ggx2 = GeometrySchlickGGX(NdotV, roughness);
- float ggx1 = GeometrySchlickGGX(NdotL, roughness);
-
- return ggx1 * ggx2;
-}
-
-vec3 fresnelSchlick(float cosTheta, vec3 F0)
-{
- return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
-}
-
-vec3 UnPack(float p_Target)
-{
- return vec3
- (
- float((uint(p_Target) >> 24) & 0xff) * 0.003921568627451,
- float((uint(p_Target) >> 16) & 0xff) * 0.003921568627451,
- float((uint(p_Target) >> 8) & 0xff) * 0.003921568627451
- );
-}
-
-bool PointInAABB(vec3 p_Point, vec3 p_AabbCenter, vec3 p_AabbHalfSize)
-{
- return
- (
- p_Point.x > p_AabbCenter.x - p_AabbHalfSize.x && p_Point.x < p_AabbCenter.x + p_AabbHalfSize.x &&
- p_Point.y > p_AabbCenter.y - p_AabbHalfSize.y && p_Point.y < p_AabbCenter.y + p_AabbHalfSize.y &&
- p_Point.z > p_AabbCenter.z - p_AabbHalfSize.z && p_Point.z < p_AabbCenter.z + p_AabbHalfSize.z
- );
-}
-
-float LuminosityFromAttenuation(mat4 p_Light)
-{
- const vec3 lightPosition = p_Light[0].rgb;
- const float constant = p_Light[0][3];
- const float linear = p_Light[1][3];
- const float quadratic = p_Light[2][3];
-
- const float distanceToLight = length(lightPosition - fs_in.FragPos);
- const float attenuation = (constant + linear * distanceToLight + quadratic * (distanceToLight * distanceToLight));
- return 1.0 / attenuation;
-}
-
-vec3 CalcAmbientBoxLight(mat4 p_Light)
-{
- const vec3 lightPosition = p_Light[0].rgb;
- const vec3 lightColor = UnPack(p_Light[2][0]);
- const float intensity = p_Light[3][3];
- const vec3 size = vec3(p_Light[0][3], p_Light[1][3], p_Light[2][3]);
-
- return PointInAABB(fs_in.FragPos, lightPosition, size) ? lightColor * intensity : vec3(0.0);
-}
-
-vec3 CalcAmbientSphereLight(mat4 p_Light)
-{
- const vec3 lightPosition = p_Light[0].rgb;
- const vec3 lightColor = UnPack(p_Light[2][0]);
- const float intensity = p_Light[3][3];
- const float radius = p_Light[0][3];
-
- return distance(lightPosition, fs_in.FragPos) <= radius ? lightColor * intensity : vec3(0.0);
-}
-
-void main()
-{
- vec2 texCoords = u_TextureOffset + vec2(mod(fs_in.TexCoords.x * u_TextureTiling.x, 1), mod(fs_in.TexCoords.y * u_TextureTiling.y, 1));
-
- vec4 albedoRGBA = texture(u_AlbedoMap, texCoords) * u_Albedo;
- vec3 albedo = pow(albedoRGBA.rgb, vec3(2.2));
- float metallic = texture(u_MetallicMap, texCoords).r * u_Metallic;
- float roughness = texture(u_RoughnessMap, texCoords).r * u_Roughness;
- float ao = texture(u_AmbientOcclusionMap, texCoords).r;
- vec3 normal;
-
- if (u_EnableNormalMapping)
- {
- normal = texture(u_NormalMap, texCoords).rgb;
- normal = normalize(normal * 2.0 - 1.0);
- normal = normalize(fs_in.TBN * normal);
- }
- else
- {
- normal = normalize(fs_in.Normal);
- }
-
- vec3 N = normalize(normal);
- vec3 V = normalize(ubo_ViewPos - fs_in.FragPos);
-
- vec3 F0 = vec3(0.04);
- F0 = mix(F0, albedo, metallic);
-
- // reflectance equation
- vec3 Lo = vec3(0.0);
- vec3 ambientSum = vec3(0.0);
-
- for (int i = 0; i < ssbo_Lights.length(); ++i)
- {
- if (int(ssbo_Lights[i][3][0]) == 3)
- {
- ambientSum += CalcAmbientBoxLight(ssbo_Lights[i]);
- }
- else if (int(ssbo_Lights[i][3][0]) == 4)
- {
- ambientSum += CalcAmbientSphereLight(ssbo_Lights[i]);
- }
- else
- {
- // calculate per-light radiance
- vec3 L = int(ssbo_Lights[i][3][0]) == 1 ? -ssbo_Lights[i][1].rgb : normalize(ssbo_Lights[i][0].rgb - fs_in.FragPos);
- vec3 H = normalize(V + L);
- float distance = length(ssbo_Lights[i][0].rgb - fs_in.FragPos);
- float lightCoeff = 0.0;
-
- switch(int(ssbo_Lights[i][3][0]))
- {
- case 0:
- lightCoeff = LuminosityFromAttenuation(ssbo_Lights[i]) * ssbo_Lights[i][3][3];
- break;
-
- case 1:
- lightCoeff = ssbo_Lights[i][3][3];
- break;
-
- case 2:
- const vec3 lightForward = ssbo_Lights[i][1].rgb;
- const float cutOff = cos(radians(ssbo_Lights[i][3][1]));
- const float outerCutOff = cos(radians(ssbo_Lights[i][3][1] + ssbo_Lights[i][3][2]));
-
- const vec3 lightDirection = normalize(ssbo_Lights[i][0].rgb - fs_in.FragPos);
- const float luminosity = LuminosityFromAttenuation(ssbo_Lights[i]);
-
- /* Calculate the spot intensity */
- const float theta = dot(lightDirection, normalize(-lightForward));
- const float epsilon = cutOff - outerCutOff;
- const float spotIntensity = clamp((theta - outerCutOff) / epsilon, 0.0, 1.0);
-
- lightCoeff = luminosity * spotIntensity * ssbo_Lights[i][3][3];
- break;
- }
-
- vec3 radiance = UnPack(ssbo_Lights[i][2][0]) * lightCoeff;
-
- // cook-torrance brdf
- float NDF = DistributionGGX(N, H, roughness);
- float G = GeometrySmith(N, V, L, roughness);
- vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
-
- vec3 kS = F;
- vec3 kD = vec3(1.0) - kS;
- kD *= 1.0 - metallic;
-
- vec3 numerator = NDF * G * F;
- float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
- vec3 specular = numerator / max(denominator, 0.001);
-
- // add to outgoing radiance Lo
- float NdotL = max(dot(N, L), 0.0);
- Lo += (kD * albedo / PI + specular) * radiance * NdotL;
- }
- }
-
- vec3 ambient = ambientSum * albedo * ao;
- vec3 color = ambient + Lo;
-
- color = color / (color + vec3(1.0));
- color = pow(color, vec3(1.0/2.2));
-
- FRAGMENT_COLOR = vec4(color, albedoRGBA.a);
-}
\ No newline at end of file
diff --git a/Resources/Engine/Shaders/StandardPBR.ovfx b/Resources/Engine/Shaders/StandardPBR.ovfx
new file mode 100644
index 00000000..28862cae
--- /dev/null
+++ b/Resources/Engine/Shaders/StandardPBR.ovfx
@@ -0,0 +1,82 @@
+#shader vertex
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+
+layout (location = 0) in vec3 geo_Pos;
+layout (location = 1) in vec2 geo_TexCoords;
+layout (location = 2) in vec3 geo_Normal;
+layout (location = 3) in vec3 geo_Tangent;
+layout (location = 4) in vec3 geo_Bitangent;
+
+out VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+ vec3 Normal;
+ mat3 TBN;
+ flat vec3 TangentViewPos;
+ vec3 TangentFragPos;
+} vs_out;
+
+void main()
+{
+ vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
+ vs_out.TexCoords = geo_TexCoords;
+ vs_out.Normal = normalize(mat3(transpose(inverse(ubo_Model))) * geo_Normal);
+ vs_out.TBN = ConstructTBN(ubo_Model, geo_Normal, geo_Tangent, geo_Bitangent);
+ vs_out.TangentViewPos = transpose(vs_out.TBN) * ubo_ViewPos;
+ vs_out.TangentFragPos = transpose(vs_out.TBN) * vs_out.FragPos;
+
+ gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
+}
+
+#shader fragment
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Lighting/PBR.ovfxh"
+
+in VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+ vec3 Normal;
+ mat3 TBN;
+ flat vec3 TangentViewPos;
+ vec3 TangentFragPos;
+} fs_in;
+
+uniform sampler2D u_AlbedoMap;
+uniform sampler2D u_MetallicMap;
+uniform sampler2D u_RoughnessMap;
+uniform sampler2D u_AmbientOcclusionMap;
+uniform sampler2D u_NormalMap;
+uniform vec4 u_Albedo = vec4(1.0);
+uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
+uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
+uniform bool u_EnableNormalMapping = false;
+uniform float u_HeightScale = 0.0;
+uniform float u_Metallic = 1.0;
+uniform float u_Roughness = 1.0;
+uniform sampler2D u_HeightMap;
+uniform sampler2D u_MaskMap;
+
+out vec4 FRAGMENT_COLOR;
+
+void main()
+{
+ vec2 texCoords = TileAndOffsetTexCoords(fs_in.TexCoords, u_TextureTiling, u_TextureOffset);
+ texCoords = ApplyParallaxMapping(texCoords, u_HeightMap, fs_in.TangentViewPos, fs_in.TangentFragPos, u_HeightScale);
+
+ if (!IsMasked(u_MaskMap, texCoords))
+ {
+ vec3 normal = ComputeNormal(u_EnableNormalMapping, texCoords, fs_in.Normal, u_NormalMap, fs_in.TBN);
+ FRAGMENT_COLOR = ComputePBRLighting(texCoords, normal, ubo_ViewPos, fs_in.FragPos, u_Albedo, u_Metallic, u_Roughness, u_AlbedoMap, u_MetallicMap, u_RoughnessMap, u_AmbientOcclusionMap);
+ }
+ else
+ {
+ FRAGMENT_COLOR = vec4(0.0);
+ }
+}
diff --git a/Resources/Engine/Shaders/Unlit.glsl b/Resources/Engine/Shaders/Unlit.glsl
deleted file mode 100644
index e734b649..00000000
--- a/Resources/Engine/Shaders/Unlit.glsl
+++ /dev/null
@@ -1,47 +0,0 @@
-#shader vertex
-#version 430 core
-
-layout (location = 0) in vec3 geo_Pos;
-layout (location = 1) in vec2 geo_TexCoords;
-layout (location = 2) in vec3 geo_Normal;
-
-layout (std140) uniform EngineUBO
-{
- mat4 ubo_Model;
- mat4 ubo_View;
- mat4 ubo_Projection;
- vec3 ubo_ViewPos;
- float ubo_Time;
-};
-
-out VS_OUT
-{
- vec2 TexCoords;
-} vs_out;
-
-void main()
-{
- vs_out.TexCoords = geo_TexCoords;
-
- gl_Position = ubo_Projection * ubo_View * ubo_Model * vec4(geo_Pos, 1.0);
-}
-
-#shader fragment
-#version 430 core
-
-out vec4 FRAGMENT_COLOR;
-
-in VS_OUT
-{
- vec2 TexCoords;
-} fs_in;
-
-uniform vec4 u_Diffuse = vec4(1.0, 1.0, 1.0, 1.0);
-uniform sampler2D u_DiffuseMap;
-uniform vec2 u_TextureTiling = vec2(1.0, 1.0);
-uniform vec2 u_TextureOffset = vec2(0.0, 0.0);
-
-void main()
-{
- FRAGMENT_COLOR = texture(u_DiffuseMap, u_TextureOffset + vec2(mod(fs_in.TexCoords.x * u_TextureTiling.x, 1), mod(fs_in.TexCoords.y * u_TextureTiling.y, 1))) * u_Diffuse;
-}
\ No newline at end of file
diff --git a/Resources/Engine/Shaders/Unlit.ovfx b/Resources/Engine/Shaders/Unlit.ovfx
new file mode 100644
index 00000000..a01db0ca
--- /dev/null
+++ b/Resources/Engine/Shaders/Unlit.ovfx
@@ -0,0 +1,47 @@
+#shader vertex
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+
+layout (location = 0) in vec3 geo_Pos;
+layout (location = 1) in vec2 geo_TexCoords;
+
+out VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+} vs_out;
+
+void main()
+{
+ vs_out.FragPos = vec3(ubo_Model * vec4(geo_Pos, 1.0));
+ vs_out.TexCoords = geo_TexCoords;
+
+ gl_Position = ubo_Projection * ubo_View * vec4(vs_out.FragPos, 1.0);
+}
+
+#shader fragment
+#version 430 core
+
+#include ":Shaders/Common/Buffers/EngineUBO.ovfxh"
+#include ":Shaders/Common/Utils.ovfxh"
+
+in VS_OUT
+{
+ vec3 FragPos;
+ vec2 TexCoords;
+} fs_in;
+
+uniform vec4 u_Diffuse = vec4(1.0);
+uniform sampler2D u_DiffuseMap;
+uniform vec2 u_TextureTiling = vec2(1.0);
+uniform vec2 u_TextureOffset = vec2(0.0);
+
+out vec4 FRAGMENT_COLOR;
+
+void main()
+{
+ vec2 texCoords = TileAndOffsetTexCoords(fs_in.TexCoords, u_TextureTiling, u_TextureOffset);
+ FRAGMENT_COLOR = texture(u_DiffuseMap, texCoords) * u_Diffuse;
+}
diff --git a/Resources/premake5.lua b/Resources/premake5.lua
new file mode 100644
index 00000000..86373146
--- /dev/null
+++ b/Resources/premake5.lua
@@ -0,0 +1,3 @@
+project "Resources"
+ kind "SharedItems"
+ files { "Editor/**", "Engine/**", "**.lua" }
diff --git a/Sources/Overload/OvAnalytics/premake5.lua b/Sources/Overload/OvAnalytics/premake5.lua
index 3aaf8437..ed0b17f8 100644
--- a/Sources/Overload/OvAnalytics/premake5.lua
+++ b/Sources/Overload/OvAnalytics/premake5.lua
@@ -2,7 +2,7 @@ project "OvAnalytics"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvAudio/premake5.lua b/Sources/Overload/OvAudio/premake5.lua
index 8c80333c..8c9976e4 100644
--- a/Sources/Overload/OvAudio/premake5.lua
+++ b/Sources/Overload/OvAudio/premake5.lua
@@ -2,7 +2,7 @@ project "OvAudio"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", dependdir .. "irrklang/include", "%{wks.location}/OvDebug/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvTools/include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvCore/premake5.lua b/Sources/Overload/OvCore/premake5.lua
index 3c8bd69b..8f749ff9 100644
--- a/Sources/Overload/OvCore/premake5.lua
+++ b/Sources/Overload/OvCore/premake5.lua
@@ -2,7 +2,7 @@ project "OvCore"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", dependdir .. "glfw/include", dependdir .. "stb_image/include", dependdir .. "lua/include", dependdir .. "bullet3/include", dependdir .. "glew/include", dependdir .. "irrklang/include",
"%{wks.location}/OvAnalytics/include", "%{wks.location}/OvAudio/include", "%{wks.location}/OvDebug/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvPhysics/include",
"%{wks.location}/OvRendering/include", "%{wks.location}/OvTools/include", "%{wks.location}/OvUI/include", "%{wks.location}/OvWindowing/include" }
diff --git a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp b/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp
index 3e06beff..546610a3 100644
--- a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp
+++ b/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp
@@ -9,7 +9,8 @@
OvRendering::Resources::Shader* OvCore::ResourceManagement::ShaderManager::CreateResource(const std::string & p_path)
{
std::string realPath = GetRealPath(p_path);
- OvRendering::Resources::Shader* shader = OvRendering::Resources::Loaders::ShaderLoader::Create(realPath);
+ auto pathParserCallback = std::bind(&OvCore::ResourceManagement::ShaderManager::GetRealPath, this, std::placeholders::_1);
+ OvRendering::Resources::Shader* shader = OvRendering::Resources::Loaders::ShaderLoader::Create(realPath, pathParserCallback);
if (shader)
*reinterpret_cast(reinterpret_cast(shader) + offsetof(OvRendering::Resources::Shader, path)) = p_path; // Force the resource path to fit the given path
@@ -23,5 +24,6 @@ void OvCore::ResourceManagement::ShaderManager::DestroyResource(OvRendering::Res
void OvCore::ResourceManagement::ShaderManager::ReloadResource(OvRendering::Resources::Shader* p_resource, const std::string& p_path)
{
- OvRendering::Resources::Loaders::ShaderLoader::Recompile(*p_resource, p_path);
+ auto pathParserCallback = std::bind(&OvCore::ResourceManagement::ShaderManager::GetRealPath, this, std::placeholders::_1);
+ OvRendering::Resources::Loaders::ShaderLoader::Recompile(*p_resource, p_path, pathParserCallback);
}
diff --git a/Sources/Overload/OvDebug/premake5.lua b/Sources/Overload/OvDebug/premake5.lua
index f5841999..c599b58c 100644
--- a/Sources/Overload/OvDebug/premake5.lua
+++ b/Sources/Overload/OvDebug/premake5.lua
@@ -2,7 +2,7 @@ project "OvDebug"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", "%{wks.location}/OvTools/include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvEditor/premake5.lua b/Sources/Overload/OvEditor/premake5.lua
index 2722061c..37a2a20a 100644
--- a/Sources/Overload/OvEditor/premake5.lua
+++ b/Sources/Overload/OvEditor/premake5.lua
@@ -1,7 +1,7 @@
project "OvEditor"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl","**.cpp", "**.rc" }
+ files { "**.h", "**.inl","**.cpp", "**.lua", "**.rc" }
includedirs { "include", dependdir .. "glfw/include", dependdir .. "stb_image/include", dependdir .. "lua/include", dependdir .. "bullet3/include", dependdir .. "glew/include", dependdir .. "irrklang/include",
"%{wks.location}/OvAnalytics/include", "%{wks.location}/OvAudio/include", "%{wks.location}/OvCore/include",
"%{wks.location}/OvDebug/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvPhysics/include",
@@ -17,19 +17,21 @@ project "OvEditor"
debugdir "%{wks.location}/../../Build/%{cfg.buildcfg}"
postbuildcommands {
- "for /f \"delims=|\" %%i in ('dir /B /S \"%{wks.location}..\\..\\Dependencies\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{wks.location}..\\..\\Bin\\%{cfg.buildcfg}\\%{prj.name}\"",
+ "for /f \"delims=|\" %%i in ('dir /B /S \"%{dependdir}\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\"",
- "xcopy \"%{wks.location}\\..\\..\\Resources\\Engine\\*\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Data\\Engine\" /y /i /r /e /q",
- "xcopy \"%{wks.location}\\..\\..\\Resources\\Editor\\*\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Data\\Editor\" /y /i /r /e /q",
- "xcopy \"%{prj.location}\\Layout.ini\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Config\\\" /y /i",
+ "rmdir /s /q \"%{builddir}%{cfg.buildcfg}\\Data\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Debug\\%{prj.name}\\*.exe\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Debug\\%{prj.name}\\*.dll\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Release\\%{prj.name}\\*.exe\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Release\\%{prj.name}\\*.dll\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\\"",
+ "xcopy \"%{resdir}Engine\\*\" \"%{builddir}%{cfg.buildcfg}\\Data\\Engine\" /y /i /r /e /q",
+ "xcopy \"%{resdir}Editor\\*\" \"%{builddir}%{cfg.buildcfg}\\Data\\Editor\" /y /i /r /e /q",
+ "xcopy \"%{prj.location}\\Layout.ini\" \"%{builddir}%{cfg.buildcfg}\\Config\\\" /y /i",
- "xcopy \"%{wks.location}..\\..\\Bin\\Debug\\OvGame\\*.exe\" \"%{wks.location}..\\..\\Build\\%{cfg.buildcfg}\\Builder\\Development\" /y /i /c",
- "xcopy \"%{wks.location}..\\..\\Bin\\Release\\OvGame\\*.exe\" \"%{wks.location}..\\..\\Build\\%{cfg.buildcfg}\\Builder\\Shipping\" /y /i /c",
+ "xcopy /Y /I /Q /D \"%{outputdir}Debug\\%{prj.name}\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Debug\\%{prj.name}\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Release\\%{prj.name}\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Release\\%{prj.name}\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\\"",
+
+ "xcopy \"%{outputdir}Debug\\OvGame\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\" /y /i /c",
+ "xcopy \"%{outputdir}Release\\OvGame\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\" /y /i /c",
"EXIT /B 0"
}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp
index 1afcbde3..d1441e34 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp
@@ -625,14 +625,16 @@ bool OvEditor::Core::EditorActions::ImportAsset(const std::string& p_initialDest
std::string modelFormats = "*.fbx;*.obj;";
std::string textureFormats = "*.png;*.jpeg;*.jpg;*.tga";
- std::string shaderFormats = "*.glsl;";
+ std::string shaderFormats = "*.ovfx";
+ std::string shaderPartFormats = "*.ovfxh";
std::string soundFormats = "*.mp3;*.ogg;*.wav;";
OpenFileDialog selectAssetDialog("Select an asset to import");
selectAssetDialog.AddFileType("Any supported format", modelFormats + textureFormats + shaderFormats + soundFormats);
selectAssetDialog.AddFileType("Model (.fbx, .obj)", modelFormats);
selectAssetDialog.AddFileType("Texture (.png, .jpeg, .jpg, .tga)", textureFormats);
- selectAssetDialog.AddFileType("Shader (.glsl)", shaderFormats);
+ selectAssetDialog.AddFileType("Shader (.ovfx)", shaderFormats);
+ selectAssetDialog.AddFileType("Shader Parts (.ovfxh)", shaderPartFormats);
selectAssetDialog.AddFileType("Sound (.mp3, .ogg, .wav)", soundFormats);
selectAssetDialog.Show();
@@ -669,14 +671,16 @@ bool OvEditor::Core::EditorActions::ImportAssetAtLocation(const std::string& p_d
std::string modelFormats = "*.fbx;*.obj;";
std::string textureFormats = "*.png;*.jpeg;*.jpg;*.tga;";
- std::string shaderFormats = "*.glsl;";
+ std::string shaderFormats = "*.ovfx";
+ std::string shaderPartFormats = "*.ovfxh";
std::string soundFormats = "*.mp3;*.ogg;*.wav;";
OpenFileDialog selectAssetDialog("Select an asset to import");
selectAssetDialog.AddFileType("Any supported format", modelFormats + textureFormats + shaderFormats + soundFormats);
selectAssetDialog.AddFileType("Model (.fbx, .obj)", modelFormats);
selectAssetDialog.AddFileType("Texture (.png, .jpeg, .jpg, .tga)", textureFormats);
- selectAssetDialog.AddFileType("Shader (.glsl)", shaderFormats);
+ selectAssetDialog.AddFileType("Shader (.ovfx)", shaderFormats);
+ selectAssetDialog.AddFileType("Shader Parts (.ovfxh)", shaderPartFormats);
selectAssetDialog.AddFileType("Sound (.mp3, .ogg, .wav)", soundFormats);
selectAssetDialog.Show();
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp
index b07161ad..ff784c5e 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp
@@ -17,8 +17,7 @@ OvEditor::Core::EditorResources::EditorResources(const std::string& p_editorAsse
{
using namespace OvRendering::Resources::Loaders;
- std::string buttonsFolder = p_editorAssetsPath + "Textures\\Buttons\\";
- std::string iconsFolder = p_editorAssetsPath + "Textures\\Icons\\";
+ std::string iconsFolder = p_editorAssetsPath + "Icons\\";
std::string modelsFolder = p_editorAssetsPath + "Models\\";
std::string shadersFolder = p_editorAssetsPath + "Shaders\\";
@@ -147,6 +146,8 @@ OvEditor::Core::EditorResources::EditorResources(const std::string& p_editorAsse
m_textures["Bill_Ambient_Sphere_Light"] = TextureLoader::CreateFromMemory(reinterpret_cast(raw.data()), 128, 128, firstFilterBillboard, secondFilterBillboard, false);
}
+ m_textures["Icon_Shader_Part"] = TextureLoader::Create(iconsFolder + "puzzle.png", firstFilterEditor, secondFilterEditor, false);
+
/* Models */
m_models["Cube"] = ModelLoader::Create(modelsFolder + "Cube.fbx", modelParserFlags);
m_models["Cylinder"] = ModelLoader::Create(modelsFolder + "Cylinder.fbx", modelParserFlags);
@@ -161,9 +162,9 @@ OvEditor::Core::EditorResources::EditorResources(const std::string& p_editorAsse
m_models["Camera"] = ModelLoader::Create(modelsFolder + "Camera.fbx", modelParserFlags);
/* Shaders */
- m_shaders["Grid"] = ShaderLoader::Create(shadersFolder + "Grid.glsl");
- m_shaders["Gizmo"] = ShaderLoader::Create(shadersFolder + "Gizmo.glsl");
- m_shaders["Billboard"] = ShaderLoader::Create(shadersFolder + "Billboard.glsl");
+ m_shaders["Grid"] = ShaderLoader::Create(shadersFolder + "Grid.ovfx");
+ m_shaders["Gizmo"] = ShaderLoader::Create(shadersFolder + "Gizmo.ovfx");
+ m_shaders["Billboard"] = ShaderLoader::Create(shadersFolder + "Billboard.ovfx");
/* From memory */
{
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp
index 02daf4b5..3d984008 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp
@@ -206,6 +206,8 @@ class FolderContextualMenu : public BrowserItemContextualMenu
auto& createShaderMenu = createMenu.CreateWidget("Shader");
auto& createMaterialMenu = createMenu.CreateWidget("Material");
+ auto& createEmptyShaderMenu = createShaderMenu.CreateWidget("Empty");
+ auto& createPartialShaderMenu = createShaderMenu.CreateWidget("Partial");
auto& createStandardShaderMenu = createShaderMenu.CreateWidget("Standard template");
auto& createStandardPBRShaderMenu = createShaderMenu.CreateWidget("Standard PBR template");
auto& createUnlitShaderMenu = createShaderMenu.CreateWidget("Unlit template");
@@ -226,6 +228,8 @@ class FolderContextualMenu : public BrowserItemContextualMenu
auto& createUnlitMaterial = createUnlitMaterialMenu.CreateWidget("");
auto& createLambertMaterial = createLambertMaterialMenu.CreateWidget("");
+ auto& createEmptyShader = createEmptyShaderMenu.CreateWidget("");
+ auto& createPartialShader = createPartialShaderMenu.CreateWidget("");
auto& createStandardShader = createStandardShaderMenu.CreateWidget("");
auto& createStandardPBRShader = createStandardPBRShaderMenu.CreateWidget("");
auto& createUnlitShader = createUnlitShaderMenu.CreateWidget("");
@@ -238,6 +242,8 @@ class FolderContextualMenu : public BrowserItemContextualMenu
createUnlitShaderMenu.ClickedEvent += [&createUnlitShader] { createUnlitShader.content = ""; };
createLambertShaderMenu.ClickedEvent += [&createLambertShader] { createLambertShader.content = ""; };
createEmptyMaterialMenu.ClickedEvent += [&createEmptyMaterial] { createEmptyMaterial.content = ""; };
+ createEmptyShaderMenu.ClickedEvent += [&createEmptyShader] { createEmptyShader.content = ""; };
+ createPartialShaderMenu.ClickedEvent += [&createPartialShader] { createPartialShader.content = ""; };
createStandardMaterialMenu.ClickedEvent += [&createStandardMaterial] { createStandardMaterial.content = ""; };
createStandardPBRMaterialMenu.ClickedEvent += [&createStandardPBRMaterial] { createStandardPBRMaterial.content = ""; };
createUnlitMaterialMenu.ClickedEvent += [&createUnlitMaterial] { createUnlitMaterial.content = ""; };
@@ -280,6 +286,46 @@ class FolderContextualMenu : public BrowserItemContextualMenu
Close();
};
+ createEmptyShader.EnterPressedEvent += [this](std::string newShaderName)
+ {
+ size_t fails = 0;
+ std::string finalPath;
+
+ do
+ {
+ finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".ovfx";
+
+ ++fails;
+ } while (std::filesystem::exists(finalPath));
+
+ {
+ std::ofstream outfile(finalPath);
+ }
+
+ ItemAddedEvent.Invoke(finalPath);
+ Close();
+ };
+
+ createPartialShader.EnterPressedEvent += [this](std::string newShaderName)
+ {
+ size_t fails = 0;
+ std::string finalPath;
+
+ do
+ {
+ finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".ovfxh";
+
+ ++fails;
+ } while (std::filesystem::exists(finalPath));
+
+ {
+ std::ofstream outfile(finalPath);
+ }
+
+ ItemAddedEvent.Invoke(finalPath);
+ Close();
+ };
+
createStandardShader.EnterPressedEvent += [this](std::string newShaderName)
{
size_t fails = 0;
@@ -287,12 +333,12 @@ class FolderContextualMenu : public BrowserItemContextualMenu
do
{
- finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".glsl";
+ finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".ovfx";
++fails;
} while (std::filesystem::exists(finalPath));
- std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\Standard.glsl", finalPath);
+ std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\Standard.ovfx", finalPath);
ItemAddedEvent.Invoke(finalPath);
Close();
};
@@ -304,12 +350,12 @@ class FolderContextualMenu : public BrowserItemContextualMenu
do
{
- finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".glsl";
+ finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".ovfx";
++fails;
} while (std::filesystem::exists(finalPath));
- std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\StandardPBR.glsl", finalPath);
+ std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\StandardPBR.ovfx", finalPath);
ItemAddedEvent.Invoke(finalPath);
Close();
};
@@ -321,12 +367,12 @@ class FolderContextualMenu : public BrowserItemContextualMenu
do
{
- finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".glsl";
+ finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".ovfx";
++fails;
} while (std::filesystem::exists(finalPath));
- std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\Unlit.glsl", finalPath);
+ std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\Unlit.ovfx", finalPath);
ItemAddedEvent.Invoke(finalPath);
Close();
};
@@ -338,12 +384,12 @@ class FolderContextualMenu : public BrowserItemContextualMenu
do
{
- finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".glsl";
+ finalPath = filePath + '\\' + (!fails ? newShaderName : newShaderName + " (" + std::to_string(fails) + ')') + ".ovfx";
++fails;
} while (std::filesystem::exists(finalPath));
- std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\Lambert.glsl", finalPath);
+ std::filesystem::copy_file(EDITOR_CONTEXT(engineAssetsPath) + "Shaders\\Lambert.ovfx", finalPath);
ItemAddedEvent.Invoke(finalPath);
Close();
};
@@ -392,7 +438,7 @@ class FolderContextualMenu : public BrowserItemContextualMenu
{
std::ofstream outfile(finalPath);
- outfile << ":Shaders\\Standard.glsl" << std::endl; // Empty standard material content
+ outfile << ":Shaders\\Standard.ovfx" << std::endl; // Empty standard material content
}
ItemAddedEvent.Invoke(finalPath);
@@ -422,7 +468,7 @@ class FolderContextualMenu : public BrowserItemContextualMenu
{
std::ofstream outfile(finalPath);
- outfile << ":Shaders\\StandardPBR.glsl" << std::endl; // Empty standard material content
+ outfile << ":Shaders\\StandardPBR.ovfx" << std::endl; // Empty standard material content
}
ItemAddedEvent.Invoke(finalPath);
@@ -453,7 +499,7 @@ class FolderContextualMenu : public BrowserItemContextualMenu
{
std::ofstream outfile(finalPath);
- outfile << ":Shaders\\Unlit.glsl" << std::endl; // Empty unlit material content
+ outfile << ":Shaders\\Unlit.ovfx" << std::endl; // Empty unlit material content
}
ItemAddedEvent.Invoke(finalPath);
@@ -483,7 +529,7 @@ class FolderContextualMenu : public BrowserItemContextualMenu
{
std::ofstream outfile(finalPath);
- outfile << ":Shaders\\Lambert.glsl" << std::endl; // Empty unlit material content
+ outfile << ":Shaders\\Lambert.ovfx" << std::endl; // Empty unlit material content
}
ItemAddedEvent.Invoke(finalPath);
@@ -683,7 +729,7 @@ class ShaderContextualMenu : public FileContextualMenu
if (shaderManager.IsResourceRegistered(resourcePath))
{
/* Trying to recompile */
- OvRendering::Resources::Loaders::ShaderLoader::Recompile(*shaderManager[resourcePath], filePath);
+ shaderManager.ReloadResource(shaderManager[resourcePath], filePath);
}
else
{
@@ -697,6 +743,17 @@ class ShaderContextualMenu : public FileContextualMenu
}
};
+class ShaderPartContextualMenu : public FileContextualMenu
+{
+public:
+ ShaderPartContextualMenu(const std::string& p_filePath, bool p_protected = false) : FileContextualMenu(p_filePath, p_protected) {}
+
+ virtual void CreateList() override
+ {
+ FileContextualMenu::CreateList();
+ }
+};
+
class ModelContextualMenu : public PreviewableContextualMenu
{
public:
@@ -740,7 +797,7 @@ class ModelContextualMenu : public PreviewableContextualMenu:Shaders\\Standard.glsl" << std::endl; // Empty standard material content
+ outfile << ":Shaders\\Standard.ovfx" << std::endl; // Empty standard material content
}
DuplicateEvent.Invoke(finalPath);
@@ -768,7 +825,7 @@ class ModelContextualMenu : public PreviewableContextualMenu:Shaders\\StandardPBR.glsl" << std::endl; // Empty standard material content
+ outfile << ":Shaders\\StandardPBR.ovfx" << std::endl; // Empty standard material content
}
DuplicateEvent.Invoke(finalPath);
@@ -796,7 +853,7 @@ class ModelContextualMenu : public PreviewableContextualMenu:Shaders\\Unlit.glsl" << std::endl; // Empty standard material content
+ outfile << ":Shaders\\Unlit.ovfx" << std::endl; // Empty standard material content
}
DuplicateEvent.Invoke(finalPath);
@@ -824,7 +881,7 @@ class ModelContextualMenu : public PreviewableContextualMenu:Shaders\\Lambert.glsl" << std::endl; // Empty standard material content
+ outfile << ":Shaders\\Lambert.ovfx" << std::endl; // Empty standard material content
}
DuplicateEvent.Invoke(finalPath);
@@ -1222,6 +1279,7 @@ void OvEditor::Panels::AssetBrowser::ConsiderItem(OvUI::Widgets::Layout::TreeNod
case OvTools::Utils::PathParser::EFileType::MODEL: contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
case OvTools::Utils::PathParser::EFileType::TEXTURE: contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
case OvTools::Utils::PathParser::EFileType::SHADER: contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
+ case OvTools::Utils::PathParser::EFileType::SHADER_PART:contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
case OvTools::Utils::PathParser::EFileType::MATERIAL: contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
case OvTools::Utils::PathParser::EFileType::SCENE: contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
default: contextMenu = &clickableText.AddPlugin(path, protectedItem); break;
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp
index 919d86c8..63c1583e 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp
@@ -50,13 +50,13 @@ OvEditor::Panels::AssetView::AssetView
m_cameraController.LockTargetActor(*m_assetActor);
/* Default Material */
- m_defaultMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Standard.glsl"]);
+ m_defaultMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Standard.ovfx"]);
m_defaultMaterial.Set("u_Diffuse", OvMaths::FVector4(1.f, 1.f, 1.f, 1.f));
m_defaultMaterial.Set("u_Shininess", 100.0f);
m_defaultMaterial.Set("u_DiffuseMap", nullptr);
/* Texture Material */
- m_textureMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.glsl"]);
+ m_textureMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.ovfx"]);
m_textureMaterial.Set("u_Diffuse", OvMaths::FVector4(1.f, 1.f, 1.f, 1.f));
m_textureMaterial.SetBackfaceCulling(false);
m_textureMaterial.SetBlendable(true);
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/SceneView.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/SceneView.cpp
index c4033ee9..81403e78 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/SceneView.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/SceneView.cpp
@@ -25,7 +25,7 @@ OvEditor::Panels::SceneView::SceneView
m_camera.SetFar(5000.0f);
- m_fallbackMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.glsl"]);
+ m_fallbackMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.ovfx"]);
m_fallbackMaterial.Set("u_Diffuse", { 1.f, 0.f, 1.f, 1.0f });
m_fallbackMaterial.Set("u_DiffuseMap", nullptr);
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp b/Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp
index f21778fd..73c8f700 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp
@@ -77,7 +77,7 @@ class DebugCamerasRenderPass : public OvRendering::Core::ARenderPass
public:
DebugCamerasRenderPass(OvRendering::Core::CompositeRenderer& p_renderer) : OvRendering::Core::ARenderPass(p_renderer)
{
- m_cameraMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Lambert.glsl"]);
+ m_cameraMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Lambert.ovfx"]);
m_cameraMaterial.Set("u_Diffuse", FVector4(0.0f, 0.3f, 0.7f, 1.0f));
m_cameraMaterial.Set("u_DiffuseMap", nullptr);
}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp b/Sources/Overload/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp
index 13d56fa2..c115c8f2 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp
@@ -20,14 +20,14 @@ OvEditor::Rendering::OutlineRenderFeature::OutlineRenderFeature(OvRendering::Cor
OvRendering::Features::ARenderFeature(p_renderer)
{
/* Stencil Fill Material */
- m_stencilFillMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.glsl"]);
+ m_stencilFillMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.ovfx"]);
m_stencilFillMaterial.SetBackfaceCulling(true);
m_stencilFillMaterial.SetDepthTest(false);
m_stencilFillMaterial.SetColorWriting(false);
m_stencilFillMaterial.Set("u_DiffuseMap", nullptr);
/* Outline Material */
- m_outlineMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.glsl"]);
+ m_outlineMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.ovfx"]);
m_outlineMaterial.Set("u_DiffuseMap", nullptr);
m_outlineMaterial.SetDepthTest(false);
}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp b/Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp
index c1ba0ba8..d04363f6 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp
@@ -27,7 +27,7 @@ OvEditor::Rendering::PickingRenderPass::PickingRenderPass(OvRendering::Core::Com
m_gizmoPickingMaterial.Set("u_IsPickable", true);
/* Picking Material */
- m_actorPickingMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.glsl"]);
+ m_actorPickingMaterial.SetShader(EDITOR_CONTEXT(shaderManager)[":Shaders\\Unlit.ovfx"]);
m_actorPickingMaterial.Set("u_Diffuse", OvMaths::FVector4(1.f, 1.f, 1.f, 1.0f));
m_actorPickingMaterial.Set("u_DiffuseMap", nullptr);
m_actorPickingMaterial.SetFrontfaceCulling(false);
diff --git a/Sources/Overload/OvGame/premake5.lua b/Sources/Overload/OvGame/premake5.lua
index 4ac3a9cc..5dd43e6d 100644
--- a/Sources/Overload/OvGame/premake5.lua
+++ b/Sources/Overload/OvGame/premake5.lua
@@ -1,7 +1,7 @@
project "OvGame"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl","**.cpp", "**.rc" }
+ files { "**.h", "**.inl","**.cpp", "**.lua", "**.rc" }
includedirs { "include", dependdir .. "glfw/include", dependdir .. "stb_image/include", dependdir .. "lua/include", dependdir .. "bullet3/include", dependdir .. "glew/include", dependdir .. "irrklang/include",
"%{wks.location}/OvAnalytics/include", "%{wks.location}/OvAudio/include", "%{wks.location}/OvCore/include",
"%{wks.location}/OvDebug/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvPhysics/include",
@@ -16,12 +16,12 @@ project "OvGame"
characterset ("MBCS")
postbuildcommands {
- "for /f \"delims=|\" %%i in ('dir /B /S \"%{wks.location}..\\..\\Dependencies\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{wks.location}..\\..\\Bin\\%{cfg.buildcfg}\\%{prj.name}\"",
+ "for /f \"delims=|\" %%i in ('dir /B /S \"%{dependdir}\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{builddir}%{cfg.buildcfg}\\%{prj.name}\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Debug\\%{prj.name}\\*.exe\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Builder\\Development\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Debug\\%{prj.name}\\*.dll\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Builder\\Development\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Release\\%{prj.name}\\*.exe\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Builder\\Shipping\"",
- "xcopy /Y /I /Q /D \"%{wks.location}\\..\\..\\Bin\\Release\\%{prj.name}\\*.dll\" \"%{wks.location}\\..\\..\\Build\\%{cfg.buildcfg}\\Builder\\Shipping\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Debug\\%{prj.name}\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Debug\\%{prj.name}\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Release\\%{prj.name}\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\"",
+ "xcopy /Y /I /Q /D \"%{outputdir}Release\\%{prj.name}\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\"",
"EXIT /B 0"
}
diff --git a/Sources/Overload/OvGame/src/OvGame/Core/Game.cpp b/Sources/Overload/OvGame/src/OvGame/Core/Game.cpp
index 7ed2f6c6..694ba975 100644
--- a/Sources/Overload/OvGame/src/OvGame/Core/Game.cpp
+++ b/Sources/Overload/OvGame/src/OvGame/Core/Game.cpp
@@ -119,11 +119,6 @@ void OvGame::Core::Game::Update(float p_deltaTime)
if (m_context.inputManager->IsKeyPressed(OvWindowing::Inputs::EKey::KEY_F12))
m_showDebugInformation = !m_showDebugInformation;
- #ifdef _DEBUG
- if (m_context.inputManager->IsKeyPressed(OvWindowing::Inputs::EKey::KEY_R))
- OvRendering::Resources::Loaders::ShaderLoader::Recompile(*m_context.shaderManager[":Shaders\\Standard.glsl"], "Data\\Engine\\Shaders\\Standard.glsl");
- #endif
-
if (m_showDebugInformation)
{
m_fpsCounter.Update(p_deltaTime);
diff --git a/Sources/Overload/OvMaths/premake5.lua b/Sources/Overload/OvMaths/premake5.lua
index 1d646ff8..aa14650a 100644
--- a/Sources/Overload/OvMaths/premake5.lua
+++ b/Sources/Overload/OvMaths/premake5.lua
@@ -2,7 +2,7 @@ project "OvMaths"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvPhysics/premake5.lua b/Sources/Overload/OvPhysics/premake5.lua
index f04bdc87..f538013c 100644
--- a/Sources/Overload/OvPhysics/premake5.lua
+++ b/Sources/Overload/OvPhysics/premake5.lua
@@ -2,7 +2,7 @@ project "OvPhysics"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", dependdir .. "bullet3/include", "%{wks.location}/OvDebug/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvTools/include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h b/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h
index 5aeb9607..f07f2a1b 100644
--- a/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h
+++ b/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h
@@ -6,6 +6,8 @@
#pragma once
+#include
+
#include "OvRendering/Resources/Shader.h"
namespace OvRendering::Resources::Loaders
@@ -16,6 +18,8 @@ namespace OvRendering::Resources::Loaders
class ShaderLoader
{
public:
+ using FilePathParserCallback = std::function;
+
/**
* Disabled constructor
*/
@@ -24,13 +28,15 @@ namespace OvRendering::Resources::Loaders
/**
* Create a shader
* @param p_filePath
+ * @param p_pathParser
*/
- static Shader* Create(const std::string& p_filePath);
+ static Shader* Create(const std::string& p_filePath, FilePathParserCallback p_pathParser = nullptr);
/**
* Create a shader from source
* @param p_vertexShader
* @param p_fragmentShader
+ * @note Doesn't support path parsing/resolving
*/
static Shader* CreateFromSource(const std::string& p_vertexShader, const std::string& p_fragmentShader);
@@ -39,7 +45,7 @@ namespace OvRendering::Resources::Loaders
* @param p_shader
* @param p_filePath
*/
- static void Recompile(Shader& p_shader, const std::string& p_filePath);
+ static void Recompile(Shader& p_shader, const std::string& p_filePath, FilePathParserCallback p_pathParser = nullptr);
/**
* Destroy a shader
@@ -48,7 +54,9 @@ namespace OvRendering::Resources::Loaders
static bool Destroy(Shader*& p_shader);
private:
- static std::pair ParseShader(const std::string& p_filePath);
+ static bool ParseIncludeDirective(const std::string& line, std::string& includeFilePath);
+ static std::string LoadShader(const std::string& p_filePath, FilePathParserCallback p_pathParser);
+ static std::pair ParseShader(const std::string& p_filePath, FilePathParserCallback p_pathParser);
static uint32_t CreateProgram(const std::string& p_vertexShader, const std::string& p_fragmentShader);
static uint32_t CompileShader(uint32_t p_type, const std::string& p_source);
diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Shader.h b/Sources/Overload/OvRendering/include/OvRendering/Resources/Shader.h
index 5ddd44fe..8d309083 100644
--- a/Sources/Overload/OvRendering/include/OvRendering/Resources/Shader.h
+++ b/Sources/Overload/OvRendering/include/OvRendering/Resources/Shader.h
@@ -15,8 +15,6 @@
#include "OvRendering/Resources/UniformInfo.h"
-
-
namespace OvRendering::Resources
{
namespace Loaders { class ShaderLoader; }
diff --git a/Sources/Overload/OvRendering/premake5.lua b/Sources/Overload/OvRendering/premake5.lua
index ab201217..cc1f0aaa 100644
--- a/Sources/Overload/OvRendering/premake5.lua
+++ b/Sources/Overload/OvRendering/premake5.lua
@@ -2,7 +2,7 @@ project "OvRendering"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", dependdir .. "glew/include", dependdir .. "stb_image/include", dependdir .. "assimp/include", "%{wks.location}/OvDebug/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvTools/include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp b/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp
index 5c25dab9..429a5147 100644
--- a/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp
+++ b/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp
@@ -15,11 +15,11 @@
std::string OvRendering::Resources::Loaders::ShaderLoader::__FILE_TRACE;
-OvRendering::Resources::Shader* OvRendering::Resources::Loaders::ShaderLoader::Create(const std::string& p_filePath)
+OvRendering::Resources::Shader* OvRendering::Resources::Loaders::ShaderLoader::Create(const std::string& p_filePath, FilePathParserCallback p_pathParser)
{
__FILE_TRACE = p_filePath;
- std::pair source = ParseShader(p_filePath);
+ std::pair source = ParseShader(p_filePath, p_pathParser);
uint32_t programID = CreateProgram(source.first, source.second);
@@ -39,11 +39,11 @@ OvRendering::Resources::Shader* OvRendering::Resources::Loaders::ShaderLoader::C
return nullptr;
}
-void OvRendering::Resources::Loaders::ShaderLoader::Recompile(Shader& p_shader, const std::string& p_filePath)
+void OvRendering::Resources::Loaders::ShaderLoader::Recompile(Shader& p_shader, const std::string& p_filePath, FilePathParserCallback p_pathParser)
{
__FILE_TRACE = p_filePath;
- std::pair source = ParseShader(p_filePath);
+ std::pair source = ParseShader(p_filePath, p_pathParser);
/* Create the new program */
uint32_t newProgram = CreateProgram(source.first, source.second);
@@ -82,24 +82,85 @@ bool OvRendering::Resources::Loaders::ShaderLoader::Destroy(Shader*& p_shader)
return false;
}
-std::pair OvRendering::Resources::Loaders::ShaderLoader::ParseShader(const std::string& p_filePath)
+bool OvRendering::Resources::Loaders::ShaderLoader::ParseIncludeDirective(const std::string& line, std::string& includeFilePath)
{
- std::ifstream stream(p_filePath);
+ // Find the position of the opening and closing quotes
+ size_t start = line.find("\"");
+ size_t end = line.find("\"", start + 1);
- enum class ShaderType { NONE = -1, VERTEX = 0, FRAGMENT = 1 };
+ // Check if both quotes are found
+ if (start != std::string::npos && end != std::string::npos && end > start)
+ {
+ // Extract the included file path
+ includeFilePath = line.substr(start + 1, end - start - 1);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+std::string OvRendering::Resources::Loaders::ShaderLoader::LoadShader(const std::string& p_filePath, FilePathParserCallback p_pathParser)
+{
+ std::ifstream file(p_filePath);
+ if (!file.is_open())
+ {
+ OVLOG_ERROR("Error: Could not open shader file - " + p_filePath);
+ return "";
+ }
+
+ std::stringstream buffer;
std::string line;
+ while (std::getline(file, line))
+ {
+ if (line.find("#include") != std::string::npos)
+ {
+ // If the line contains #include, process the included file
+ std::string includeFilePath;
+ if (ParseIncludeDirective(line, includeFilePath))
+ {
+ // Recursively load the included file
+ const std::string realIncludeFilePath = p_pathParser ? p_pathParser(includeFilePath) : includeFilePath;
+ std::string includedShader = LoadShader(realIncludeFilePath, p_pathParser);
+ buffer << includedShader << std::endl;
+ }
+ else
+ {
+ OVLOG_ERROR("Error: Invalid #include directive in file - " + p_filePath);
+ }
+ }
+ else {
+ // If the line does not contain #include, just append it to the buffer
+ buffer << line << std::endl;
+ }
+ }
+
+ return buffer.str();
+}
+
+std::pair OvRendering::Resources::Loaders::ShaderLoader::ParseShader(const std::string& p_filePath, FilePathParserCallback p_pathParser)
+{
+ const std::string shaderCode = LoadShader(p_filePath, p_pathParser);
+
+ std::istringstream stream(shaderCode); // Add this line to create a stringstream from shaderCode
+ std::string line;
std::stringstream ss[2];
+ enum class ShaderType { NONE = -1, VERTEX = 0, FRAGMENT = 1 };
+
ShaderType type = ShaderType::NONE;
while (std::getline(stream, line))
{
if (line.find("#shader") != std::string::npos)
{
- if (line.find("vertex") != std::string::npos) type = ShaderType::VERTEX;
- else if (line.find("fragment") != std::string::npos) type = ShaderType::FRAGMENT;
+ if (line.find("vertex") != std::string::npos)
+ type = ShaderType::VERTEX;
+ else if (line.find("fragment") != std::string::npos)
+ type = ShaderType::FRAGMENT;
}
else if (type != ShaderType::NONE)
{
@@ -107,8 +168,8 @@ std::pair OvRendering::Resources::Loaders::ShaderLoade
}
}
- return
- {
+ return
+ {
ss[static_cast(ShaderType::VERTEX)].str(),
ss[static_cast(ShaderType::FRAGMENT)].str()
};
diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/PathParser.h b/Sources/Overload/OvTools/include/OvTools/Utils/PathParser.h
index 6fc60c99..758d21fb 100644
--- a/Sources/Overload/OvTools/include/OvTools/Utils/PathParser.h
+++ b/Sources/Overload/OvTools/include/OvTools/Utils/PathParser.h
@@ -23,6 +23,7 @@ namespace OvTools::Utils
MODEL,
TEXTURE,
SHADER,
+ SHADER_PART,
MATERIAL,
SOUND,
SCENE,
diff --git a/Sources/Overload/OvTools/premake5.lua b/Sources/Overload/OvTools/premake5.lua
index f31b1e9c..f6631c31 100644
--- a/Sources/Overload/OvTools/premake5.lua
+++ b/Sources/Overload/OvTools/premake5.lua
@@ -2,7 +2,7 @@ project "OvTools"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvTools/src/OvTools/Utils/PathParser.cpp b/Sources/Overload/OvTools/src/OvTools/Utils/PathParser.cpp
index 5969e235..4a0da637 100644
--- a/Sources/Overload/OvTools/src/OvTools/Utils/PathParser.cpp
+++ b/Sources/Overload/OvTools/src/OvTools/Utils/PathParser.cpp
@@ -88,6 +88,7 @@ std::string OvTools::Utils::PathParser::FileTypeToString(EFileType p_fileType)
case OvTools::Utils::PathParser::EFileType::MODEL: return "Model";
case OvTools::Utils::PathParser::EFileType::TEXTURE: return "Texture";
case OvTools::Utils::PathParser::EFileType::SHADER: return "Shader";
+ case OvTools::Utils::PathParser::EFileType::SHADER_PART:return "Shader_Part";
case OvTools::Utils::PathParser::EFileType::MATERIAL: return "Material";
case OvTools::Utils::PathParser::EFileType::SOUND: return "Sound";
case OvTools::Utils::PathParser::EFileType::SCENE: return "Scene";
@@ -105,7 +106,8 @@ OvTools::Utils::PathParser::EFileType OvTools::Utils::PathParser::GetFileType(co
if (ext == "fbx" || ext == "obj") return EFileType::MODEL;
else if (ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "tga") return EFileType::TEXTURE;
- else if (ext == "glsl") return EFileType::SHADER;
+ else if (ext == "ovfx") return EFileType::SHADER;
+ else if (ext == "ovfxh") return EFileType::SHADER_PART;
else if (ext == "ovmat") return EFileType::MATERIAL;
else if (ext == "wav" || ext == "mp3" || ext == "ogg") return EFileType::SOUND;
else if (ext == "ovscene") return EFileType::SCENE;
diff --git a/Sources/Overload/OvUI/premake5.lua b/Sources/Overload/OvUI/premake5.lua
index d1e6c121..f826271e 100644
--- a/Sources/Overload/OvUI/premake5.lua
+++ b/Sources/Overload/OvUI/premake5.lua
@@ -2,7 +2,7 @@ project "OvUI"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", dependdir .. "glfw/include", dependdir .. "glew/include", "%{wks.location}/OvMaths/include", "%{wks.location}/OvTools/include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/OvWindowing/premake5.lua b/Sources/Overload/OvWindowing/premake5.lua
index f4d1a7fb..0fb15a7f 100644
--- a/Sources/Overload/OvWindowing/premake5.lua
+++ b/Sources/Overload/OvWindowing/premake5.lua
@@ -2,7 +2,7 @@ project "OvWindowing"
kind "StaticLib"
language "C++"
cppdialect "C++17"
- files { "**.h", "**.inl", "**.cpp" }
+ files { "**.h", "**.inl", "**.cpp", "**.lua" }
includedirs { "include", dependdir .. "glfw/include", dependdir .. "stb_image/include", "%{wks.location}/OvTools/include" }
targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}")
objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}")
diff --git a/Sources/Overload/premake5.lua b/Sources/Overload/premake5.lua
index 65a20524..dbac74c4 100644
--- a/Sources/Overload/premake5.lua
+++ b/Sources/Overload/premake5.lua
@@ -6,6 +6,8 @@ workspace "Overload"
outputdir = "%{wks.location}/../../Bin/"
objoutdir = "%{wks.location}/../../Bin-Int/"
dependdir = "%{wks.location}/../../Dependencies/"
+builddir = "%{wks.location}/../../Build/"
+resdir = "%{wks.location}/../../Resources/"
include "OvAnalytics"
include "OvAudio"
@@ -19,4 +21,6 @@ include "OvUI"
include "OvWindowing"
include "OvEditor"
-include "OvGame"
\ No newline at end of file
+include "OvGame"
+
+include "../../Resources"