diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index ebe4144..4654e68 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -1164,7 +1164,7 @@ namespace Prism UpdateWindowTitle("Untitled Scene"); m_SceneFilePath = std::string(); - m_EditorCamera = EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 1000.0f)); + m_EditorCamera = EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 100.0f)); m_SelectionContext.clear(); } diff --git a/Editor/assets/shaders/BloomBlur.glsl b/Editor/assets/shaders/BloomBlur.glsl index 2ac3df4..a630d84 100644 --- a/Editor/assets/shaders/BloomBlur.glsl +++ b/Editor/assets/shaders/BloomBlur.glsl @@ -24,16 +24,16 @@ uniform sampler2D u_Texture; uniform bool u_Horizontal; // 未使用,可保留或移除 uniform bool u_FirstPass; // 是否进行阈值处理 uniform float u_Threshold; // 亮度阈值 +uniform int u_Quality; +uniform float u_Directions; // 模糊方向数 +uniform float u_Size; // 模糊半径 void main() { float Pi = 6.28318530718; // 2*PI - float Directions = 32.0; // 模糊方向数 - float Quality = 6.0; // 每个方向上的采样质量(采样次数) - float Size = 16.0; // 模糊半径 - vec2 Radius = Size / textureSize(u_Texture, 0); + vec2 Radius = u_Size / textureSize(u_Texture, 0); // 中心像素采样 vec3 centerColor = texture(u_Texture, v_TexCoord).rgb; @@ -50,9 +50,9 @@ void main() float totalSamples = 1.0; // 有效采样计数(中心像素已计入) // 周围像素采样 - for (float d = 0.0; d < Pi; d += Pi / Directions) + for (float d = 0.0; d < Pi; d += Pi / u_Directions) { - for (float i = 1.0 / Quality; i <= 1.0; i += 1.0 / Quality) + for (float i = 1.0 / u_Quality; i <= 1.0; i += 1.0 / u_Quality) { vec2 offset = vec2(cos(d), sin(d)) * Radius * i; vec3 sampleColor = texture(u_Texture, v_TexCoord + offset).rgb; diff --git a/Editor/assets/shaders/Lighting.glsl b/Editor/assets/shaders/Lighting.glsl new file mode 100644 index 0000000..7721db1 --- /dev/null +++ b/Editor/assets/shaders/Lighting.glsl @@ -0,0 +1,348 @@ +#type vertex +#version 430 core + +layout(location = 0) in vec3 a_Position; +layout(location = 1) in vec2 a_TexCoord; + +out vec2 v_TexCoord; + +void main() +{ + v_TexCoord = a_TexCoord; + gl_Position = vec4(a_Position.xy, 0.0, 1.0); +} + + +#type fragment +#version 430 core + +// ==================== 输入 ==================== +in vec2 v_TexCoord; + +// G-buffer 纹理 +uniform sampler2D u_AlbedoMetallic; // RGB: albedo, A: metallic +uniform sampler2D u_NormalRoughness; // RGB: normal (encoded), A: roughness +uniform sampler2D u_EmissiveAO; // RGB: emissive, A: AO +uniform sampler2D u_Depth; // depth + +// 相机参数 +uniform mat4 u_InvViewProj; // 逆视图投影矩阵,用于重建世界坐标 +uniform vec3 u_CameraPosition; + +// 光源结构体(与你的PBR着色器一致) +struct DirectionalLight { + vec3 Direction; + vec3 Radiance; + 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; +}; + +uniform DirectionalLight u_DirectionalLights; // 仅一个方向光 +uniform int u_PointLightCount; +uniform PointLight u_PointLights[16]; // 假设最多16个点光源 +uniform int u_SpotLightCount; +uniform SpotLight u_SpotLights[16]; // 最多16个聚光源 + +// IBL 相关 +uniform samplerCube u_EnvRadianceTex; +uniform samplerCube u_EnvIrradianceTex; +uniform sampler2D u_BRDFLUTTexture; +uniform float u_IBLContribution; +uniform float u_EnvMapRotation; + +// 阴影相关 +uniform sampler2D u_ShadowMap; +uniform float u_ShadowBias; +uniform float u_ShadowSoftness; +uniform int u_ShadowEnabled; +uniform float u_ShadowIntensity; // 阴影强度(0-1) +uniform mat4 u_LightSpaceMatrix; // 方向光光源空间矩阵 + +// 天空盒(可选) +uniform samplerCube u_Skybox; // 如果深度为1.0则采样天空盒 +uniform float u_SkyIntensity; +uniform float u_SkyTextureLod; + +// 输出 +layout(location = 0) out vec4 o_Color; + +// ==================== 常量 ==================== +const float PI = 3.14159265359; +const float Epsilon = 0.00001; +const vec3 Fdielectric = vec3(0.04); + + +// ==================== 工具函数 ==================== +// 从深度重建世界坐标 +vec3 worldPosFromDepth(vec2 uv, float depth) { + vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + vec4 worldPos = u_InvViewProj * clipPos; + return worldPos.xyz / worldPos.w; +} + +// 从深度重建世界空间方向(用于天空盒采样) +vec3 worldDirFromUV(vec2 uv) { + // 假设深度为1.0时,得到远平面方向 + vec4 clipPos = vec4(uv * 2.0 - 1.0, 1.0, 1.0); + vec4 worldPos = u_InvViewProj * clipPos; + return normalize(worldPos.xyz / worldPos.w); +} + +// 旋转向量(绕Y轴) +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)) + ); + return rotationMatrix * vec; +} + +// ==================== PBR 函数(复用你的代码) ==================== +float ndfGGX(float cosLh, float roughness) { + float alpha = roughness * roughness; + float alphaSq = alpha * alpha; + float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0; + return alphaSq / (PI * denom * denom); +} + +float GeometrySchlickGGX(float NdotV, float roughness) { + float r = (roughness + 1.0); + float k = (r * r) / 8.0; + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + return nom / 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(vec3 F0, float cosTheta) { + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} + +vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness) { + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); +} + +// ---------- 方向光 ---------- +vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic) { + vec3 L = normalize(-light.Direction); + vec3 Lradiance = light.Radiance * light.Intensity; + + vec3 Lh = normalize(L + V); + float cosLi = max(dot(N, L), 0.0); + float cosLh = max(dot(N, Lh), 0.0); + + vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0)); + float D = ndfGGX(cosLh, roughness); + float G = GeometrySmith(N, V, L, roughness); + + vec3 kd = (1.0 - F) * (1.0 - metallic); + vec3 diffuseBRDF = kd * albedo; + vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV); + + return (diffuseBRDF + specularBRDF) * Lradiance * cosLi; +} + +// ---------- 点光源 ---------- +vec3 ComputePointLight(PointLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, 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 + V); + float cosLi = max(dot(N, L), 0.0); + float cosLh = max(dot(N, Lh), 0.0); + + vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0)); + float D = ndfGGX(cosLh, roughness); + float G = GeometrySmith(N, V, L, roughness); + + vec3 kd = (1.0 - F) * (1.0 - metallic); + vec3 diffuseBRDF = kd * albedo; + vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV); + + return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation; +} + +// ---------- 聚光源 ---------- +vec3 ComputeSpotLight(SpotLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, 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)); + 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 + V); + float cosLi = max(dot(N, L), 0.0); + float cosLh = max(dot(N, Lh), 0.0); + + vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0)); + float D = ndfGGX(cosLh, roughness); + float G = GeometrySmith(N, V, L, roughness); + + vec3 kd = (1.0 - F) * (1.0 - metallic); + vec3 diffuseBRDF = kd * albedo; + vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV); + + return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation; +} + +// ---------- IBL ---------- +vec3 IBL(vec3 F0, vec3 N, vec3 V, float NdotV, float roughness, float metallic, vec3 albedo) { + vec3 irradiance = texture(u_EnvIrradianceTex, N).rgb; + vec3 F = fresnelSchlickRoughness(F0, NdotV, roughness); + vec3 kd = (1.0 - F) * (1.0 - metallic); + vec3 diffuseIBL = albedo * irradiance; + + vec3 R = 2.0 * NdotV * N - V; // 反射向量 + int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex); + vec3 specularIrradiance = textureLod( + u_EnvRadianceTex, + RotateVectorAboutY(u_EnvMapRotation, R), + roughness * u_EnvRadianceTexLevels + ).rgb; + + vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(NdotV, 1.0 - roughness)).rg; + vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y); + + return kd * diffuseIBL + specularIBL; +} + +// ---------- 阴影 ---------- +float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) { + if (u_ShadowEnabled == 0) return 0.0; + + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + projCoords = projCoords * 0.5 + 0.5; + + if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0) + return 0.0; + + float closestDepth = texture(u_ShadowMap, projCoords.xy).r; + float currentDepth = projCoords.z; + + float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1); + + float shadow = 0.0; + vec2 texelSize = 1.0 / textureSize(u_ShadowMap, 0); + int pcfRange = int(u_ShadowSoftness); + int sampleCount = 0; + + for (int x = -pcfRange; x <= pcfRange; ++x) { + for (int y = -pcfRange; y <= pcfRange; ++y) { + float pcfDepth = texture(u_ShadowMap, projCoords.xy + vec2(x, y) * texelSize).r; + shadow += (currentDepth - bias > pcfDepth) ? 1.0 : 0.0; + sampleCount++; + } + } + shadow /= float(sampleCount); + + return shadow * u_ShadowIntensity; // 应用阴影强度 +} + +// ==================== 主函数 ==================== +void main() { + vec2 uv = v_TexCoord; + float depth = texture(u_Depth, uv).r; + + if (depth >= 1.0) { + vec3 dir = worldDirFromUV(uv); + vec3 skyColor = textureLod(u_Skybox, dir, u_SkyTextureLod).rgb * u_SkyIntensity; + o_Color = vec4(skyColor, 1.0); + return; + } + + vec4 albedoMetal = texture(u_AlbedoMetallic, uv); + vec4 normalRough = texture(u_NormalRoughness, uv); + vec4 emissiveAO = texture(u_EmissiveAO, uv); + + vec3 albedo = albedoMetal.rgb; + float metallic = albedoMetal.a; + vec3 normal = normalRough.rgb * 2.0 - 1.0; + float roughness = normalRough.a; + vec3 emissive = emissiveAO.rgb; + float ao = emissiveAO.a; + + vec3 worldPos = worldPosFromDepth(uv, depth); + vec3 V = normalize(u_CameraPosition - worldPos); + float NdotV = clamp(dot(normal, V), 0.0, 1.0); + + vec3 F0 = mix(Fdielectric, albedo, metallic); + + vec3 Lo = vec3(0.0); + + // Direction Light + if (u_DirectionalLights.Intensity > 0.0) { + Lo += ComputeDirectionalLight(u_DirectionalLights, F0, normal, V, NdotV, albedo, roughness, metallic); + } + + // Point Light + for (int i = 0; i < u_PointLightCount; ++i) { + Lo += ComputePointLight(u_PointLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos); + } + + // Spot light + for (int i = 0; i < u_SpotLightCount; ++i) { + Lo += ComputeSpotLight(u_SpotLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos); + } + + float shadowFactor = 1.0; + if (u_ShadowEnabled > 0 && u_DirectionalLights.CastShadows && u_DirectionalLights.Intensity > 0.0) { + vec4 fragPosLightSpace = u_LightSpaceMatrix * vec4(worldPos, 1.0); + float shadow = calculateShadow(fragPosLightSpace, normal, u_DirectionalLights.Direction); + shadowFactor = 1.0 - shadow; + } + Lo *= shadowFactor; + + // 计算 IBL + vec3 ibl = IBL(F0, normal, V, NdotV, roughness, metallic, albedo) * u_IBLContribution; + + vec3 finalColor = Lo + ibl + emissive; + + o_Color = vec4(finalColor, 1.0); +} \ No newline at end of file diff --git a/Editor/assets/shaders/PBRShader_Anim.glsl b/Editor/assets/shaders/PBRShader_Anim.glsl index c3e5611..845d831 100644 --- a/Editor/assets/shaders/PBRShader_Anim.glsl +++ b/Editor/assets/shaders/PBRShader_Anim.glsl @@ -161,6 +161,13 @@ uniform float u_ShadowSoftness; uniform float u_ShadowIntensity; uniform int u_ShadowEnabled; +// Emissive +uniform sampler2D u_EmissiveTexture; +uniform float u_EmissiveTexToggle; +uniform vec3 u_EmissiveColor; +uniform float u_EmissiveIntensity; + + struct PBRParameters { vec3 Albedo; @@ -425,7 +432,16 @@ float ComputeShadow(vec4 fragPosLightSpace, float NdotL) void main() { - m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor; + float alpha = 1.0; + if (u_AlbedoTexToggle > 0.5) { + vec4 albedoWithAlpha = texture(u_AlbedoTexture, vs_Input.TexCoord); + m_Params.Albedo = albedoWithAlpha.rgb; + alpha = albedoWithAlpha.a; + } else { + m_Params.Albedo = u_AlbedoColor; + alpha = 1.0; + } + m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness; m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; m_Params.Roughness = max(m_Params.Roughness, 0.05); @@ -463,7 +479,16 @@ void main() vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution; - color = vec4(lightContribution + iblContribution, 1.0); + vec3 emissive = u_EmissiveColor; + if (u_EmissiveTexToggle > 0.5) { + emissive = texture(u_EmissiveTexture, vs_Input.TexCoord).rgb; + } + emissive *= u_EmissiveIntensity; + + vec3 finalRGB = lightContribution + iblContribution + emissive; + vec4 finalColor = vec4(finalRGB, alpha); + + color = finalColor; // Bloom float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); diff --git a/Editor/assets/shaders/PBRShader_Static.glsl b/Editor/assets/shaders/PBRShader_Static.glsl index 6aaed4c..a755049 100644 --- a/Editor/assets/shaders/PBRShader_Static.glsl +++ b/Editor/assets/shaders/PBRShader_Static.glsl @@ -55,6 +55,12 @@ void main() #type fragment #version 430 core +layout(location = 0) out vec4 outAlbedoMetal; +layout(location = 1) out vec4 outNormalRoughness; +layout(location = 2) out vec4 outEmissiveAO; +layout(location = 3) out vec4 outColor; +layout(location = 4) out vec4 outBloomColor; + const float PI = 3.141592; const float Epsilon = 0.00001; @@ -100,8 +106,8 @@ in VertexOutput vec4 FragPosLightSpace; } vs_Input; -layout(location = 0) out vec4 color; -layout(location = 1) out vec4 o_BloomColor; + +uniform bool u_GBufferMode; uniform DirectionalLight u_DirectionalLights; @@ -149,6 +155,12 @@ uniform float u_ShadowSoftness; uniform float u_ShadowIntensity; uniform int u_ShadowEnabled; +// Emissive +uniform sampler2D u_EmissiveTexture; +uniform float u_EmissiveTexToggle; +uniform vec3 u_EmissiveColor; +uniform float u_EmissiveIntensity; + struct PBRParameters { vec3 Albedo; @@ -411,19 +423,44 @@ float ComputeShadow(vec4 fragPosLightSpace, float NdotL) void main() { - m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor; - m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness; - m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; - m_Params.Roughness = max(m_Params.Roughness, 0.05); + // === 1. 采样基础属性(所有模式都需要) === + vec4 albedoWithAlpha = texture(u_AlbedoTexture, vs_Input.TexCoord); + vec3 albedo = u_AlbedoTexToggle > 0.5 ? albedoWithAlpha.rgb : u_AlbedoColor; + float alpha = u_AlbedoTexToggle > 0.5 ? albedoWithAlpha.a : 1.0; - // normal - m_Params.Normal = normalize(vs_Input.Normal); + float metallic = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness; + float roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; + roughness = max(roughness, 0.05); + + // === 2. 法线计算(世界空间) === + vec3 normal = normalize(vs_Input.Normal); if (u_NormalTexToggle > 0.5) { - m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0); - m_Params.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal); + vec3 tangentNormal = texture(u_NormalTexture, vs_Input.TexCoord).rgb * 2.0 - 1.0; + normal = normalize(vs_Input.WorldNormals * tangentNormal); } + // === 3. 自发光计算 === + vec3 emissive = u_EmissiveColor; + if (u_EmissiveTexToggle > 0.5) + emissive = texture(u_EmissiveTexture, vs_Input.TexCoord).rgb; + emissive *= u_EmissiveIntensity; + + // === 4. GBuffer 模式:直接输出到多个目标 === + if (u_GBufferMode) + { + outAlbedoMetal = vec4(albedo, metallic); + outNormalRoughness = vec4(normal * 0.5 + 0.5, roughness); + outEmissiveAO = vec4(emissive, 1.0); // AO 暂设为 1.0 + return; // 提前结束 + } + + // === 5. 非 GBuffer 模式:继续 PBR 光照计算 === + // 填充 PBRParameters + m_Params.Albedo = albedo; + m_Params.Metalness = metallic; + m_Params.Roughness = roughness; + m_Params.Normal = normal; m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition); m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0); @@ -449,9 +486,12 @@ void main() vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution; - color = vec4(lightContribution + iblContribution, 1.0); + vec3 finalRGB = lightContribution + iblContribution + emissive; + vec4 finalColor = vec4(finalRGB, alpha); + + outColor = finalColor; // Bloom - float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); - o_BloomColor = brightness > u_BloomThreshold ? color : vec4(0.0, 0.0, 0.0, 1.0); + float brightness = dot(finalColor.rgb, vec3(0.2126, 0.7152, 0.0722)); + outBloomColor = brightness > u_BloomThreshold ? finalColor : vec4(0.0, 0.0, 0.0, 1.0); } diff --git a/Editor/assets/shaders/SceneComposite.glsl b/Editor/assets/shaders/SceneComposite.glsl index b004448..63df49a 100644 --- a/Editor/assets/shaders/SceneComposite.glsl +++ b/Editor/assets/shaders/SceneComposite.glsl @@ -17,13 +17,11 @@ void main() #version 430 layout(location = 0) out vec4 o_Color; -layout(location = 1) out vec4 o_BloomTexture; in vec2 v_TexCoord; -uniform sampler2DMS u_Texture; -uniform sampler2D u_BloomTexture; - +uniform sampler2D u_HDRTexture; // 来自 LightingPass 的 HDR 颜色 +uniform sampler2D u_BloomTexture; // 来自 BloomBlendPass 的 Bloom 纹理 uniform bool u_EnableAutoExposure; uniform float u_ManualExposure; @@ -32,73 +30,36 @@ layout(std430, binding = 2) buffer Exposure float u_Exposure; }; -uniform int u_TextureSamples; - uniform bool u_EnableBloom; -uniform float u_BloomThreshold; -const float uFar = 1.0; - -vec4 SampleTexture(sampler2D tex, vec2 texCoord) -{ - return texture(tex, texCoord); -} - -vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc) -{ - ivec2 texSize = textureSize(tex); - ivec2 texCoord = ivec2(tc * texSize); - vec4 result = vec4(0.0); - for (int i = 0; i < u_TextureSamples; i++) - result += texelFetch(tex, texCoord, i); - - result /= float(u_TextureSamples); - return result; -} - -float MultiSampleDepth(sampler2DMS tex, vec2 tc) -{ - ivec2 texSize = textureSize(tex); - ivec2 texCoord = ivec2(tc * texSize); - float result = 0.0; - for (int i = 0; i < u_TextureSamples; i++) - result += texelFetch(tex, texCoord, i).r; - result /= float(u_TextureSamples); - return result; -} +const float gamma = 2.2; +const float pureWhite = 1.0; void main() { - const float gamma = 2.2; - const float pureWhite = 1.0; - - // Tonemapping - vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord); - vec3 color = msColor.rgb; + // 采样 HDR 颜色(单样本) + vec3 color = texture(u_HDRTexture, v_TexCoord).rgb; + // 混合 Bloom(如果启用) if (u_EnableBloom) { vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb; - color += bloomColor; + color += bloomColor; // 在 HDR 空间混合 } - if(u_EnableAutoExposure) - color *= u_Exposure; + // 应用曝光 + if (u_EnableAutoExposure) + color *= u_Exposure; else - color *= u_ManualExposure; + color *= u_ManualExposure; - // Reinhard tonemapping operator. - // see: "Photographic Tone Reproduction for Digital Images", eq. 4 + // Reinhard 色调映射 float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722)); float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance); - // Scale color by ratio of average luminances. + // 按亮度比例缩放颜色 vec3 mappedColor = (mappedLuminance / luminance) * color; - // Gamma correction. + // Gamma 校正 o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0); - - // Show over-exposed areas - // if (o_Color.r > 1.0 || o_Color.g > 1.0 || o_Color.b > 1.0) - // o_Color.rgb *= vec3(1.0, 0.25, 0.25); -} +} \ No newline at end of file diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp index 4a324da..99e70c0 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLFrameBuffer.cpp @@ -75,8 +75,8 @@ namespace Prism { glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height); - glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLRenderPass.h b/Prism/src/Prism/Platform/OpenGL/OpenGLRenderPass.h index 90c66d3..98d48fa 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLRenderPass.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLRenderPass.h @@ -16,7 +16,7 @@ namespace Prism virtual ~OpenGLRenderPass(); virtual RenderPassSpecification& GetSpecification() override { return m_Spec; } - virtual const RenderPassSpecification& GetSpecification() const { return m_Spec; } + virtual const RenderPassSpecification& GetSpecification() const override { return m_Spec; } private: RenderPassSpecification m_Spec; diff --git a/Prism/src/Prism/Renderer/RenderPass.h b/Prism/src/Prism/Renderer/RenderPass.h index dae3773..e46f79b 100644 --- a/Prism/src/Prism/Renderer/RenderPass.h +++ b/Prism/src/Prism/Renderer/RenderPass.h @@ -20,6 +20,7 @@ namespace Prism virtual ~RenderPass() = default; virtual RenderPassSpecification& GetSpecification() = 0; + virtual const RenderPassSpecification& GetSpecification() const = 0; static Ref Create(const RenderPassSpecification& spec); }; diff --git a/Prism/src/Prism/Renderer/Renderer3D.cpp b/Prism/src/Prism/Renderer/Renderer3D.cpp index eec019c..59635f7 100644 --- a/Prism/src/Prism/Renderer/Renderer3D.cpp +++ b/Prism/src/Prism/Renderer/Renderer3D.cpp @@ -25,20 +25,28 @@ namespace Prism LightEnvironment SceneLightEnvironment; // Resources - Ref SkyboxMaterial; Ref SceneEnvironment; + Ref SkyboxTexture; + float SkyboxLoad; } SceneData; Ref BRDFLUT; Ref CompositeShader; Ref BloomBlurShader; - Ref BloomBlendShader; + // Ref BloomBlendShader; Ref GeoPass; + + Ref LightingPass; + Ref LightingShader; + // Ref CompositePass; Ref BloomBlurPass[2]; Ref BloomBlendPass; Ref ResolvedHDRTexture; // 解析后的单样本 HDR 颜色 + int Quality = 6; + float Directions = 32.0f; + float Size = 16.0f; struct AutoExposureData { @@ -95,7 +103,7 @@ namespace Prism bool ShadowEnabled = true; float ShadowBias = 0.001f; float ShadowIntensity = 0.0f; - int ShadowSoftness = 0; + float ShadowSoftness = 0.0f; struct DrawCommand { @@ -134,11 +142,15 @@ namespace Prism { float ShadowPass = 0.0f; float GeometryPass = 0.0f; + float LightingPass = 0.0f; + float BloomPass = 0.0f; float CompositePass = 0.0f; float AutoExposurePass = 0.0f; Timer ShadowPassTimer; Timer GeometryPassTimer; + Timer LightingPassTimer; + Timer BloomPassTimer; Timer CompositePassTimer; Timer AutoExposurePassTimer; }; @@ -153,9 +165,15 @@ namespace Prism //////////////// GeoPass //////////////// { FramebufferSpecification geoFramebufferSpec; - geoFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::DEPTH24STENCIL8 }; - geoFramebufferSpec.Samples = 8; - geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f }; + geoFramebufferSpec.Attachments = { + FramebufferTextureFormat::RGBA16F, // Albedo + Metallic + FramebufferTextureFormat::RGBA16F, // Normal + Roughness + FramebufferTextureFormat::RGBA16F, // Emissive+AO + FramebufferTextureFormat::DEPTH24STENCIL8 // Depth + }; + + geoFramebufferSpec.Samples = 1; + geoFramebufferSpec.ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; RenderPassSpecification geoRenderPassSpec; geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec); @@ -164,6 +182,18 @@ namespace Prism ///////////////////////////////////////////// + //////////////// GeoPass //////////////// + FramebufferSpecification spec; + spec.Attachments = { FramebufferTextureFormat::RGBA16F }; // HDR 颜色输出 + spec.Samples = 1; + spec.ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + RenderPassSpecification rpSpec; + rpSpec.TargetFramebuffer = FrameBuffer::Create(spec); + s_Data.LightingPass = RenderPass::Create(rpSpec); + s_Data.LightingShader = Shader::Create("assets/shaders/Lighting.glsl"); + ///////////////////////////////////////////// + + //////////////// BloomPass //////////////// { FramebufferSpecification bloomBlurFramebufferSpec; @@ -185,7 +215,7 @@ namespace Prism s_Data.BloomBlendPass = RenderPass::Create(bloomBlendRenderPassSpec); s_Data.BloomBlurShader = Shader::Create("assets/shaders/BloomBlur.glsl"); - s_Data.BloomBlendShader = Shader::Create("assets/shaders/BloomBlend.glsl"); + // s_Data.BloomBlendShader = Shader::Create("assets/shaders/BloomBlend.glsl"); } ///////////////////////////////////////////// @@ -284,7 +314,8 @@ namespace Prism void Renderer3D::BeginScene(const Scene* scene, const SceneRendererCamera& camera) { s_Data.SceneData.SceneCamera = camera; - s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial; + s_Data.SceneData.SkyboxTexture = scene->m_SkyboxTexture; + s_Data.SceneData.SkyboxLoad = scene->m_SkyboxLod; s_Data.SceneData.SceneEnvironment = scene->m_Environment; s_Data.SceneData.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity; s_Data.SceneData.SceneLightEnvironment = scene->m_LightEnvironment; @@ -468,7 +499,13 @@ namespace Prism Renderer::Submit([] { s_Stats.GeometryPass = s_Stats.GeometryPassTimer.ElapsedMillis(); }); } - ResolveMSAA(); + { + Renderer::Submit([]() { s_Stats.LightingPassTimer.Reset(); }); + LightingPass(); + Renderer::Submit([] { s_Stats.LightingPass = s_Stats.LightingPassTimer.ElapsedMillis(); }); + } + + // ResolveMSAA(); // Compute average luminance and update exposure (GPU-copy + mipmap -> read 1 texel) { @@ -477,13 +514,17 @@ namespace Prism Renderer::Submit([] { s_Stats.AutoExposurePass = s_Stats.AutoExposurePassTimer.ElapsedMillis(); }); } - BloomBlurPass(); + { + Renderer::Submit([]() { s_Stats.BloomPassTimer.Reset(); }); + BloomBlurPass(); + Renderer::Submit([] { s_Stats.BloomPass = s_Stats.BloomPassTimer.ElapsedMillis(); }); + } - OverlayPass(); { Renderer::Submit([]() { s_Stats.CompositePassTimer.Reset(); }); CompositePass(outRenderPass); + OverlayPass(outRenderPass); Renderer::Submit([] { s_Stats.CompositePass = s_Stats.CompositePassTimer.ElapsedMillis(); }); // BloomBlurPass(); } @@ -501,7 +542,8 @@ namespace Prism if (!ae.EnableAutoExposure) return; - auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer; + auto srcFB = s_Data.LightingPass->GetSpecification().TargetFramebuffer; + // auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer; auto dstFB = ae.LuminancePass->GetSpecification().TargetFramebuffer; if (!srcFB || !dstFB) return; @@ -639,22 +681,23 @@ namespace Prism const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3]; // TODO: Negate instead - // Skybox - s_Data.SceneData.SkyboxMaterial->Set("u_InverseVP", glm::inverse(cameraViewProjection)); - s_Data.SceneData.SkyboxMaterial->Set("u_SkyIntensity", s_Data.SceneData.SceneEnvironmentIntensity); - // s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0); - Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial); - - // const float aspectRatio = (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetWidth() / (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetHeight(); - // float frustumSize = 2.0f * sceneCamera.Near * glm::tan(sceneCamera.FOV * 0.5f) * aspectRatio; - // Render entities + Renderer::Submit([]() + { + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + }); + for (auto& dc : s_Data.DrawList) { auto baseMaterial = dc.mesh->GetMaterial(); + baseMaterial->Set("u_GBufferMode", true); baseMaterial->Set("u_ViewProjectionMatrix", cameraViewProjection); baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix); baseMaterial->Set("u_CameraPosition", cameraPosition); + baseMaterial->Set("u_EmissiveColor", 1.0f); + baseMaterial->Set("u_EmissiveIntensity", 0.0f); + baseMaterial->Set("u_EmissiveTexToggle", 0.0f); // baseMaterial->Set("u_LightMatrixCascade0", s_Data.LightMatrices[0]); // baseMaterial->Set("u_LightMatrixCascade1", s_Data.LightMatrices[1]); // baseMaterial->Set("u_LightMatrixCascade2", s_Data.LightMatrices[2]); @@ -752,6 +795,9 @@ namespace Prism baseMaterial->Set("u_ViewProjectionMatrix", cameraViewProjection); baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix); baseMaterial->Set("u_CameraPosition", cameraPosition); + baseMaterial->Set("u_EmissiveColor", 1.0f); + baseMaterial->Set("u_EmissiveIntensity", 0.0f); + baseMaterial->Set("u_EmissiveTexToggle", 0.0f); // baseMaterial->Set("u_CascadeSplits", s_Data.CascadeSplits); // baseMaterial->Set("u_ShowCascades", s_Data.ShowCascades); // baseMaterial->Set("u_SoftShadows", s_Data.SoftShadows); @@ -919,10 +965,7 @@ namespace Prism } - // Grid - const auto option = GetOptions(); - - if (option.ShowBoundingBoxes) + if (const auto option = GetOptions(); option.ShowBoundingBoxes) { Renderer2D::BeginScene(cameraViewProjection); for (auto& dc : s_Data.DrawList) @@ -933,6 +976,112 @@ namespace Prism Renderer::EndRenderPass(); } + void Renderer3D::LightingPass() + { + Renderer::BeginRenderPass(s_Data.LightingPass); + s_Data.LightingShader->Bind(); + + // uniform + const glm::mat4 invViewProj = glm::inverse(s_Data.SceneData.SceneCamera.Camera.GetProjectionMatrix() * s_Data.SceneData.SceneCamera.ViewMatrix); + s_Data.LightingShader->SetMat4("u_InvViewProj", invViewProj); + const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3]; + s_Data.LightingShader->SetFloat3("u_CameraPosition", cameraPosition); + + + // G-buffer + auto fb = s_Data.GeoPass->GetSpecification().TargetFramebuffer; + Renderer::Submit([fb]() { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fb->GetColorAttachmentRendererID(0)); // AlbedoMetallic + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, fb->GetColorAttachmentRendererID(1)); // NormalRoughness + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, fb->GetColorAttachmentRendererID(2)); // EmissiveAO + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, fb->GetDepthAttachmentRendererID()); // Depth + }); + s_Data.LightingShader->SetInt("u_AlbedoMetallic", 0); + s_Data.LightingShader->SetInt("u_NormalRoughness", 1); + s_Data.LightingShader->SetInt("u_EmissiveAO", 2); + s_Data.LightingShader->SetInt("u_Depth", 3); + + + // uniform + const auto& lights = s_Data.SceneData.SceneLightEnvironment; + // s_Data.LightingShader->SetStruct("u_DirectionalLights", lights.DirectionalLights[0]); // 需确保 SetStruct 支持 + s_Data.LightingShader->SetFloat3("u_DirectionalLights.Direction", lights.DirectionalLights[0].Direction); + s_Data.LightingShader->SetFloat3("u_DirectionalLights.Radiance", lights.DirectionalLights[0].Radiance); + s_Data.LightingShader->SetFloat("u_DirectionalLights.Intensity", lights.DirectionalLights[0].Intensity); + s_Data.LightingShader->SetBool("u_DirectionalLights.CastShadows", lights.DirectionalLights[0].CastShadows); + + s_Data.LightingShader->SetInt("u_PointLightCount", lights.PointLightCount); + // s_Data.LightingShader->SetStructArray("u_PointLights", lights.PointLights, lights.PointLightCount); + for (int i = 0; i < lights.PointLightCount; i++) { + std::string base = "u_PointLights[" + std::to_string(i) + "]"; + s_Data.LightingShader->SetFloat3(base + ".Position", lights.PointLights[i].Position); + s_Data.LightingShader->SetFloat3(base + ".Radiance", lights.PointLights[i].Radiance); + s_Data.LightingShader->SetFloat(base + ".Intensity", lights.PointLights[i].Intensity); + s_Data.LightingShader->SetFloat(base + ".Range", lights.PointLights[i].Radius); + s_Data.LightingShader->SetBool(base + ".CastShadows", lights.PointLights[i].CastShadows); + } + + s_Data.LightingShader->SetInt("u_SpotLightCount", lights.SpotLightCount); + for (int i = 0; i < lights.SpotLightCount; i++) { + std::string base = "u_SpotLights[" + std::to_string(i) + "]"; + s_Data.LightingShader->SetFloat3(base + ".Position", lights.SpotLights[i].Position); + s_Data.LightingShader->SetFloat3(base + ".Direction", lights.SpotLights[i].Direction); + s_Data.LightingShader->SetFloat3(base + ".Radiance", lights.SpotLights[i].Radiance); + s_Data.LightingShader->SetFloat(base + ".Intensity", lights.SpotLights[i].Intensity); + s_Data.LightingShader->SetFloat(base + ".Range", lights.SpotLights[i].Range); + s_Data.LightingShader->SetFloat(base + ".InnerConeCos", lights.SpotLights[i].InnerConeCos); + s_Data.LightingShader->SetFloat(base + ".OuterConeCos", lights.SpotLights[i].OuterConeCos); + s_Data.LightingShader->SetBool(base + ".CastShadows", lights.SpotLights[i].CastShadows); + } + + // IBL + s_Data.LightingShader->SetInt("u_EnvRadianceTex", 4); + s_Data.LightingShader->SetInt("u_EnvIrradianceTex", 5); + s_Data.LightingShader->SetInt("u_BRDFLUTTexture", 6); + s_Data.LightingShader->SetFloat("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity); + s_Data.LightingShader->SetFloat("u_EnvMapRotation", 0.0f); // 若需要可调整 + + const auto& sceneEnvironment = s_Data.SceneData.SceneEnvironment; + const auto& BRDFLUT = s_Data.BRDFLUT; + Renderer::Submit([sceneEnvironment, BRDFLUT]() { + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_CUBE_MAP, sceneEnvironment->RadianceMap->GetRendererID()); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, sceneEnvironment->IrradianceMap->GetRendererID()); + glActiveTexture(GL_TEXTURE6); + glBindTexture(GL_TEXTURE_2D, BRDFLUT->GetRendererID()); + }); + + s_Data.LightingShader->SetMat4("u_LightSpaceMatrix", s_Data.LightMatrices); + s_Data.LightingShader->SetBool("u_ShadowEnabled", s_Data.ShadowEnabled); + s_Data.LightingShader->SetFloat("u_ShadowBias", s_Data.ShadowBias); + s_Data.LightingShader->SetFloat("u_ShadowIntensity", s_Data.ShadowIntensity); + s_Data.LightingShader->SetFloat("u_ShadowSoftness", s_Data.ShadowSoftness); + + if (s_Data.ShadowEnabled) { + s_Data.LightingShader->SetInt("u_ShadowMap", 7); + Renderer::Submit([]() { + glActiveTexture(GL_TEXTURE7); + glBindTexture(GL_TEXTURE_2D, s_Data.ShadowMapRenderPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID()); + glBindSampler(7, s_Data.ShadowMapSampler); + }); + } + + if (s_Data.SceneData.SkyboxTexture) { + s_Data.LightingShader->SetFloat("u_SkyTextureLod", s_Data.SceneData.SkyboxLoad); + s_Data.SceneData.SkyboxTexture->Bind(8); + s_Data.LightingShader->SetInt("u_Skybox", 8); // 使用纹理单元 8(确保不与其他单元冲突) + s_Data.LightingShader->SetFloat("u_SkyIntensity", s_Data.SceneData.SceneEnvironmentIntensity); + } + + Renderer::SubmitFullscreenQuad(nullptr); + Renderer::EndRenderPass(); + } + void Renderer3D::BloomBlurPass() { if (!s_Data.EnableBloom) @@ -943,59 +1092,73 @@ namespace Prism return; } - uint32_t srcTex = s_Data.ResolvedHDRTexture->GetRendererID(); - const int iterations = 5; // 模糊迭代次数,可调 + // uint32_t srcTex = s_Data.ResolvedHDRTexture->GetRendererID(); + uint32_t srcTex = s_Data.LightingPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); // 第一次:提取高光 + 水平模糊 { Renderer::BeginRenderPass(s_Data.BloomBlurPass[0]); s_Data.BloomBlurShader->Bind(); s_Data.BloomBlurShader->SetInt("u_Texture", 0); - // s_Data.BloomBlurShader->SetBool("u_Horizontal", true); s_Data.BloomBlurShader->SetBool("u_FirstPass", true); s_Data.BloomBlurShader->SetFloat("u_Threshold", s_Data.BloomThreshold); + s_Data.BloomBlurShader->SetInt("u_Quality", s_Data.Quality); + s_Data.BloomBlurShader->SetFloat("u_Directions", s_Data.Directions); + s_Data.BloomBlurShader->SetFloat("u_Size", s_Data.Size); Renderer::Submit([srcTex]() { glBindTextureUnit(0, srcTex); }); Renderer::SubmitFullscreenQuad(nullptr); Renderer::EndRenderPass(); } - // 后续迭代 - for (int i = 1; i < iterations; ++i) - { - bool horizontal = (i % 2 == 1); // 第二次垂直,第三次水平... - uint32_t inputTex = (i % 2 == 1) ? - s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID() : - s_Data.BloomBlurPass[1]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); - auto outputPass = (i % 2 == 1) ? s_Data.BloomBlurPass[1] : s_Data.BloomBlurPass[0]; - - Renderer::BeginRenderPass(outputPass); - s_Data.BloomBlurShader->Bind(); - s_Data.BloomBlurShader->SetInt("u_Texture", 0); - // s_Data.BloomBlurShader->SetBool("u_Horizontal", horizontal); - s_Data.BloomBlurShader->SetBool("u_FirstPass", false); - Renderer::Submit([inputTex]() { glBindTextureUnit(0, inputTex); }); - Renderer::SubmitFullscreenQuad(nullptr); - Renderer::EndRenderPass(); - } - - // 将最终模糊结果拷贝到 BloomBlendPass(供合成使用) - uint32_t finalBlurTex = (iterations % 2 == 0) ? - s_Data.BloomBlurPass[1]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID() : - s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); + uint32_t finalBlurTex = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); Renderer::BeginRenderPass(s_Data.BloomBlendPass); s_Data.BloomBlurShader->Bind(); s_Data.BloomBlurShader->SetInt("u_Texture", 0); - // s_Data.BloomBlurShader->SetBool("u_Horizontal", false); s_Data.BloomBlurShader->SetBool("u_FirstPass", false); + s_Data.BloomBlurShader->SetInt("u_Quality", s_Data.Quality); + s_Data.BloomBlurShader->SetFloat("u_Directions", s_Data.Directions); + s_Data.BloomBlurShader->SetFloat("u_Size", s_Data.Size); Renderer::Submit([finalBlurTex]() { glBindTextureUnit(0, finalBlurTex); }); Renderer::SubmitFullscreenQuad(nullptr); Renderer::EndRenderPass(); } - void Renderer3D::OverlayPass() + + void Renderer3D::CompositePass(const Ref& outRenderPass) { - Renderer::BeginRenderPass(s_Data.GeoPass, false); + Renderer::BeginRenderPass(outRenderPass); + + s_Data.CompositeShader->Bind(); + + s_Data.CompositeShader->SetBool("u_EnableAutoExposure", s_Data.AutoExposureData.EnableAutoExposure); + s_Data.CompositeShader->SetFloat("u_ManualExposure", s_Data.SceneData.SceneCamera.Camera.GetExposure()); + + s_Data.CompositeShader->SetBool("u_EnableBloom", s_Data.EnableBloom); + s_Data.LightingPass->GetSpecification().TargetFramebuffer->BindTexture(); // 通常绑定到单元0 + Renderer::Submit([]() { + glBindTextureUnit(1, s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID()); + }); + + if (s_Data.EnableBloom) + { + uint32_t bloomTex = s_Data.BloomBlendPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); + Renderer::Submit([bloomTex]() { + glBindTextureUnit(2, bloomTex); + }); + s_Data.CompositeShader->SetInt("u_BloomTexture", 2); + } + + s_Data.AutoExposureData.ExposureSSBO->BindBase(2); + + + Renderer::SubmitFullscreenQuad(nullptr); + Renderer::EndRenderPass(); + } + + void Renderer3D::OverlayPass(const Ref& outRenderPass) + { + Renderer::BeginRenderPass(outRenderPass, false); if (const auto option = GetOptions(); option.ShowGrid) { @@ -1023,216 +1186,7 @@ namespace Prism Renderer::EndRenderPass(); } - void Renderer3D::CompositePass(const Ref& outRenderPass) - { - Renderer::BeginRenderPass(outRenderPass); - s_Data.CompositeShader->Bind(); - - s_Data.AutoExposureData.ExposureSSBO->BindBase(2); - s_Data.CompositeShader->SetBool("u_EnableAutoExposure", s_Data.AutoExposureData.EnableAutoExposure); - s_Data.CompositeShader->SetFloat("u_ManualExposure", s_Data.SceneData.SceneCamera.Camera.GetExposure()); - s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples); - s_Data.CompositeShader->SetBool("u_EnableBloom", s_Data.EnableBloom); - - // 绑定几何阶段颜色纹理(多重采样) - s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture(0); // 通常绑定到单元0 - Renderer::Submit([]() { - glBindTextureUnit(1, s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID()); - }); - - // 新增:绑定 Bloom 纹理(如果启用) - if (s_Data.EnableBloom) - { - uint32_t bloomTex = s_Data.BloomBlendPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); - Renderer::Submit([bloomTex]() { - glBindTextureUnit(2, bloomTex); // 绑定到单元2 - }); - s_Data.CompositeShader->SetInt("u_BloomTexture", 2); // 告诉着色器使用单元2 - } - - Renderer::SubmitFullscreenQuad(nullptr); - - Renderer::EndRenderPass(); - } - - - /* - void Renderer3D::CompositePass(const Ref& outRenderPass) - { - Renderer::BeginRenderPass(outRenderPass); - - s_Data.CompositeShader->Bind(); - - s_Data.BloomBlendShader->Bind(); - s_Data.BloomBlendShader->SetBool("u_EnableBloom", s_Data.EnableBloom); - - s_Data.AutoExposureData.ExposureSSBO->BindBase(2); - - Renderer::Submit([]() { - glBindTextureUnit(0, s_Data.ResolvedHDRTexture->GetRendererID()); - }); - s_Data.BloomBlendShader->SetInt("u_SceneTexture", 0); - - s_Data.CompositeShader->SetBool("u_EnableAutoExposure",s_Data.AutoExposureData.EnableAutoExposure); - s_Data.CompositeShader->SetFloat("u_ManualExposure", s_Data.SceneData.SceneCamera.Camera.GetExposure()); - s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples); - s_Data.CompositeShader->SetFloat("u_EnableBloom", s_Data.EnableBloom); - - if (s_Data.EnableBloom) - { - uint32_t bloomTex = s_Data.BloomBlendPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); - Renderer::Submit([bloomTex]() { - glBindTextureUnit(1, bloomTex); - }); - s_Data.BloomBlendShader->SetInt("u_BloomTexture", 1); - } - - s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture(); - Renderer::Submit([]() - { - glBindTextureUnit(1, s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID()); - }); - - Renderer::SubmitFullscreenQuad(nullptr); - - Renderer::EndRenderPass(); - } - */ - - - /* - struct FrustumBounds - { - float r, l, b, t, f, n; - }; - - struct CascadeData - { - glm::mat4 ViewProj; - glm::mat4 View; - float SplitDepth; - }; - - - static void CalculateCascades(CascadeData* cascades, const glm::vec3& lightDirection) - { - // FrustumBounds frustumBounds[3]; - - auto& sceneCamera = s_Data.SceneData.SceneCamera; - auto viewProjection = sceneCamera.Camera.GetProjectionMatrix() * sceneCamera.ViewMatrix; - - constexpr int SHADOW_MAP_CASCADE_COUNT = 4; - float cascadeSplits[SHADOW_MAP_CASCADE_COUNT]; - - // TODO: less hard-coding! - float nearClip = 0.1f; - float farClip = 1000.0f; - float clipRange = farClip - nearClip; - - float minZ = nearClip; - float maxZ = nearClip + clipRange; - - float range = maxZ - minZ; - float ratio = maxZ / minZ; - - // Calculate split depths based on view camera frustum - // Based on method presented in https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch10.html - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) - { - float p = (i + 1) / static_cast(SHADOW_MAP_CASCADE_COUNT); - float log = minZ * std::pow(ratio, p); - float uniform = minZ + range * p; - float d = s_Data.CascadeSplitLambda * (log - uniform) + uniform; - cascadeSplits[i] = (d - nearClip) / clipRange; - } - - // cascadeSplits[3] = 0.3f; - - // Manually set cascades here - // cascadeSplits[0] = 0.05f; - // cascadeSplits[1] = 0.15f; - // cascadeSplits[2] = 0.3f; - // cascadeSplits[3] = 1.0f; - - // Calculate orthographic projection matrix for each cascade - float lastSplitDist = 1.0; - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) - { - float splitDist = cascadeSplits[i]; - - glm::vec3 frustumCorners[8] = - { - glm::vec3(-1.0f, 1.0f, -1.0f), - glm::vec3( 1.0f, 1.0f, -1.0f), - glm::vec3( 1.0f, -1.0f, -1.0f), - glm::vec3(-1.0f, -1.0f, -1.0f), - glm::vec3(-1.0f, 1.0f, 1.0f), - glm::vec3( 1.0f, 1.0f, 1.0f), - glm::vec3( 1.0f, -1.0f, 1.0f), - glm::vec3(-1.0f, -1.0f, 1.0f), - }; - - // Project frustum corners into world space - glm::mat4 invCam = glm::inverse(viewProjection); - for (uint32_t i = 0; i < 8; i++) - { - glm::vec4 invCorner = invCam * glm::vec4(frustumCorners[i], 1.0f); - frustumCorners[i] = invCorner / invCorner.w; - } - - for (uint32_t i = 0; i < 4; i++) - { - glm::vec3 dist = frustumCorners[i + 4] - frustumCorners[i]; - frustumCorners[i + 4] = frustumCorners[i] + (dist * splitDist); - frustumCorners[i] = frustumCorners[i] + (dist * lastSplitDist); - } - - // Get frustum center - glm::vec3 frustumCenter = glm::vec3(0.0f); - for (uint32_t i = 0; i < 8; i++) - frustumCenter += frustumCorners[i]; - - frustumCenter /= 8.0f; - - //frustumCenter *= 0.01f; - - float radius = 0.0f; - for (uint32_t i = 0; i < 8; i++) - { - float distance = glm::length(frustumCorners[i] - frustumCenter); - radius = glm::max(radius, distance); - } - radius = std::ceil(radius * 16.0f) / 16.0f; - - glm::vec3 maxExtents = glm::vec3(radius); - glm::vec3 minExtents = -maxExtents; - - glm::vec3 lightDir = -lightDirection; - glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 0.0f, 1.0f)); - glm::mat4 lightOrthoMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + s_Data.CascadeNearPlaneOffset, maxExtents.z - minExtents.z + s_Data.CascadeFarPlaneOffset); - - // Offset to texel space to avoid shimmering (from https://stackoverflow.com/questions/33499053/cascaded-shadow-map-shimmering) - glm::mat4 shadowMatrix = lightOrthoMatrix * lightViewMatrix; - constexpr float ShadowMapResolution = 4096.0f; - glm::vec4 shadowOrigin = (shadowMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f; - glm::vec4 roundedOrigin = glm::round(shadowOrigin); - glm::vec4 roundOffset = roundedOrigin - shadowOrigin; - roundOffset = roundOffset * 2.0f / ShadowMapResolution; - roundOffset.z = 0.0f; - roundOffset.w = 0.0f; - - lightOrthoMatrix[3] += roundOffset; - - // Store split distance and matrix in cascade - cascades[i].SplitDepth = (nearClip + splitDist * clipRange) * -1.0f; - cascades[i].ViewProj = lightOrthoMatrix * lightViewMatrix; - cascades[i].View = lightViewMatrix; - - lastSplitDist = cascadeSplits[i]; - } - } - */ std::vector GetFrustumCornersWorldSpace(const SceneRendererCamera& sceneCamera) { std::vector corners(8); @@ -1258,39 +1212,6 @@ namespace Prism } - void Renderer3D::ResolveMSAA() - { - auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer; - const uint32_t width = srcFB->GetWidth(); - const uint32_t height = srcFB->GetHeight(); - - if (!s_Data.ResolvedHDRTexture || - s_Data.ResolvedHDRTexture->GetWidth() != width || - s_Data.ResolvedHDRTexture->GetHeight() != height) - { - s_Data.ResolvedHDRTexture = Texture2D::Create(TextureFormat::RGBA16F, width, height); - } - - Renderer::Submit([srcFB, resolvedTex = s_Data.ResolvedHDRTexture]() { - GLuint resolveFBO; - glGenFramebuffers(1, &resolveFBO); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolvedTex->GetRendererID(), 0); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID()); - glReadBuffer(GL_COLOR_ATTACHMENT0); - - glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), - 0, 0, srcFB->GetWidth(), srcFB->GetHeight(), - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - glDeleteFramebuffers(1, &resolveFBO); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - }); - } - - void SceneRenderer::OnImGuiRender() { ImGui::Begin("Scene Renderer"); @@ -1298,9 +1219,37 @@ namespace Prism UI::Property("Geometry Pass time", s_Stats.GeometryPass); UI::Property("Composite Pass time", s_Stats.CompositePass); + UI::Property("Bloom Pass time", s_Stats.BloomPass); UI::Property("Shadow Pass time", s_Stats.ShadowPass); UI::Property("AutoExposure Pass time", s_Stats.AutoExposurePass); + if (UI::BeginTreeNode("Geometry", false)) + { + const float size = ImGui::GetContentRegionAvail().x; // (float)fb->GetWidth() * 0.5f, (float)fb->GetHeight() * 0.5f + float w = size; + auto fb = s_Data.GeoPass->GetSpecification().TargetFramebuffer; + auto image1 = fb->GetColorAttachmentRendererID(0); + auto image2 = fb->GetColorAttachmentRendererID(1); + auto image3 = fb->GetColorAttachmentRendererID(2); + float h = w / ((float)fb->GetWidth() / (float)fb->GetHeight()); + ImGui::Image((ImTextureID)image1, { w, h }, { 0, 1 }, { 1, 0 }); + ImGui::Image((ImTextureID)image2, { w, h }, { 0, 1 }, { 1, 0 }); + ImGui::Image((ImTextureID)image3, { w, h }, { 0, 1 }, { 1, 0 }); + + auto lightFB = s_Data.LightingPass->GetSpecification().TargetFramebuffer; + auto lightImage = lightFB->GetColorAttachmentRendererID(); + + + + ImGui::Image((ImTextureID)lightImage, { w, h }, { 0, 1 }, { 1, 0 }); + + auto depthfb = s_Data.GeoPass->GetSpecification().TargetFramebuffer; + uint32_t depthID = depthfb->GetDepthAttachmentRendererID(); + ImGui::Image((ImTextureID)depthID, {w, h}, {0, 1}, {1, 0}); + + UI::EndTreeNode(); + } + if (UI::BeginTreeNode("Grid Config", false)) { // Grid plane: 0 = XZ (Y up), 1 = XY (Z forward), 2 = YZ (X right) @@ -1361,6 +1310,10 @@ namespace Prism UI::BeginPropertyGrid(); UI::Property("Bloom", s_Data.EnableBloom); UI::Property("Bloom threshold", s_Data.BloomThreshold, 0.05f); + UI::Property("Directions", s_Data.Directions); + UI::Property("Quality", s_Data.Quality); + UI::Property("Size", s_Data.Size); + UI::EndPropertyGrid(); auto fb = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer; @@ -1374,24 +1327,9 @@ namespace Prism float h = w / ((float)fb->GetWidth() / (float)fb->GetHeight()); ImGui::Image((ImTextureID)id, { w, h }, { 0, 1 }, { 1, 0 }); ImGui::Image((ImTextureID)id2, { w, h }, { 0, 1 }, { 1, 0 }); - ImGui::Image((ImTextureID)s_Data.ResolvedHDRTexture->GetRendererID(), { w, h }, { 0, 1 }, { 1, 0 }); UI::EndTreeNode(); } - /* - if (UI::BeginTreeNode("Auto Exposure", false)) - { - UI::BeginPropertyGrid(); - UI::Property("Enable Auto Exposure", s_Data.AutoExposureData.EnableAutoExposure); - UI::Property("Key (middle gray)", s_Data.AutoExposureData.Key, 0.001f, 0.001f, 2.5f); - UI::Property("Adaptation Speed", s_Data.AutoExposureData.AdaptationSpeed, 0.01f, 0.001f, 5.0f); - UI::Property("Current Exposure", s_Data.AutoExposureData.CurrentExposure, 0.01f, 0.0f, 0.0f, true); - UI::EndPropertyGrid(); - - UI::EndTreeNode(); - } - */ - if (UI::BeginTreeNode("Auto Exposure", false)) { UI::BeginPropertyGrid(); diff --git a/Prism/src/Prism/Renderer/Renderer3D.h b/Prism/src/Prism/Renderer/Renderer3D.h index e11a3ef..2bff9d5 100644 --- a/Prism/src/Prism/Renderer/Renderer3D.h +++ b/Prism/src/Prism/Renderer/Renderer3D.h @@ -61,13 +61,15 @@ namespace Prism static void AutoExposurePass(); static void ShadowMapPass(); static void GeometryPass(); + static void LightingPass(); static void BloomBlurPass(); - static void OverlayPass(); + + static void OverlayPass(const Ref& outRenderPass); static void CompositePass(const Ref& outRenderPass); - static void ResolveMSAA(); + // static void ResolveMSAA(); }; } diff --git a/Prism/src/Prism/Renderer/SceneRenderer.cpp b/Prism/src/Prism/Renderer/SceneRenderer.cpp index dae0265..44243c7 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.cpp +++ b/Prism/src/Prism/Renderer/SceneRenderer.cpp @@ -26,7 +26,7 @@ namespace Prism void SceneRenderer::Init() { FramebufferSpecification finalFramebufferSpec; - finalFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::Depth}; + finalFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::DEPTH24STENCIL8}; finalFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f }; RenderPassSpecification finalRenderPassSpec; diff --git a/Prism/src/Prism/Scene/Components.h b/Prism/src/Prism/Scene/Components.h index e876184..6db5a30 100644 --- a/Prism/src/Prism/Scene/Components.h +++ b/Prism/src/Prism/Scene/Components.h @@ -452,7 +452,7 @@ namespace Prism MeshComponent, RigidBodyComponent, BoxColliderComponent, SphereColliderComponent, CapsuleColliderComponent, MeshColliderComponent, AnimationComponent, - DirectionalLightComponent, SkyLightComponent, + DirectionalLightComponent, SkyLightComponent, PointLightComponent, SpotLightComponent, ScriptComponent, CameraComponent >; diff --git a/Prism/src/Prism/Scene/Scene.cpp b/Prism/src/Prism/Scene/Scene.cpp index 8cebea5..e6938c0 100644 --- a/Prism/src/Prism/Scene/Scene.cpp +++ b/Prism/src/Prism/Scene/Scene.cpp @@ -70,9 +70,9 @@ namespace Prism void Scene::Init() { - const auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl"); - m_SkyboxMaterial = MaterialInstance::Create(Material::Create(skyboxShader)); - m_SkyboxMaterial->SetFlag(MaterialFlag::DepthTest, false); + // const auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl"); + // m_SkyboxMaterial = MaterialInstance::Create(Material::Create(skyboxShader)); + // m_SkyboxMaterial->SetFlag(MaterialFlag::DepthTest, false); m_CameraIcon = AssetsManager::GetAsset("assets/editor/Camera.png"); m_LightIcon = AssetsManager::GetAsset("assets/editor/light.png"); @@ -171,7 +171,8 @@ namespace Prism // TODO: only one sky light at the moment! { - m_Environment = Ref::Create(); + if (!m_Environment) + m_Environment = Ref::Create(Renderer3D::GetBlackCubeTexture(), Renderer3D::GetBlackCubeTexture()); const auto lights = m_Registry.group(entt::get); for (const auto entity : lights) { @@ -184,7 +185,6 @@ namespace Prism } - m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod); SceneRenderer::BeginScene(this, { static_cast(camera), cameraViewMatrix }, false); { @@ -236,7 +236,7 @@ namespace Prism // TODO: only one sky light at the moment! { const auto lights = m_Registry.group(entt::get); - if (lights.empty()) + if (!m_Environment) m_Environment = Ref::Create(Renderer3D::GetBlackCubeTexture(), Renderer3D::GetBlackCubeTexture()); if (!lights.empty()) { @@ -251,13 +251,14 @@ namespace Prism m_Environment = skyLightComponent.SceneEnvironment; m_EnvironmentIntensity = skyLightComponent.Intensity; - if (m_Environment) - SetSkybox(m_Environment->RadianceMap); + + break; //TODO: this only support one environment } } } + if (m_Environment) + SetSkybox(m_Environment->RadianceMap); - m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod); // TODO: this value should be storage and can modify // TODO: Renderer2D cannot blend with Renderer3D @@ -440,7 +441,6 @@ namespace Prism void Scene::SetSkybox(const Ref& skybox) { m_SkyboxTexture = skybox; - m_SkyboxMaterial->Set("u_Texture", skybox); } Entity Scene::GetMainCameraEntity() @@ -579,8 +579,8 @@ namespace Prism { target->m_Environment = m_Environment; target->m_SkyboxTexture = m_SkyboxTexture; - target->m_SkyboxMaterial = m_SkyboxMaterial; target->m_SkyboxLod = m_SkyboxLod; + target->m_EnvironmentIntensity = m_EnvironmentIntensity; std::unordered_map enttMap; auto idComponents = m_Registry.view(); @@ -646,35 +646,33 @@ namespace Prism // Point Light { const auto pointLights = m_Registry.group(entt::get); - uint32_t pointLightIndex = 0; + m_LightEnvironment.PointLightCount = 0; for (const auto entity : pointLights) { - if (pointLightIndex >= 8) break; + if (m_LightEnvironment.PointLightCount >= 16) break; auto [transform, light] = pointLights.get(entity); - m_LightEnvironment.PointLights[pointLightIndex++] = { + m_LightEnvironment.PointLights[m_LightEnvironment.PointLightCount++] = { transform.Translation, light.Radiance, light.Radius, light.Intensity, light.CastShadows, }; - - m_LightEnvironment.PointLightCount ++; } } // Spot Light { const auto spotLights = m_Registry.group(entt::get); - uint32_t pointLightIndex = 0; + m_LightEnvironment.SpotLightCount = 0; for (const auto entity : spotLights) { - if (pointLightIndex >= 8) break; + if (m_LightEnvironment.SpotLightCount >= 16) break; auto [transform, light] = spotLights.get(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++] = { + m_LightEnvironment.SpotLights[m_LightEnvironment.SpotLightCount++] = { transform.Translation, direction, light.Radiance, @@ -684,7 +682,6 @@ namespace Prism outerCos, light.CastShadows, }; - m_LightEnvironment.SpotLightCount ++; } } } diff --git a/Prism/src/Prism/Scene/Scene.h b/Prism/src/Prism/Scene/Scene.h index 060b86a..aeafb93 100644 --- a/Prism/src/Prism/Scene/Scene.h +++ b/Prism/src/Prism/Scene/Scene.h @@ -54,10 +54,10 @@ namespace Prism { GPUDirectionalLight DirectionalLights[4]; - GPUPointLight PointLights[8]{}; + GPUPointLight PointLights[16]{}; int PointLightCount = 0; - GPUSpotLight SpotLights[8]{}; + GPUSpotLight SpotLights[16]{}; int SpotLightCount = 0; }; @@ -164,11 +164,10 @@ namespace Prism bool m_IsPlaying = false; Ref m_Environment; - float m_EnvironmentIntensity = 1.0f; Ref m_SkyboxTexture; - Ref m_SkyboxMaterial; - float m_SkyboxLod = 1.0f; + float m_SkyboxLod = 0.0f; + float m_EnvironmentIntensity = 1.0f; Ref m_CameraIcon;