PBR Factored

This commit is contained in:
Confideo-IOM
2026-07-18 18:39:17 +01:00
parent b7aa111438
commit 120f18b1f9
19 changed files with 218 additions and 72 deletions
+9 -1
View File
@@ -4,12 +4,20 @@ bool HydraGame::Initialise()
{ {
// m_angle = 0.01f; // m_angle = 0.01f;
// m_sun_light_id = GetEngine()->ActorManager()->CreateActor<HydraPointLightActor>();
// GetEngine()->ActorManager()->InitialiseActor(m_sun_light_id);
// GetEngine()->ActorManager()->SetOrientation(m_sun_light_id, -0.5f, 0.0f, 0.0f);
// GetEngine()->ActorManager()->SetPosition(m_sun_light_id, glm::dvec3(0.0f, 4.0f, 10.0f));
m_sun_light_id = GetEngine()->ActorManager()->CreateActor<HydraPointLightActor>(); m_sun_light_id = GetEngine()->ActorManager()->CreateActor<HydraPointLightActor>();
GetEngine()->ActorManager()->InitialiseActor(m_sun_light_id); GetEngine()->ActorManager()->InitialiseActor(m_sun_light_id);
GetEngine()->ActorManager()->SetOrientation(m_sun_light_id, -0.5f, 0.0f, 0.0f); GetEngine()->ActorManager()->SetOrientation(m_sun_light_id, -0.5f, 0.0f, 0.0f);
GetEngine()->ActorManager()->SetPosition(m_sun_light_id, glm::dvec3(0.0f, 4.0f, 10.0f)); GetEngine()->ActorManager()->SetPosition(m_sun_light_id, glm::dvec3(0.0f, 4.0f, 10.0f));
m_other_light_id = GetEngine()->ActorManager()->CreateActor<HydraPointLightActor>();
GetEngine()->ActorManager()->InitialiseActor(m_other_light_id);
GetEngine()->ActorManager()->SetOrientation(m_other_light_id, -0.5f, 0.0f, 0.0f);
GetEngine()->ActorManager()->SetPosition(m_other_light_id, glm::dvec3(5.0f, 4.0f, 5.0f));
// m_other_light_id = GetEngine()->ActorManager()->CreateActor<HydraDirectionalLightActor>(); // m_other_light_id = GetEngine()->ActorManager()->CreateActor<HydraDirectionalLightActor>();
// GetEngine()->ActorManager()->InitialiseActor(m_other_light_id); // GetEngine()->ActorManager()->InitialiseActor(m_other_light_id);
// GetEngine()->ActorManager()->SetOrientation(m_other_light_id, 0.4f, 0.5f, 0.0f); // GetEngine()->ActorManager()->SetOrientation(m_other_light_id, 0.4f, 0.5f, 0.0f);
@@ -18,11 +18,17 @@ uint HYDRA_LIGHT_SPOT = 3;
struct light_structure struct light_structure
{ {
vec4 light_colour; vec4 ambient;
float light_intensity; vec4 diffuse;
uint chunk_id; vec4 specular;
uint light_type; float intensity;
float padding[1]; float constant;
float linear;
float quadratic;
float falloff;
float falloff_smooth;
uint entity_id;
uint light_type;
}; };
layout(binding = 0) uniform uniform_per_frame layout(binding = 0) uniform uniform_per_frame
@@ -105,32 +111,20 @@ vec3 fresnelSchlick(float cosTheta, vec3 F0)
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
} }
vec3 DirectionalShading(vec3 normal, vec3 diffuse, float roughness, float metallic, float light_intensity, vec3 lightColour, vec3 lightDir, vec3 lightPos, vec3 worldPos, vec3 viewPos) vec3 CalculatePBR(vec3 normal, vec3 view_pos, vec3 world_pos,vec3 light_dir, vec3 diffuse, vec3 radiance, float roughness, float metallic )
{ {
vec3 N = normalize(normal); vec3 N = normalize(normal);
vec3 V = normalize(viewPos - worldPos); vec3 V = normalize(view_pos - world_pos);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0 // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow) // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04); vec3 F0 = vec3(0.04);
F0 = mix(F0, diffuse, metallic); F0 = mix(F0, diffuse, metallic);
// reflectance equation
vec3 Lo = vec3(0.0);
// calculate per-light radiance // calculate per-light radiance
vec3 L = normalize(lightDir); vec3 L = normalize(light_dir);
vec3 H = normalize(V + L); vec3 H = normalize(V + L);
float distance = length(lightPos - worldPos);
float attenuation = 1.0;
// if(light_intensity > 0)
// {
// attenuation = light_intensity / (distance * distance);
// }
vec3 radiance = lightColour * attenuation;
// Cook-Torrance BRDF // Cook-Torrance BRDF
float NDF = DistributionGGX(N, H, roughness); float NDF = DistributionGGX(N, H, roughness);
@@ -156,61 +150,133 @@ vec3 DirectionalShading(vec3 normal, vec3 diffuse, float roughness, float metall
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.0);
// add to outgoing radiance Lo // add to outgoing radiance Lo
Lo += (kD * diffuse / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again vec3 Lo = (kD * diffuse / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
return Lo;
}
vec3 DirectionalShading(vec3 normal,
vec3 diffuse,
float roughness,
float metallic,
float light_intensity,
vec3 light_dir,
vec3 light_pos,
vec3 world_pos,
vec3 view_pos)
{
// vec3 N = normalize(normal);
// vec3 V = normalize(vieview_pos - world_pos);
// // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
// vec3 F0 = vec3(0.04);
// F0 = mix(F0, diffuse, metallic);
// // reflectance equation
// vec3 Lo = vec3(0.0);
// // calculate per-light radiance
// vec3 L = normalize(lightDir);
// vec3 H = normalize(V + L);
float distance = length(light_pos - world_pos);
float attenuation = 1.0;
vec3 radiance = diffuse * attenuation;
vec3 Lo = CalculatePBR(normal, view_pos, world_pos, light_dir, diffuse, radiance, roughness, metallic);
// // Cook-Torrance BRDF
// float NDF = DistributionGGX(N, H, roughness);
// float G = GeometrySmith(N, V, L, roughness);
// vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
// vec3 numerator = NDF * G * F;
// float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero
// vec3 specular = numerator / denominator;
// // kS is equal to Fresnel
// vec3 kS = F;
// // for energy conservation, the diffuse and specular light can't
// // be above 1.0 (unless the surface emits light); to preserve this
// // relationship the diffuse component (kD) should equal 1.0 - kS.
// vec3 kD = vec3(1.0) - kS;
// // multiply kD by the inverse metalness such that only non-metals
// // have diffuse lighting, or a linear blend if partly metal (pure metals
// // have no diffuse light).
// kD *= 1.0 - metallic;
// // scale light by NdotL
// float NdotL = max(dot(N, L), 0.0);
// // add to outgoing radiance Lo
// Lo += (kD * diffuse / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
return Lo; return Lo;
} }
vec3 PointShading(vec3 normal, vec3 diffuse, float roughness, float metallic, float light_intensity, vec3 lightColour, vec3 lightDir, vec3 lightPos, vec3 worldPos, vec3 viewPos) vec3 PointShading(vec3 normal,
vec3 diffuse,
float roughness,
float metallic,
float light_intensity,
vec3 light_pos,
float light_constant,
float light_linear,
float light_quadratic,
vec3 world_pos,
vec3 view_pos)
{ {
vec3 N = normalize(normal); // vec3 N = normalize(normal);
vec3 V = normalize(viewPos - worldPos); // vec3 V = normalize(viewPos - worldPos);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0 // // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow) // // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04); // vec3 F0 = vec3(0.04);
F0 = mix(F0, diffuse, metallic); // F0 = mix(F0, diffuse, metallic);
// reflectance equation // // reflectance equation
vec3 Lo = vec3(0.0); // vec3 Lo = vec3(0.0);
// calculate per-light radiance // // calculate per-light radiance
vec3 L = normalize(lightPos - worldPos); // vec3 L = normalize(lightPos - worldPos);
vec3 H = normalize(V + L); // vec3 H = normalize(V + L);
float distance = length(lightPos - worldPos); float distance = length(light_pos - world_pos);
float attenuation = 1.0; float attenuation = 1.0;
attenuation = light_intensity / (distance * distance); //attenuation = light_intensity / (distance * distance);
attenuation = light_intensity / (light_constant + (light_linear * distance) + (light_quadratic * distance * distance));
vec3 radiance = diffuse * attenuation;
vec3 light_dir = normalize(light_pos - world_pos);
vec3 Lo = CalculatePBR(normal, view_pos, world_pos, light_dir, diffuse, radiance, roughness, metallic);
vec3 radiance = lightColour * attenuation; // // Cook-Torrance BRDF
// float NDF = DistributionGGX(N, H, roughness);
// float G = GeometrySmith(N, V, L, roughness);
// vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
// Cook-Torrance BRDF // vec3 numerator = NDF * G * F;
float NDF = DistributionGGX(N, H, roughness); // float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero
float G = GeometrySmith(N, V, L, roughness); // vec3 specular = (numerator / denominator) * attenuation;
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
vec3 numerator = NDF * G * F; // // kS is equal to Fresnel
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero // vec3 kS = F;
vec3 specular = numerator / denominator; // // for energy conservation, the diffuse and specular light can't
// // be above 1.0 (unless the surface emits light); to preserve this
// // relationship the diffuse component (kD) should equal 1.0 - kS.
// vec3 kD = vec3(1.0) - kS;
// // multiply kD by the inverse metalness such that only non-metals
// // have diffuse lighting, or a linear blend if partly metal (pure metals
// // have no diffuse light).
// kD *= 1.0 - metallic;
// kS is equal to Fresnel // // scale light by NdotL
vec3 kS = F; // float NdotL = max(dot(N, L), 0.0);
// for energy conservation, the diffuse and specular light can't
// be above 1.0 (unless the surface emits light); to preserve this
// relationship the diffuse component (kD) should equal 1.0 - kS.
vec3 kD = vec3(1.0) - kS;
// multiply kD by the inverse metalness such that only non-metals
// have diffuse lighting, or a linear blend if partly metal (pure metals
// have no diffuse light).
kD *= 1.0 - metallic;
// scale light by NdotL // // add to outgoing radiance Lo
float NdotL = max(dot(N, L), 0.0); // Lo += (kD * diffuse / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
// add to outgoing radiance Lo
Lo += (kD * diffuse / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
return Lo; return Lo;
} }
@@ -245,21 +311,31 @@ void main()
vec3 Lo = vec3(0,0,0); vec3 Lo = vec3(0,0,0);
for(int i = 0; i < ubo_per_frame.light_count; i ++) for(int i = 0; i < ubo_per_frame.light_count; i ++)
{ {
mat4 model = model_matrix[lights[i].chunk_id]; mat4 model = model_matrix[lights[i].entity_id];
mat3 rot_mat = GetRotationOnlyMatrix(model); mat3 rot_mat = GetRotationOnlyMatrix(model);
vec3 light_direction = rot_mat * vec3(0,0,1); vec3 light_direction = rot_mat * vec3(0,0,1);
vec3 light_pos = model[3].xyz; vec3 light_pos = model[3].xyz;
if(lights[i].light_type == HYDRA_LIGHT_DIRECTIONAL) if(lights[i].light_type == HYDRA_LIGHT_DIRECTIONAL)
{ {
Lo+= DirectionalShading(normal, diffuse.xyz, rough, metal, lights[i].light_intensity, lights[i].light_colour.xyz, light_direction, light_pos, world_pos, ubo_per_frame.viewer_pos); Lo+= DirectionalShading(normal, diffuse.xyz, rough, metal, lights[i].intensity, light_direction, light_pos, world_pos, ubo_per_frame.viewer_pos);
} }
else if(lights[i].light_type == HYDRA_LIGHT_POINT) else if(lights[i].light_type == HYDRA_LIGHT_POINT)
{ {
Lo+= PointShading(normal, diffuse.xyz, rough, metal, lights[i].light_intensity, lights[i].light_colour.xyz, light_direction, light_pos, world_pos, ubo_per_frame.viewer_pos);
Lo+= PointShading(normal,
diffuse.xyz,
rough,
metal,
lights[i].intensity,
light_pos,
lights[i].constant,
lights[i].linear,
lights[i].quadratic,
world_pos,
ubo_per_frame.viewer_pos);
} }
//uFragColor = vec4(light_direction, 1);
} }
float lighting = 0; float lighting = 0;
@@ -271,7 +347,7 @@ void main()
float ao = 1; float ao = 1;
vec3 ambient = vec3(0.05) * diffuse.xyz * ao; vec3 ambient = vec3(0.05) * diffuse.xyz * ao;
vec3 output_color = ambient + Lo; vec3 output_color = Lo;
// HDR tonemapping // HDR tonemapping
output_color = output_color / (output_color + vec3(1.0)); output_color = output_color / (output_color + vec3(1.0));
@@ -28,8 +28,8 @@ void HydraDirectionalLightActor::InitialiseComponents()
//light_comp.light_id = GetEngine()->LightBufferManager()->CreateLight(light); //light_comp.light_id = GetEngine()->LightBufferManager()->CreateLight(light);
light_comp.light_colour = glm::vec4(1,1,1,1); light_comp.diffuse = glm::vec4(1,1,1,1);
light_comp.light_intensity = 100.0f; light_comp.intensity = 1.0f;
light_comp.light_type = static_cast<uint32_t>(HYDRA_LIGHT_TYPE::HYDRA_LIGHT_DIRECTIONAL); light_comp.light_type = static_cast<uint32_t>(HYDRA_LIGHT_TYPE::HYDRA_LIGHT_DIRECTIONAL);
light_comp.entity_id = GetID(); light_comp.entity_id = GetID();
@@ -20,8 +20,8 @@ void HydraPointLightActor::InitialiseComponents()
HydraLightComponent light_comp = {}; HydraLightComponent light_comp = {};
HydraECS *ecs = GetEngine()->ECS(); HydraECS *ecs = GetEngine()->ECS();
light_comp.light_colour = glm::vec4(1,1,1,1); light_comp.diffuse = glm::vec4(1,1,1,1);
light_comp.light_intensity = 10.0f; light_comp.intensity = 100.0f;
light_comp.light_type = static_cast<uint32_t>(HYDRA_LIGHT_TYPE::HYDRA_LIGHT_POINT); light_comp.light_type = static_cast<uint32_t>(HYDRA_LIGHT_TYPE::HYDRA_LIGHT_POINT);
light_comp.entity_id = GetID(); light_comp.entity_id = GetID();
@@ -0,0 +1,38 @@
#include "HydraSpotLightActor.h"
#include "../engine/HydraEngine.h"
#include "../actor/HydraActorManager.h"
#include "../task/HydraTask.h"
#include "../ecs/HydraECS.h"
#include "../ecs/components/HydraPositionComponent.h"
#include "../ecs/components/HydraMeshComponent.h"
#include "../ecs/components/HydraRenderableComponent.h"
#include "../ecs/components/HydraMaterialComponent.h"
#include "../ecs/components/HydraLightComponent.h"
#include "../buffer/HydraLightBufferManager.h"
#include "../buffer/HydraLightBuffer.h"
void HydraSpotLightActor::InitialiseComponents()
{
HydraLightComponent light_comp = {};
HydraECS *ecs = GetEngine()->ECS();
light_comp.diffuse = glm::vec4(1,1,1,1);
light_comp.intensity = 100.0f;
light_comp.light_type = static_cast<uint32_t>(HYDRA_LIGHT_TYPE::HYDRA_LIGHT_SPOT);
light_comp.entity_id = GetID();
ecs->AddComponent<HydraLightComponent>(GetID(), light_comp);
HydraPositionComponent position_component;
ecs->AddComponent<HydraPositionComponent>(GetID(), position_component);
}
void HydraSpotLightActor::Destroy()
{
}
@@ -0,0 +1,18 @@
#ifndef HYDRASPOTLIGHTACTOR
#define HYDRASPOTLIGHTACTOR
#include "HydraActor.h"
class CLASS_DEFINE HydraSpotLightActor : public HydraActor
{
private:
protected:
public:
virtual void InitialiseComponents() override;
virtual void Destroy() override;
};
#endif /* HYDRASPOTLIGHTACTOR */
@@ -4,11 +4,17 @@
struct HydraLightComponent struct HydraLightComponent
{ {
glm::vec4 light_colour; glm::vec4 ambient = {0.0f, 0.0f, 0.0f, 0.0f};
float light_intensity; glm::vec4 diffuse = {1.0f, 1.0f, 1.0f, 1.0f};
glm::vec4 specular = {1.0f, 1.0f, 1.0f, 1.0f};
float intensity = 1.0f;
float constant = 1.0f;
float linear = 0.7;
float quadratic = 1.8;
float falloff = 1.5;
float falloff_smooth = 0.0f;
HydraID entity_id; HydraID entity_id;
uint32_t light_type; uint32_t light_type;
float padding[1];
}; };
#endif /* HYDRAECSLIGHTCOMPONENT */ #endif /* HYDRAECSLIGHTCOMPONENT */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.