add Preetham sky; add point light and spot light;

This commit is contained in:
2026-03-16 01:44:23 +08:00
parent 3f56a6878d
commit 28d9a7dfb6
18 changed files with 723 additions and 129 deletions

View File

@ -1062,7 +1062,6 @@ namespace Prism
for (const auto& selectedEntity : m_SelectionContext)
{
if (alreadySelectedEntityID == selectedEntity.Entity.GetUUID()) continue;
OnSelected(selectedEntity);
return false;
}
}

View File

@ -75,11 +75,30 @@ const float Epsilon = 0.00001;
const int LightCount = 1;
const vec3 Fdielectric = vec3(0.04);
struct DirectionalLight
{
struct DirectionalLight {
vec3 Direction;
vec3 Radiance;
float Multiplier;
float Intensity;
bool CastShadows;
};
struct PointLight {
vec3 Position;
vec3 Radiance;
float Intensity;
float Range;
bool CastShadows;
};
struct SpotLight {
vec3 Position;
vec3 Direction;
vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
};
in VertexOutput
@ -100,6 +119,13 @@ layout(location = 1) out vec4 o_BloomColor;
uniform DirectionalLight u_DirectionalLights;
uniform vec3 u_CameraPosition;
uniform int u_PointLightCount;
uniform PointLight u_PointLights;
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights;
// PBR
uniform sampler2D u_AlbedoTexture;
uniform sampler2D u_NormalTexture;
@ -185,13 +211,104 @@ vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
}
// ---------- direction light ----------
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
{
vec3 L = normalize(-light.Direction);
vec3 Lradiance = light.Radiance * light.Intensity;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
}
vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
float attenuation = 1.0 / (dist * dist + 0.0001);
// 可选:范围平滑衰减
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor; // 平滑
attenuation *= rangeFactor;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
// 距离衰减
float attenuation = 1.0 / (dist * dist + 0.0001);
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor;
attenuation *= rangeFactor;
// 角度衰减(聚光锥)
float cosAngle = dot(-L, normalize(light.Direction)); // 光方向指向外,所以用 -L
if (cosAngle < light.OuterConeCos) return vec3(0.0);
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
attenuation *= angleFalloff;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
vec3 Lighting(vec3 F0)
{
vec3 result = vec3(0.0);
for(int i = 0; i < LightCount; i++)
{
vec3 Li = u_DirectionalLights.Direction;
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Multiplier;
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
vec3 Lh = normalize(Li + m_Params.View);
float cosLi = max(0.0, dot(m_Params.Normal, Li));
@ -216,9 +333,9 @@ vec3 RotateVectorAboutY(float angle, vec3 vec)
{
angle = radians(angle);
mat3 rotationMatrix = mat3(
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
);
return rotationMatrix * vec;
}
@ -232,9 +349,9 @@ vec3 IBL(vec3 F0, vec3 Lr)
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
vec3 specularIrradiance = textureLod(
u_EnvRadianceTex,
RotateVectorAboutY(u_EnvMapRotation, Lr),
m_Params.Roughness * u_EnvRadianceTexLevels
u_EnvRadianceTex,
RotateVectorAboutY(u_EnvMapRotation, Lr),
m_Params.Roughness * u_EnvRadianceTexLevels
).rgb;
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
@ -334,8 +451,15 @@ void main()
shadowFactor = 1.0 - shadow;
}
// directional light with shadow
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
if(u_PointLightCount > 0)
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
if(u_SpotLightCount > 0)
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;

View File

@ -61,13 +61,33 @@ const float Epsilon = 0.00001;
const int LightCount = 1;
const vec3 Fdielectric = vec3(0.04);
struct DirectionalLight
{
struct DirectionalLight {
vec3 Direction;
vec3 Radiance;
float Multiplier;
float Intensity;
bool CastShadows;
};
struct PointLight {
vec3 Position;
vec3 Radiance;
float Intensity;
float Range;
bool CastShadows;
};
struct SpotLight {
vec3 Position;
vec3 Direction;
vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
};
in VertexOutput
{
vec3 WorldPosition;
@ -84,6 +104,14 @@ layout(location = 0) out vec4 color;
layout(location = 1) out vec4 o_BloomColor;
uniform DirectionalLight u_DirectionalLights;
uniform int u_PointLightCount;
uniform PointLight u_PointLights;
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights;
uniform vec3 u_CameraPosition;
// PBR
@ -171,13 +199,102 @@ vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
}
// ---------- direction light ----------
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
{
vec3 L = normalize(-light.Direction);
vec3 Lradiance = light.Radiance * light.Intensity;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
}
vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
float attenuation = 1.0 / (dist * dist + 0.0001);
// 可选:范围平滑衰减
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor; // 平滑
attenuation *= rangeFactor;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
// 距离衰减
float attenuation = 1.0 / (dist * dist + 0.0001);
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor;
attenuation *= rangeFactor;
// 角度衰减(聚光锥)
float cosAngle = dot(-L, normalize(light.Direction)); // 光方向指向外,所以用 -L
if (cosAngle < light.OuterConeCos) return vec3(0.0);
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
attenuation *= angleFalloff;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
vec3 Lighting(vec3 F0)
{
vec3 result = vec3(0.0);
for(int i = 0; i < LightCount; i++)
{
vec3 Li = u_DirectionalLights.Direction;
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Multiplier;
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
vec3 Lh = normalize(Li + m_Params.View);
float cosLi = max(0.0, dot(m_Params.Normal, Li));
@ -202,9 +319,9 @@ vec3 RotateVectorAboutY(float angle, vec3 vec)
{
angle = radians(angle);
mat3 rotationMatrix = mat3(
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
);
return rotationMatrix * vec;
}
@ -218,9 +335,9 @@ vec3 IBL(vec3 F0, vec3 Lr)
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
vec3 specularIrradiance = textureLod(
u_EnvRadianceTex,
RotateVectorAboutY(u_EnvMapRotation, Lr),
m_Params.Roughness * u_EnvRadianceTexLevels
u_EnvRadianceTex,
RotateVectorAboutY(u_EnvMapRotation, Lr),
m_Params.Roughness * u_EnvRadianceTexLevels
).rgb;
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
@ -314,6 +431,7 @@ void main()
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
// Shadow
float shadowFactor = 1.0;
if (u_ShadowEnabled > 0.5) {
float shadow = calculateShadow(vs_Input.FragPosLightSpace, m_Params.Normal, u_DirectionalLights.Direction);
@ -321,7 +439,13 @@ void main()
}
// directional light with with shadow
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
if(u_PointLightCount > 0)
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
if(u_SpotLightCount > 0)
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;

View File

@ -0,0 +1,135 @@
#type compute
#version 450 core
const float PI = 3.141592;
layout(binding = 0, rgba32f) restrict writeonly uniform imageCube o_CubeMap;
uniform vec3 u_TurbidityAzimuthInclination;
vec3 GetCubeMapTexCoord()
{
vec2 st = gl_GlobalInvocationID.xy / vec2(imageSize(o_CubeMap));
vec2 uv = 2.0 * vec2(st.x, 1.0 - st.y) - vec2(1.0);
vec3 ret;
if (gl_GlobalInvocationID.z == 0) ret = vec3( 1.0, uv.y, -uv.x);
else if (gl_GlobalInvocationID.z == 1) ret = vec3( -1.0, uv.y, uv.x);
else if (gl_GlobalInvocationID.z == 2) ret = vec3( uv.x, 1.0, -uv.y);
else if (gl_GlobalInvocationID.z == 3) ret = vec3( uv.x, -1.0, uv.y);
else if (gl_GlobalInvocationID.z == 4) ret = vec3( uv.x, uv.y, 1.0);
else if (gl_GlobalInvocationID.z == 5) ret = vec3(-uv.x, uv.y, -1.0);
return normalize(ret);
}
#define PI 3.14159265359
float saturatedDot( in vec3 a, in vec3 b )
{
return max( dot( a, b ), 0.0 );
}
vec3 YxyToXYZ( in vec3 Yxy )
{
float Y = Yxy.r;
float x = Yxy.g;
float y = Yxy.b;
float X = x * ( Y / y );
float Z = ( 1.0 - x - y ) * ( Y / y );
return vec3(X,Y,Z);
}
vec3 XYZToRGB( in vec3 XYZ )
{
// CIE/E
mat3 M = mat3
(
2.3706743, -0.9000405, -0.4706338,
-0.5138850, 1.4253036, 0.0885814,
0.0052982, -0.0146949, 1.0093968
);
return XYZ * M;
}
vec3 YxyToRGB( in vec3 Yxy )
{
vec3 XYZ = YxyToXYZ( Yxy );
vec3 RGB = XYZToRGB( XYZ );
return RGB;
}
void calculatePerezDistribution( in float t, out vec3 A, out vec3 B, out vec3 C, out vec3 D, out vec3 E )
{
A = vec3( 0.1787 * t - 1.4630, -0.0193 * t - 0.2592, -0.0167 * t - 0.2608 );
B = vec3( -0.3554 * t + 0.4275, -0.0665 * t + 0.0008, -0.0950 * t + 0.0092 );
C = vec3( -0.0227 * t + 5.3251, -0.0004 * t + 0.2125, -0.0079 * t + 0.2102 );
D = vec3( 0.1206 * t - 2.5771, -0.0641 * t - 0.8989, -0.0441 * t - 1.6537 );
E = vec3( -0.0670 * t + 0.3703, -0.0033 * t + 0.0452, -0.0109 * t + 0.0529 );
}
vec3 calculateZenithLuminanceYxy( in float t, in float thetaS )
{
float chi = ( 4.0 / 9.0 - t / 120.0 ) * ( PI - 2.0 * thetaS );
float Yz = ( 4.0453 * t - 4.9710 ) * tan( chi ) - 0.2155 * t + 2.4192;
float theta2 = thetaS * thetaS;
float theta3 = theta2 * thetaS;
float T = t;
float T2 = t * t;
float xz =
( 0.00165 * theta3 - 0.00375 * theta2 + 0.00209 * thetaS + 0.0) * T2 +
(-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * thetaS + 0.00394) * T +
( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * thetaS + 0.25886);
float yz =
( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * thetaS + 0.0) * T2 +
(-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * thetaS + 0.00516) * T +
( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * thetaS + 0.26688);
return vec3( Yz, xz, yz );
}
vec3 calculatePerezLuminanceYxy( in float theta, in float gamma, in vec3 A, in vec3 B, in vec3 C, in vec3 D, in vec3 E )
{
return ( 1.0 + A * exp( B / cos( theta ) ) ) * ( 1.0 + C * exp( D * gamma ) + E * cos( gamma ) * cos( gamma ) );
}
vec3 calculateSkyLuminanceRGB( in vec3 s, in vec3 e, in float t )
{
vec3 A, B, C, D, E;
calculatePerezDistribution( t, A, B, C, D, E );
float thetaS = acos( saturatedDot( s, vec3(0,1,0) ) );
float thetaE = acos( saturatedDot( e, vec3(0,1,0) ) );
float gammaE = acos( saturatedDot( s, e ) );
vec3 Yz = calculateZenithLuminanceYxy( t, thetaS );
vec3 fThetaGamma = calculatePerezLuminanceYxy( thetaE, gammaE, A, B, C, D, E );
vec3 fZeroThetaS = calculatePerezLuminanceYxy( 0.0, thetaS, A, B, C, D, E );
vec3 Yp = Yz * ( fThetaGamma / fZeroThetaS );
return YxyToRGB( Yp );
}
layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
void main()
{
vec3 cubeTC = GetCubeMapTexCoord();
float turbidity = u_TurbidityAzimuthInclination.x;
float azimuth = u_TurbidityAzimuthInclination.y;;
float inclination = u_TurbidityAzimuthInclination.z;
vec3 sunDir = normalize( vec3( sin(inclination) * cos(azimuth), cos(inclination), sin(inclination) * sin(azimuth) ) );
vec3 viewDir = cubeTC;
vec3 skyLuminance = calculateSkyLuminanceRGB( sunDir, viewDir, turbidity );
vec4 color = vec4(skyLuminance * 0.05, 1.0);
imageStore(o_CubeMap, ivec3(gl_GlobalInvocationID), color);
}

View File

@ -5,12 +5,12 @@
layout(location = 0) in vec3 a_Position;
uniform mat4 u_ViewProjection;
uniform mat4 u_LightViewProjection;
uniform mat4 u_Transform;
void main()
{
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
gl_Position = u_LightViewProjection * u_Transform * vec4(a_Position, 1.0);
}
#type fragment

View File

@ -8,7 +8,7 @@ layout(location = 0) in vec3 a_Position;
layout(location = 5) in ivec4 a_BoneIndices;
layout(location = 6) in vec4 a_BoneWeights;
uniform mat4 u_ViewProjection;
uniform mat4 u_LightViewProjection;
uniform mat4 u_Transform;
const int MAX_BONES = 100;
@ -22,7 +22,7 @@ void main()
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
gl_Position = u_ViewProjection * u_Transform * localPosition;
gl_Position = u_LightViewProjection * u_Transform * localPosition;
}
#type fragment

View File

@ -5,6 +5,7 @@
#ifndef LOG_H
#define LOG_H
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
#include <spdlog/spdlog.h>

View File

@ -19,6 +19,7 @@
#include "Prism/Physics/PhysicsLayer.h"
#include "Prism/Physics/PhysicsWrappers.h"
#include "Prism/Renderer/Meshfactory.h"
#include "Prism/Renderer/Renderer3D.h"
#include "Prism/Script/ScriptEngine.h"
namespace Prism
@ -330,9 +331,19 @@ namespace Prism
isCreated = true;
SetSelected(newEntity);
}
if (ImGui::MenuItem("Point Light"))
{
auto newEntity = m_Context->CreateEntity("Point Light");
newEntity.AddComponent<PointLightComponent>();
isCreated = true;
SetSelected(newEntity);
}
if (ImGui::MenuItem("Spot Light"))
{
PM_CORE_WARN("not impl");
auto newEntity = m_Context->CreateEntity("Spot Light");
newEntity.AddComponent<SpotLightComponent>();
isCreated = true;
SetSelected(newEntity);
}
if (ImGui::MenuItem("Directional Light"))
{
@ -671,6 +682,8 @@ namespace Prism
ImGui::SeparatorText("Light Component");
AddComponentPopup<DirectionalLightComponent>("Directional Light");
AddComponentPopup<SkyLightComponent>("sky Light");
AddComponentPopup<PointLightComponent>("Point Light");
AddComponentPopup<SpotLightComponent>("Spot Light");
ImGui::SeparatorText("Other Component");
AddComponentPopup<CameraComponent>("Camera");
@ -991,12 +1004,51 @@ namespace Prism
UI::EndPropertyGrid();
});
DrawComponent<PointLightComponent>("Point Light", entity, [](PointLightComponent& pc)
{
UI::BeginPropertyGrid();
UI::PropertyColor("Radiance", pc.Radiance);
UI::Property("Intensity", pc.Intensity);
UI::Property("Radius", pc.Radius);
UI::EndPropertyGrid();
});
DrawComponent<SpotLightComponent>("Spot Light", entity, [](SpotLightComponent& sc)
{
UI::BeginPropertyGrid();
UI::PropertyColor("Radiance", sc.Radiance);
UI::Property("Intensity", sc.Intensity);
UI::Property("Range", sc.Range);
UI::Property("InnerConeAngle", sc.InnerConeAngle);
UI::Property("OuterConeAngle", sc.OuterConeAngle);
UI::EndPropertyGrid();
});
DrawComponent<SkyLightComponent>("Sky Light", entity, [](SkyLightComponent& slc)
{
UI::BeginPropertyGrid();
UI::PropertyAssetReference("Environment Map", slc.SceneEnvironment, AssetType::EnvMap);
UI::Property("Intensity", slc.Intensity, 0.01f, 0.0f, 5.0f);
ImGui::Separator();
const bool isEnable = UI::Property("Dynamic Sky", slc.DynamicSky);
if (slc.DynamicSky)
{
bool changed = UI::Property("Turbidity", slc.TurbidityAzimuthInclination.x, 0.01f);
changed |= UI::Property("Azimuth", slc.TurbidityAzimuthInclination.y, 0.01f);
changed |= UI::Property("Inclination", slc.TurbidityAzimuthInclination.z, 0.01f);
if (changed || isEnable)
{
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(slc.TurbidityAzimuthInclination.x, slc.TurbidityAzimuthInclination.y, slc.TurbidityAzimuthInclination.z);
slc.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
}
}
UI::EndPropertyGrid();
});

View File

@ -22,6 +22,33 @@ namespace Prism
return 0;
}
static GLenum SizedInternalFormat(TextureFormat format) {
switch (format) {
case TextureFormat::RGB: return GL_RGB8;
case TextureFormat::RGBA: return GL_RGBA8;
case TextureFormat::Float16: return GL_RGBA16F;
default: return 0;
}
}
static GLenum ImageFormat(TextureFormat format) {
switch (format) {
case TextureFormat::RGB: return GL_RGB;
case TextureFormat::RGBA: return GL_RGBA;
case TextureFormat::Float16: return GL_RGBA; // 根据实际情况调整
default: return 0;
}
}
static GLenum DataType(TextureFormat format) {
switch (format) {
case TextureFormat::RGB:
case TextureFormat::RGBA: return GL_UNSIGNED_BYTE;
case TextureFormat::Float16: return GL_HALF_FLOAT;
default: return 0;
}
}
// ******************************************
// Texture2D
@ -169,22 +196,41 @@ namespace Prism
// TextureCube
// ******************************************
OpenGLTextureCube::OpenGLTextureCube(TextureFormat format, uint32_t width, uint32_t height)
OpenGLTextureCube::OpenGLTextureCube(TextureFormat format, uint32_t width, uint32_t height, const void* data)
{
m_Width = width;
m_Height = height;
m_Format = format;
if (data)
{
const uint32_t size = width * height * 4 * 6; // six layers
m_LocalStorage = Buffer::Copy(data, size);
}
const GLint levels = CalculateMipMapCount(width, height);
Ref<OpenGLTextureCube> instance = this;
Renderer::Submit([instance, levels]() mutable {
glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &instance->m_RendererID);
glTextureStorage2D(instance->m_RendererID, levels, PrismToOpenGLTextureFormat(instance->m_Format), instance->m_Width, instance->m_Height);
glTextureStorage2D(instance->m_RendererID, levels,
SizedInternalFormat(instance->m_Format),
instance->m_Width, instance->m_Height);
if (instance->m_LocalStorage.Data)
{
GLenum imgFormat = ImageFormat(instance->m_Format);
GLenum dataType = DataType(instance->m_Format);
glTextureSubImage3D(instance->m_RendererID, 0,
0, 0, 0,
instance->m_Width, instance->m_Height, 6,
imgFormat, dataType, instance->m_LocalStorage.Data);
}
glTextureParameteri(instance->m_RendererID, GL_TEXTURE_MIN_FILTER, levels > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTextureParameteri(instance->m_RendererID, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
});
}

View File

@ -58,10 +58,13 @@ namespace Prism
std::string m_FilePath;
};
class OpenGLTextureCube : public TextureCube
{
public:
OpenGLTextureCube(TextureFormat format, uint32_t width, uint32_t height);
OpenGLTextureCube(TextureFormat format, uint32_t width, uint32_t height, const void* data);
OpenGLTextureCube(const std::string& path);
virtual ~OpenGLTextureCube();
@ -90,6 +93,7 @@ namespace Prism
uint8_t* m_ImageData = nullptr;
std::string m_FilePath;
Buffer m_LocalStorage;
};
}

View File

@ -27,7 +27,6 @@ namespace Prism
// Resources
Ref<MaterialInstance> SkyboxMaterial;
Ref<Environment> SceneEnvironment;
Light ActiveLight;
} SceneData;
Ref<Texture2D> BRDFLUT;
@ -124,6 +123,8 @@ namespace Prism
}GridData;
SceneRendererOptions Options;
Ref<TextureCube> BlackCubeTexture;
};
struct Renderer3DStats
@ -259,6 +260,10 @@ namespace Prism
s_Data.ShadowMapShader = Shader::Create("assets/shaders/ShadowMap.glsl");
s_Data.ShadowMapAnimShader = Shader::Create("assets/shaders/ShadowMap_Anim.glsl");
uint32_t blackTextureData[6] = { 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000 };
s_Data.BlackCubeTexture = TextureCube::Create(TextureFormat::RGBA, 1, 1, &blackTextureData);
}
void Renderer3D::SetViewportSize(uint32_t width, uint32_t height)
@ -385,6 +390,34 @@ namespace Prism
return { envFiltered, irradianceMap };
}
static Ref<Shader> preethamSkyShader;
Ref<TextureCube> Renderer3D::CreatePreethamSky(float turbidity, float azimuth, float inclination)
{
constexpr uint32_t cubemapSize = 2048;
Ref<TextureCube> environmentMap = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize);
if (!preethamSkyShader)
preethamSkyShader = Shader::Create("assets/shaders/PreethamSky.glsl");
preethamSkyShader->Bind();
const glm::vec3 TurbidityAzimuthInclination = { turbidity, azimuth, inclination};
preethamSkyShader->SetFloat3("u_TurbidityAzimuthInclination", TurbidityAzimuthInclination);
Renderer::Submit([environmentMap, cubemapSize]()
{
glBindImageTexture(0, environmentMap->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F);
glDispatchCompute(cubemapSize / 32, cubemapSize / 32, 6);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glGenerateTextureMipmap(environmentMap->GetRendererID());
});
return environmentMap;
}
/*
Ref<RenderPass> Renderer3D::GetFinalRenderPass()
{
@ -420,6 +453,11 @@ namespace Prism
return s_Data.Options;
}
Ref<TextureCube> Renderer3D::GetBlackCubeTexture()
{
return s_Data.BlackCubeTexture;
}
void Renderer3D::FlushDrawList(Ref<RenderPass>& outRenderPass)
{
@ -550,6 +588,11 @@ namespace Prism
// Set lights (TODO: move to light environment and don't do per mesh)
baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.SceneLightEnvironment.DirectionalLights[0]);
baseMaterial->Set("u_PointLightCount", s_Data.SceneData.SceneLightEnvironment.PointLightCount);
baseMaterial->Set("u_PointLights", s_Data.SceneData.SceneLightEnvironment.PointLights[0]);
baseMaterial->Set("u_SpotLightCount", s_Data.SceneData.SceneLightEnvironment.SpotLightCount);
baseMaterial->Set("u_SpotLights", s_Data.SceneData.SceneLightEnvironment.SpotLights[0]);
// baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.ActiveLight);
// shadow
@ -642,6 +685,10 @@ namespace Prism
// Set lights (TODO: move to light environment and don't do per mesh)
baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.SceneLightEnvironment.DirectionalLights[0]);
baseMaterial->Set("u_PointLightCount", s_Data.SceneData.SceneLightEnvironment.PointLightCount);
baseMaterial->Set("u_PointLights", s_Data.SceneData.SceneLightEnvironment.PointLights[0]);
baseMaterial->Set("u_SpotLightCount", s_Data.SceneData.SceneLightEnvironment.SpotLightCount);
baseMaterial->Set("u_SpotLights", s_Data.SceneData.SceneLightEnvironment.SpotLights[0]);
// baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.ActiveLight);
@ -881,59 +928,6 @@ namespace Prism
});
}
/*
void Renderer3D::BloomBlurPass()
{
int amount = 10;
int index = 0;
int horizontalCounter = 0, verticalCounter = 0;
for (int i = 0; i < amount; i++)
{
index = i % 2;
Renderer::BeginRenderPass(s_Data.BloomBlurPass[index]);
s_Data.BloomBlurShader->Bind();
s_Data.BloomBlurShader->SetBool("u_Horizontal", index);
if (index)
horizontalCounter++;
else
verticalCounter++;
if (i > 0)
{
auto fb = s_Data.BloomBlurPass[1 - index]->GetSpecification().TargetFramebuffer;
fb->BindTexture();
}
else
{
auto fb = s_Data.CompositePass->GetSpecification().TargetFramebuffer;
auto id = fb->GetColorAttachmentRendererID(1);
Renderer::Submit([id]()
{
glBindTextureUnit(0, id);
});
}
Renderer::SubmitFullscreenQuad(nullptr);
Renderer::EndRenderPass();
}
// Composite bloom
{
Renderer::BeginRenderPass(s_Data.BloomBlendPass);
s_Data.BloomBlendShader->Bind();
auto & adad =s_Data;
// s_Data.BloomBlendShader->SetFloat("u_Exposure", s_Data.SceneData.SceneCamera.Camera.GetExposure());
s_Data.CompositeShader->SetFloat("u_Exposure", s_Data.AutoExposureData.EnableAutoExposure ? s_Data.AutoExposureData.CurrentExposure : s_Data.SceneData.SceneCamera.Camera.GetExposure());
s_Data.BloomBlendShader->SetBool("u_EnableBloom", s_Data.EnableBloom);
s_Data.CompositePass->GetSpecification().TargetFramebuffer->BindTexture(0);
s_Data.BloomBlurPass[index]->GetSpecification().TargetFramebuffer->BindTexture(1);
Renderer::SubmitFullscreenQuad(nullptr);
Renderer::EndRenderPass();
}
}
*/
/*
struct FrustumBounds
{
@ -1066,11 +1060,34 @@ namespace Prism
}
}
*/
std::vector<glm::vec3> GetFrustumCornersWorldSpace(const SceneRendererCamera& sceneCamera)
{
std::vector<glm::vec3> corners(8);
const auto& proj = sceneCamera.Camera.GetProjectionMatrix();
const auto& view = sceneCamera.ViewMatrix;
const glm::mat4 invViewProj = glm::inverse(proj * view);
// 视锥体在 NDC 空间中的八个点
const std::vector<glm::vec4> ndcCorners = {
glm::vec4(-1, -1, -1, 1), glm::vec4( 1, -1, -1, 1),
glm::vec4( 1, 1, -1, 1), glm::vec4(-1, 1, -1, 1),
glm::vec4(-1, -1, 1, 1), glm::vec4( 1, -1, 1, 1),
glm::vec4( 1, 1, 1, 1), glm::vec4(-1, 1, 1, 1)
};
for (size_t i = 0; i < 8; ++i)
{
glm::vec4 worldPos = invViewProj * ndcCorners[i];
worldPos /= worldPos.w;
corners[i] = glm::vec3(worldPos);
}
return corners;
}
void Renderer3D::ShadowMapPass()
{
const auto& directionalLights = s_Data.SceneData.SceneLightEnvironment.DirectionalLights;
if (directionalLights[0].Multiplier == 0.0f || !directionalLights[0].CastShadows)
if (directionalLights[0].Intensity == 0.0f || !directionalLights[0].CastShadows)
{
for (int i = 0; i < 4; i++)
{
@ -1083,14 +1100,13 @@ namespace Prism
// TODO: this will not be hardcode
const glm::vec3 lightDir = glm::normalize(directionalLights[0].Direction); // 光线方向(从光源指向场景)
glm::vec3 lightPos = lightDir * 100.0f;
const glm::vec3 lightPos = lightDir * 100.0f;
const glm::mat4 lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
float orthoSize = 100.0f;
float nearPlane = 0.01f, farPlane = 1000.0f;
glm::mat4 lightProjection = glm::ortho(-orthoSize, orthoSize, -orthoSize, orthoSize, nearPlane, farPlane);
glm::mat4 lightSpaceMatrix = lightProjection * lightView;
const float orthoSize = 100.0f;
const float nearPlane = 0.01f, farPlane = 1000.0f;
const glm::mat4 lightProjection = glm::ortho(-orthoSize, orthoSize, -orthoSize, orthoSize, nearPlane, farPlane);
const glm::mat4 lightSpaceMatrix = lightProjection * lightView;
Renderer::Submit([]()
{
@ -1108,7 +1124,7 @@ namespace Prism
for (auto& dc : s_Data.ShadowPassDrawList)
{
Ref<Shader> shader = dc.mesh->IsAnimated() ? s_Data.ShadowMapAnimShader : s_Data.ShadowMapShader;
shader->SetMat4("u_ViewProjection", lightSpaceMatrix);
shader->SetMat4("u_LightViewProjection", lightSpaceMatrix);
Renderer::SubmitMeshWithShader(dc.mesh, dc.Transform, shader);
}
@ -1120,6 +1136,7 @@ namespace Prism
{
ImGui::Begin("Scene Renderer");
UI::Property("Composite Pass time", s_Stats.CompositePass);
UI::Property("Geometry Pass time", s_Stats.GeometryPass);
UI::Property("Shadow Pass time", s_Stats.ShadowPass);

View File

@ -41,6 +41,7 @@ namespace Prism
static void SubmitColliderMesh(const CapsuleColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
static void SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
static std::pair<Ref<TextureCube>, Ref<TextureCube>> CreateEnvironmentMap(const std::string& filepath);
static Ref<TextureCube> CreatePreethamSky(float turbidity, float azimuth, float inclination);
// static Ref<RenderPass> GetFinalRenderPass();
static Ref<RenderPass> GetGeoPass();
@ -52,6 +53,7 @@ namespace Prism
// static uint32_t GetFinalColorBufferRendererID();
static SceneRendererOptions& GetOptions();
static Ref<TextureCube> GetBlackCubeTexture();
private:
static void FlushDrawList(Ref<RenderPass>& outRenderPass);

View File

@ -49,12 +49,12 @@ namespace Prism
return nullptr;
}
Ref<TextureCube> TextureCube::Create(TextureFormat format, uint32_t width, uint32_t height)
Ref<TextureCube> TextureCube::Create(TextureFormat format, uint32_t width, uint32_t height, const void* data)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLTextureCube>::Create(format, width, height);
case RendererAPIType::OpenGL: return Ref<OpenGLTextureCube>::Create(format, width, height, data);
}
return nullptr;
}

View File

@ -72,7 +72,7 @@ namespace Prism
class PRISM_API TextureCube : public Texture
{
public:
static Ref<TextureCube> Create(TextureFormat format, uint32_t width, uint32_t height);
static Ref<TextureCube> Create(TextureFormat format, uint32_t width, uint32_t height, const void* data = nullptr);
static Ref<TextureCube> Create(const std::string& path);
virtual const std::string& GetPath() const = 0;

View File

@ -366,13 +366,6 @@ namespace Prism
};
// Lights
// TODO: Move to renderer
enum class LightType
{
None = 0, Directional = 1, Point = 2, Spot = 3
};
struct DirectionalLightComponent
{
glm::vec3 Radiance = { 1.0f, 1.0f, 1.0f };
@ -382,20 +375,45 @@ namespace Prism
float LightSize = 0.5f; // For PCSS
};
struct PointLightComponent
{
glm::vec3 Radiance = {1.0f, 1.0f, 1.0f};
float Radius = 10.0f;
float Intensity = 1.0f;
uint32_t CastShadows;
PointLightComponent() = default;
PointLightComponent(const PointLightComponent& other) = default;
};
// 聚光灯光源组件
struct SpotLightComponent
{
glm::vec3 Radiance = {1.0f, 1.0f, 1.0f};
float Intensity = 1.0f;
float Range = 10.0f;
float InnerConeAngle = glm::radians(30.0f); // 内锥角(半角)
float OuterConeAngle = glm::radians(45.0f); // 外锥角(半角)
bool CastShadows = true; // 聚光通常需要阴影
SpotLightComponent() = default;
SpotLightComponent(const SpotLightComponent& other) = default;
};
struct SkyLightComponent
{
Ref<Environment> SceneEnvironment;
float Intensity = 1.0f;
float Angle = 0.0f;
bool DynamicSky = false;
glm::vec3 TurbidityAzimuthInclination = { 2.0, 0.0, 0.0 };
SkyLightComponent(const Ref<Environment>& environment)
: SceneEnvironment(environment)
{
}
SkyLightComponent()
: SceneEnvironment(Ref<Environment>::Create())
{
}
SkyLightComponent() = default;
};
template<typename... Components>

View File

@ -23,6 +23,7 @@
#include "Prism/Core/Math/Math.h"
#include "Prism/Physics/Physics2D.h"
#include "Prism/Renderer/Renderer.h"
#include "Prism/Renderer/Renderer3D.h"
namespace Prism
{
@ -176,7 +177,7 @@ namespace Prism
for (const auto entity : lights)
{
auto [transformComponent, lightComponent] = lights.get<TransformComponent, DirectionalLightComponent>(entity);
const glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(1.0f));
const glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(0.0f, 0.0f, -1.0f));
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
{
direction,
@ -253,13 +254,12 @@ namespace Prism
// Process lights
{
m_LightEnvironment = LightEnvironment();
const auto lights = m_Registry.group<DirectionalLightComponent>(entt::get<TransformComponent>);
uint32_t directionalLightIndex = 0;
for (const auto entity : lights)
{
auto [transformComponent, lightComponent] = lights.get<TransformComponent, DirectionalLightComponent>(entity);
const glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(1.0f));
const glm::vec3 direction = glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(0.0f, 0.0f,1.0f));
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
{
direction,
@ -270,17 +270,69 @@ namespace Prism
}
}
{
const auto pointLights = m_Registry.group<PointLightComponent>(entt::get<TransformComponent>);
uint32_t pointLightIndex = 0;
for (const auto entity : pointLights)
{
if (pointLightIndex >= 8) break;
auto [transform, light] = pointLights.get<TransformComponent, PointLightComponent>(entity);
m_LightEnvironment.PointLights[pointLightIndex++] = {
transform.Translation,
light.Radiance,
light.Radius,
light.Intensity,
light.CastShadows,
};
m_LightEnvironment.PointLightCount ++;
}
}
{
const auto spotLights = m_Registry.group<SpotLightComponent>(entt::get<TransformComponent>);
uint32_t pointLightIndex = 0;
for (const auto entity : spotLights)
{
if (pointLightIndex >= 8) break;
auto [transform, light] = spotLights.get<TransformComponent, SpotLightComponent>(entity);
const glm::vec3 direction = glm::normalize(glm::mat3(transform.GetTransform()) * glm::vec3(0.0f, 0.0f, 1.0f));
const float innerCos = glm::cos(glm::radians(light.InnerConeAngle));
const float outerCos = glm::cos(glm::radians(light.OuterConeAngle));
m_LightEnvironment.SpotLights[pointLightIndex++] = {
transform.Translation,
direction,
light.Radiance,
light.Intensity,
light.Range,
innerCos,
outerCos,
light.CastShadows,
};
m_LightEnvironment.SpotLightCount ++;
}
}
// TODO: only one sky light at the moment!
{
const auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
if (lights.empty())
m_Environment = Ref<Environment>::Create(Renderer3D::GetBlackCubeTexture(), Renderer3D::GetBlackCubeTexture());
if (!lights.empty())
{
for (const auto entity : lights)
{
auto [transformComponent, skyLightComponent] = lights.get<TransformComponent, SkyLightComponent>(entity);
if (!skyLightComponent.SceneEnvironment && skyLightComponent.DynamicSky)
{
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(skyLightComponent.TurbidityAzimuthInclination.x, skyLightComponent.TurbidityAzimuthInclination.y, skyLightComponent.TurbidityAzimuthInclination.z);
skyLightComponent.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
}
m_Environment = skyLightComponent.SceneEnvironment;
m_EnvironmentIntensity = skyLightComponent.Intensity;
SetSkybox(m_Environment->RadianceMap);
if (m_Environment)
SetSkybox(m_Environment->RadianceMap);
}
}
}

View File

@ -18,27 +18,47 @@
namespace Prism
{
struct Light
{
glm::vec3 Direction{-0.314f, -0.941f, -0.209f};
glm::vec3 Radiance{ 0.0f, 0.0f, 0.0f};
float Multiplier = 1.0f;
};
struct DirectionalLight
struct GPUDirectionalLight
{
glm::vec3 Direction = { 0.0f, 0.0f, 0.0f };
glm::vec3 Radiance = { 0.0f, 0.0f, 0.0f };
float Multiplier = 0.0f;
float Intensity = 0.0f;
// C++ only
bool CastShadows = true;
};
struct GPUPointLight
{
glm::vec3 Position;
glm::vec3 Radiance;
float Intensity;
float Radius;
uint32_t CastShadows;
};
struct GPUSpotLight {
glm::vec3 Position;
glm::vec3 Direction;
glm::vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
// mat4 LightSpaceMatrix;
// int ShadowMapIndex;
};
struct LightEnvironment
{
DirectionalLight DirectionalLights[4];
GPUDirectionalLight DirectionalLights[4];
GPUPointLight PointLights[8]{};
int PointLightCount = 0;
GPUSpotLight SpotLights[8]{};
int SpotLightCount = 0;
};
@ -136,7 +156,7 @@ namespace Prism
Entity* m_Physics2DBodyEntityBuffer = nullptr;
Entity* m_Physics3DBodyEntityBuffer = nullptr;
LightEnvironment m_LightEnvironment;
LightEnvironment m_LightEnvironment{};
bool m_IsPlaying = false;

View File

@ -18,7 +18,7 @@ namespace Prism
virtual ~SceneCamera();
void SetPerspective(float verticalFOV, float nearClip = 0.01f, float farClip = 10000.0f);
void SetPerspective(float verticalFOV, float nearClip = 0.01f, float farClip = 1000.0f);
void SetOrthographic(float size, float nearClip = -1.0f, float farClip = 1.0f);
void SetViewportSize(uint32_t width, uint32_t height);