add bloom;some treaks
This commit is contained in:
@ -21,59 +21,64 @@ layout(location = 0) out vec4 o_Color;
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform bool u_Horizontal;
|
||||
uniform bool u_Horizontal; // 未使用,可保留或移除
|
||||
uniform bool u_FirstPass; // 是否进行阈值处理
|
||||
uniform float u_Threshold; // 亮度阈值
|
||||
|
||||
void main()
|
||||
{
|
||||
#if 1
|
||||
// From learnopengl.com
|
||||
float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||
float Pi = 6.28318530718; // 2*PI
|
||||
|
||||
vec2 tex_offset = 1.0 / textureSize(u_Texture, 0); // gets size of single texel
|
||||
vec3 result = texture(u_Texture, v_TexCoord).rgb * weight[0]; // current fragment's contribution
|
||||
if (u_Horizontal)
|
||||
float Directions = 32.0; // 模糊方向数
|
||||
float Quality = 6.0; // 每个方向上的采样质量(采样次数)
|
||||
float Size = 16.0; // 模糊半径
|
||||
|
||||
vec2 Radius = Size / textureSize(u_Texture, 0);
|
||||
|
||||
// 中心像素采样
|
||||
vec3 centerColor = texture(u_Texture, v_TexCoord).rgb;
|
||||
float centerLum = dot(centerColor, vec3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
// 如果启用第一次处理且中心像素亮度低于阈值,则直接输出黑色(不进行模糊)
|
||||
if (u_FirstPass && centerLum <= u_Threshold)
|
||||
{
|
||||
for(int i = 1; i < 5; ++i)
|
||||
o_Color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 result = centerColor; // 先累加中心像素
|
||||
float totalSamples = 1.0; // 有效采样计数(中心像素已计入)
|
||||
|
||||
// 周围像素采样
|
||||
for (float d = 0.0; d < Pi; d += Pi / Directions)
|
||||
{
|
||||
for (float i = 1.0 / Quality; i <= 1.0; i += 1.0 / Quality)
|
||||
{
|
||||
result += texture(u_Texture, v_TexCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||
result += texture(u_Texture, v_TexCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 1; i < 5; ++i)
|
||||
{
|
||||
result += texture(u_Texture, v_TexCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||
result += texture(u_Texture, v_TexCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||
vec2 offset = vec2(cos(d), sin(d)) * Radius * i;
|
||||
vec3 sampleColor = texture(u_Texture, v_TexCoord + offset).rgb;
|
||||
|
||||
if (u_FirstPass)
|
||||
{
|
||||
float lum = dot(sampleColor, vec3(0.2126, 0.7152, 0.0722));
|
||||
if (lum <= u_Threshold)
|
||||
{
|
||||
// 低于阈值则贡献黑色,但采样点仍计入分母?这里选择不计入有效采样数
|
||||
// 若希望保持模糊能量,可以 continue 跳过累加,但需调整分母
|
||||
// 为简单起见,此处设为黑色并计入计数(分母不变),也可选择跳过
|
||||
sampleColor = vec3(0.0);
|
||||
// 如果希望忽略该采样点,可以 continue 并减少 totalSamples
|
||||
// 但为了效果平滑,这里保留为黑色并计入计数
|
||||
}
|
||||
}
|
||||
|
||||
result += sampleColor;
|
||||
totalSamples += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// 归一化:除以总采样数(包括中心像素)
|
||||
// 若之前选择忽略低于阈值的采样点(continue),则需相应调整 totalSamples
|
||||
result /= totalSamples;
|
||||
|
||||
o_Color = vec4(result, 1.0);
|
||||
#else
|
||||
// From https://www.shadertoy.com/view/Xltfzj
|
||||
|
||||
float Pi = 6.28318530718; // Pi*2
|
||||
|
||||
// GAUSSIAN BLUR SETTINGS {{{
|
||||
float Directions =32.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
|
||||
float Quality = 6.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
|
||||
float Size = 16.0; // BLUR SIZE (Radius)
|
||||
// GAUSSIAN BLUR SETTINGS }}}
|
||||
|
||||
vec2 Radius = Size/textureSize(u_Texture, 0);
|
||||
|
||||
vec3 result = texture(u_Texture, v_TexCoord).rgb;
|
||||
vec2 uv = v_TexCoord;
|
||||
// Blur calculations
|
||||
for( float d=0.0; d<Pi; d+=Pi/Directions)
|
||||
{
|
||||
for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality)
|
||||
{
|
||||
result += texture( u_Texture, uv+vec2(cos(d),sin(d))*Radius*i).rgb;
|
||||
}
|
||||
}
|
||||
|
||||
// Output to screen
|
||||
result /= Quality * Directions - 15.0;
|
||||
o_Color = vec4(result, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ layout(binding = 0, rgba32f) restrict writeonly uniform imageCube o_CubeMap;
|
||||
|
||||
uniform vec3 u_TurbidityAzimuthInclination;
|
||||
|
||||
#define PI 3.14159265359
|
||||
|
||||
vec3 GetCubeMapTexCoord()
|
||||
{
|
||||
vec2 st = gl_GlobalInvocationID.xy / vec2(imageSize(o_CubeMap));
|
||||
@ -22,11 +24,10 @@ vec3 GetCubeMapTexCoord()
|
||||
return normalize(ret);
|
||||
}
|
||||
|
||||
#define PI 3.14159265359
|
||||
|
||||
float saturatedDot( in vec3 a, in vec3 b )
|
||||
{
|
||||
return max( dot( a, b ), 0.0 );
|
||||
return clamp(dot(a, b), 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 YxyToXYZ( in vec3 Yxy )
|
||||
@ -96,6 +97,7 @@ vec3 calculateZenithLuminanceYxy( in float t, in float thetaS )
|
||||
|
||||
vec3 calculatePerezLuminanceYxy( in float theta, in float gamma, in vec3 A, in vec3 B, in vec3 C, in vec3 D, in vec3 E )
|
||||
{
|
||||
float cosTheta = max(cos(theta), 1e-6);
|
||||
return ( 1.0 + A * exp( B / cos( theta ) ) ) * ( 1.0 + C * exp( D * gamma ) + E * cos( gamma ) * cos( gamma ) );
|
||||
}
|
||||
|
||||
@ -104,8 +106,8 @@ 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 thetaS = acos(clamp(dot(s, vec3(0,1,0)), 0.0, 1.0));
|
||||
float thetaE = acos(clamp(dot(e, vec3(0,1,0)), 0.0, 1.0));
|
||||
float gammaE = acos( saturatedDot( s, e ) );
|
||||
|
||||
vec3 Yz = calculateZenithLuminanceYxy( t, thetaS );
|
||||
@ -128,8 +130,30 @@ void main()
|
||||
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 );
|
||||
|
||||
const float SUN_ANGULAR_RADIUS = 0.03465;
|
||||
const float SUN_INTENSITY = 100.0;
|
||||
vec3 skyLuminance;
|
||||
|
||||
if (viewDir.y < 0.0) {
|
||||
skyLuminance = vec3(0.02);
|
||||
} else {
|
||||
skyLuminance = calculateSkyLuminanceRGB(sunDir, viewDir, turbidity);
|
||||
}
|
||||
|
||||
float cosAngle = dot(viewDir, sunDir);
|
||||
float angle = acos(cosAngle);
|
||||
if (angle < SUN_ANGULAR_RADIUS) {
|
||||
skyLuminance = vec3(SUN_INTENSITY);
|
||||
} else {
|
||||
float haloWidth = 0.1;
|
||||
if (angle < SUN_ANGULAR_RADIUS + haloWidth) {
|
||||
float t = (angle - SUN_ANGULAR_RADIUS) / haloWidth;
|
||||
float haloFactor = 1.0 - smoothstep(0.0, 1.0, t);
|
||||
skyLuminance += vec3(SUN_INTENSITY * 0.1 * haloFactor);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 color = vec4(skyLuminance * 0.05, 1.0);
|
||||
imageStore(o_CubeMap, ivec3(gl_GlobalInvocationID), color);
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,7 @@ layout(location = 1) out vec4 o_BloomTexture;
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2DMS u_Texture;
|
||||
uniform sampler2D u_BloomTexture;
|
||||
|
||||
|
||||
uniform bool u_EnableAutoExposure;
|
||||
@ -55,6 +56,17 @@ vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc)
|
||||
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;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
const float gamma = 2.2;
|
||||
@ -62,12 +74,11 @@ void main()
|
||||
|
||||
// Tonemapping
|
||||
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
|
||||
|
||||
vec3 color = msColor.rgb;
|
||||
|
||||
if (u_EnableBloom)
|
||||
{
|
||||
vec3 bloomColor = MultiSampleTexture(u_Texture, v_TexCoord).rgb;
|
||||
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||
color += bloomColor;
|
||||
}
|
||||
|
||||
|
||||
@ -327,7 +327,12 @@ namespace Prism
|
||||
if (ImGui::MenuItem("Sky Light"))
|
||||
{
|
||||
auto newEntity = m_Context->CreateEntity("Sky Light");
|
||||
newEntity.AddComponent<SkyLightComponent>();
|
||||
auto& slc = newEntity.AddComponent<SkyLightComponent>();
|
||||
slc.DynamicSky = true;
|
||||
|
||||
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(slc.TurbidityAzimuthInclination);
|
||||
slc.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
|
||||
|
||||
isCreated = true;
|
||||
SetSelected(newEntity);
|
||||
}
|
||||
@ -681,7 +686,12 @@ namespace Prism
|
||||
|
||||
ImGui::SeparatorText("Light Component");
|
||||
AddComponentPopup<DirectionalLightComponent>("Directional Light");
|
||||
AddComponentPopup<SkyLightComponent>("sky Light");
|
||||
AddComponentPopup<SkyLightComponent>("Sky Light", [&]( SkyLightComponent& slc)
|
||||
{
|
||||
slc.DynamicSky = true;
|
||||
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(slc.TurbidityAzimuthInclination);
|
||||
slc.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
|
||||
});
|
||||
AddComponentPopup<PointLightComponent>("Point Light");
|
||||
AddComponentPopup<SpotLightComponent>("Spot Light");
|
||||
|
||||
@ -939,6 +949,10 @@ namespace Prism
|
||||
});
|
||||
|
||||
DrawComponent<CameraComponent>("Camera", entity, [](CameraComponent& cameraComponent) {
|
||||
|
||||
UI::Property("ShowIcon", cameraComponent.ShowIcon);
|
||||
UI::Separator();
|
||||
|
||||
// Projection Type
|
||||
const char* projTypeStrings[] = { "Perspective", "Orthographic" };
|
||||
const char* currentProj = projTypeStrings[(int)cameraComponent.Camera.GetProjectionType()];
|
||||
@ -996,6 +1010,8 @@ namespace Prism
|
||||
DrawComponent<DirectionalLightComponent>("Directional Light", entity, [](DirectionalLightComponent& dlc)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
UI::Property("ShowIcon", dlc.ShowIcon);
|
||||
UI::Separator();
|
||||
UI::PropertyColor("Radiance", dlc.Radiance);
|
||||
UI::Property("Intensity", dlc.Intensity);
|
||||
UI::Property("Cast Shadows", dlc.CastShadows);
|
||||
@ -1007,6 +1023,8 @@ namespace Prism
|
||||
DrawComponent<PointLightComponent>("Point Light", entity, [](PointLightComponent& pc)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
UI::Property("ShowIcon", pc.ShowIcon);
|
||||
UI::Separator();
|
||||
|
||||
UI::PropertyColor("Radiance", pc.Radiance);
|
||||
UI::Property("Intensity", pc.Intensity);
|
||||
@ -1018,6 +1036,8 @@ namespace Prism
|
||||
DrawComponent<SpotLightComponent>("Spot Light", entity, [](SpotLightComponent& sc)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
UI::Property("ShowIcon", sc.ShowIcon);
|
||||
UI::Separator();
|
||||
|
||||
UI::PropertyColor("Radiance", sc.Radiance);
|
||||
UI::Property("Intensity", sc.Intensity);
|
||||
@ -1032,9 +1052,17 @@ namespace Prism
|
||||
{
|
||||
|
||||
UI::BeginPropertyGrid();
|
||||
UI::PropertyAssetReference("Environment Map", slc.SceneEnvironment, AssetType::EnvMap);
|
||||
|
||||
UI::Property("ShowIcon", slc.ShowIcon);
|
||||
UI::Separator();
|
||||
|
||||
if (UI::PropertyAssetReference("Environment Map", slc.SceneEnvironment, AssetType::EnvMap))
|
||||
{
|
||||
if (slc.DynamicSky) slc.DynamicSky = false;
|
||||
}
|
||||
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)
|
||||
@ -1044,7 +1072,7 @@ namespace Prism
|
||||
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);
|
||||
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(slc.TurbidityAzimuthInclination);
|
||||
slc.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ namespace Prism
|
||||
}
|
||||
|
||||
OpenGLFrameBuffer::OpenGLFrameBuffer(const FramebufferSpecification& spec)
|
||||
: m_Specification(spec), m_Width(spec.Width), m_Height(spec.Height)
|
||||
: m_Specification(spec)
|
||||
{
|
||||
for (auto format : m_Specification.Attachments.Attachments)
|
||||
{
|
||||
@ -124,7 +124,7 @@ namespace Prism
|
||||
Ref<const OpenGLFrameBuffer> instance = this;
|
||||
Renderer::Submit([instance]() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, instance->m_RendererID);
|
||||
glViewport(0, 0, instance->m_Width, instance->m_Height);
|
||||
glViewport(0, 0, instance->m_Specification.Width, instance->m_Specification.Height);
|
||||
});
|
||||
}
|
||||
|
||||
@ -137,11 +137,11 @@ namespace Prism
|
||||
|
||||
void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height, const bool forceReCreate)
|
||||
{
|
||||
if (!forceReCreate && (m_Width == width && m_Height == height))
|
||||
if (!forceReCreate && (m_Specification.Width == width && m_Specification.Height == height))
|
||||
return;
|
||||
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Specification.Width = width;
|
||||
m_Specification.Height = height;
|
||||
|
||||
Ref<OpenGLFrameBuffer> instance = this;
|
||||
Renderer::Submit([instance]() mutable
|
||||
@ -173,16 +173,16 @@ namespace Prism
|
||||
switch (instance->m_ColorAttachmentFormats[i])
|
||||
{
|
||||
case FramebufferTextureFormat::RGBA8:
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA8, instance->m_Width, instance->m_Height, i);
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA8, instance->m_Specification.Width, instance->m_Specification.Height, i);
|
||||
break;
|
||||
case FramebufferTextureFormat::RGBA16F:
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA16F, instance->m_Width, instance->m_Height, i);
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA16F, instance->m_Specification.Width, instance->m_Specification.Height, i);
|
||||
break;
|
||||
case FramebufferTextureFormat::RGBA32F:
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA32F, instance->m_Width, instance->m_Height, i);
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RGBA32F, instance->m_Specification.Width, instance->m_Specification.Height, i);
|
||||
break;
|
||||
case FramebufferTextureFormat::RG32F:
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RG32F, instance->m_Width, instance->m_Height, i);
|
||||
Utils::AttachColorTexture(instance->m_ColorAttachments[i], instance->m_Specification.Samples, GL_RG32F, instance->m_Specification.Width, instance->m_Specification.Height, i);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -196,10 +196,10 @@ namespace Prism
|
||||
switch (instance->m_DepthAttachmentFormat)
|
||||
{
|
||||
case FramebufferTextureFormat::DEPTH24STENCIL8:
|
||||
Utils::AttachDepthTexture(instance->m_DepthAttachment, instance->m_Specification.Samples, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, instance->m_Width, instance->m_Height);
|
||||
Utils::AttachDepthTexture(instance->m_DepthAttachment, instance->m_Specification.Samples, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, instance->m_Specification.Width, instance->m_Specification.Height);
|
||||
break;
|
||||
case FramebufferTextureFormat::DEPTH32F:
|
||||
Utils::AttachDepthTexture(instance->m_DepthAttachment, instance->m_Specification.Samples, GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, instance->m_Width, instance->m_Height);
|
||||
Utils::AttachDepthTexture(instance->m_DepthAttachment, instance->m_Specification.Samples, GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, instance->m_Specification.Width, instance->m_Specification.Height);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -40,8 +40,6 @@ namespace Prism
|
||||
|
||||
std::vector<FramebufferTextureFormat> m_ColorAttachmentFormats;
|
||||
FramebufferTextureFormat m_DepthAttachmentFormat = FramebufferTextureFormat::None;
|
||||
|
||||
uint32_t m_Width = 0, m_Height = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -67,7 +67,10 @@ namespace Prism {
|
||||
|
||||
void OpenGLStorageBuffer::GetData(void* outData, const uint32_t size, const uint32_t offset) const
|
||||
{
|
||||
glGetNamedBufferSubData(m_RendererID, offset, size, outData);
|
||||
Renderer::Submit([this, outData, size, offset]()
|
||||
{
|
||||
glGetNamedBufferSubData(m_RendererID, offset, size, outData);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,7 +17,7 @@ namespace Prism
|
||||
{
|
||||
case TextureFormat::RGB: return GL_RGB;
|
||||
case TextureFormat::RGBA: return GL_RGBA;
|
||||
case TextureFormat::Float16: return GL_RGBA16F;
|
||||
case TextureFormat::RGBA16F: return GL_RGBA16F;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -26,7 +26,7 @@ namespace Prism
|
||||
switch (format) {
|
||||
case TextureFormat::RGB: return GL_RGB8;
|
||||
case TextureFormat::RGBA: return GL_RGBA8;
|
||||
case TextureFormat::Float16: return GL_RGBA16F;
|
||||
case TextureFormat::RGBA16F: return GL_RGBA16F;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ namespace Prism
|
||||
switch (format) {
|
||||
case TextureFormat::RGB: return GL_RGB;
|
||||
case TextureFormat::RGBA: return GL_RGBA;
|
||||
case TextureFormat::Float16: return GL_RGBA; // 根据实际情况调整
|
||||
case TextureFormat::RGBA16F: return GL_RGBA; // 根据实际情况调整
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ namespace Prism
|
||||
switch (format) {
|
||||
case TextureFormat::RGB:
|
||||
case TextureFormat::RGBA: return GL_UNSIGNED_BYTE;
|
||||
case TextureFormat::Float16: return GL_HALF_FLOAT;
|
||||
case TextureFormat::RGBA16F: return GL_HALF_FLOAT;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@ -69,7 +69,12 @@ namespace Prism
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTextureParameterf(instance->m_RendererID, GL_TEXTURE_MAX_ANISOTROPY, RendererAPI::GetCapabilities().MaxAnisotropy);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, PrismToOpenGLTextureFormat(instance->m_Format), (GLint)instance->m_Width, (GLint)instance->m_Height, 0, Prism::PrismToOpenGLTextureFormat(instance->m_Format), GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
SizedInternalFormat(instance->m_Format), // 内部格式
|
||||
(GLint)instance->m_Width, (GLint)instance->m_Height, 0,
|
||||
ImageFormat(instance->m_Format), // 像素格式
|
||||
DataType(instance->m_Format), // 数据类型
|
||||
nullptr);
|
||||
// glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
@ -88,7 +93,7 @@ namespace Prism
|
||||
PM_CORE_INFO("Loading HDR texture {0}, srgb={1}", path, srgb);
|
||||
m_ImageData.Data = (byte*)stbi_loadf(path.c_str(), &width, &height, &channels, 0);
|
||||
m_IsHDR = true;
|
||||
m_Format = TextureFormat::Float16;
|
||||
m_Format = TextureFormat::RGBA16F;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -126,9 +131,12 @@ namespace Prism
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
const GLint wrap = instance->m_Wrap == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, wrap);
|
||||
|
||||
GLenum internalFormat = PrismToOpenGLTextureFormat(instance->m_Format);
|
||||
GLenum format = srgb ? GL_SRGB8 : (instance->m_IsHDR ? GL_RGB : PrismToOpenGLTextureFormat(instance->m_Format)); // HDR = GL_RGB for now
|
||||
@ -178,6 +186,27 @@ namespace Prism
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLTexture2D::SetData(const void* data, int count)
|
||||
{
|
||||
Lock();
|
||||
|
||||
PM_CORE_ASSERT(count <= m_ImageData.Size * 4);
|
||||
// Convert RGBA32F color to RGBA8
|
||||
auto pixels = m_ImageData.Data;
|
||||
|
||||
const auto* pixelData = static_cast<const glm::vec4*>(data);
|
||||
for (uint32_t i = 0; i < m_Width * m_Height; i++)
|
||||
{
|
||||
const glm::vec4& value = pixelData[i];
|
||||
*pixels++ = static_cast<uint32_t>(value.x * 255.0f);
|
||||
*pixels++ = static_cast<uint32_t>(value.y * 255.0f);
|
||||
*pixels++ = static_cast<uint32_t>(value.z * 255.0f);
|
||||
*pixels++ = static_cast<uint32_t>(value.w * 255.0f);
|
||||
}
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void OpenGLTexture2D::Resize(uint32_t width, uint32_t height)
|
||||
{
|
||||
PM_CORE_ASSERT(m_Locked, "Texture must be locked!");
|
||||
|
||||
@ -30,6 +30,8 @@ namespace Prism
|
||||
virtual void Lock() override;
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual void SetData(const void* data, int count) override;
|
||||
|
||||
virtual void Resize(uint32_t width, uint32_t height) override;
|
||||
virtual Buffer GetWriteableBuffer() override;
|
||||
|
||||
@ -47,7 +49,7 @@ namespace Prism
|
||||
RendererID m_RendererID = 0;
|
||||
TextureFormat m_Format;
|
||||
unsigned int m_Width, m_Height;
|
||||
TextureWrap m_Wrap = TextureWrap::Clamp;
|
||||
TextureWrap m_Wrap = TextureWrap::Repeat;
|
||||
|
||||
bool m_IsHDR = false;
|
||||
bool m_Loaded = false;
|
||||
|
||||
@ -119,6 +119,8 @@ namespace Prism
|
||||
|
||||
static Ref<MaterialInstance> Create(const Ref<Material>& material);
|
||||
|
||||
static Ref<MaterialInstance> Copy(Ref<MaterialInstance> other);
|
||||
|
||||
template<typename T>
|
||||
T& Get(const std::string& name)
|
||||
{
|
||||
|
||||
@ -38,13 +38,16 @@ namespace Prism
|
||||
// Ref<RenderPass> CompositePass;
|
||||
Ref<RenderPass> BloomBlurPass[2];
|
||||
Ref<RenderPass> BloomBlendPass;
|
||||
Ref<Texture2D> ResolvedHDRTexture; // 解析后的单样本 HDR 颜色
|
||||
|
||||
struct AutoExposureData
|
||||
{
|
||||
Ref<RenderPass> LuminancePass;
|
||||
|
||||
float Exposure = 1.0f;
|
||||
|
||||
bool EnableAutoExposure = true;
|
||||
float Key = 0.11f;
|
||||
float Key = 0.3f;
|
||||
Timer ExposureTimer;
|
||||
float MaxExposure = 5.0f;
|
||||
float MinExposure = 0.01f;
|
||||
@ -266,12 +269,16 @@ namespace Prism
|
||||
s_Data.BlackCubeTexture = TextureCube::Create(TextureFormat::RGBA, 1, 1, &blackTextureData);
|
||||
}
|
||||
|
||||
void Renderer3D::SetViewportSize(uint32_t width, uint32_t height)
|
||||
void Renderer3D::SetViewportSize(const uint32_t width, const uint32_t height)
|
||||
{
|
||||
s_Data.GeoPass->GetSpecification().TargetFramebuffer->Resize(width, height);
|
||||
// s_Data.CompositePass->GetSpecification().TargetFramebuffer->Resize(width, height);
|
||||
if (s_Data.AutoExposureData.LuminancePass)
|
||||
s_Data.AutoExposureData.LuminancePass->GetSpecification().TargetFramebuffer->Resize(width, height);
|
||||
|
||||
s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->Resize(width, height);
|
||||
s_Data.BloomBlurPass[1]->GetSpecification().TargetFramebuffer->Resize(width, height);
|
||||
s_Data.BloomBlendPass->GetSpecification().TargetFramebuffer->Resize(width, height);
|
||||
}
|
||||
|
||||
void Renderer3D::BeginScene(const Scene* scene, const SceneRendererCamera& camera)
|
||||
@ -331,11 +338,11 @@ namespace Prism
|
||||
constexpr uint32_t cubemapSize = 2048;
|
||||
constexpr uint32_t irradianceMapSize = 32;
|
||||
|
||||
Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize);
|
||||
Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize);
|
||||
if (!equirectangularConversionShader)
|
||||
equirectangularConversionShader = Shader::Create("assets/shaders/EquirectangularToCubeMap.glsl");
|
||||
Ref<Texture2D> envEquirect = Texture2D::Create(filepath);
|
||||
if (envEquirect->GetFormat() != TextureFormat::Float16)
|
||||
if (envEquirect->GetFormat() != TextureFormat::RGBA16F)
|
||||
PM_CORE_WARN("Texture is not HDR!");
|
||||
|
||||
equirectangularConversionShader->Bind();
|
||||
@ -351,7 +358,7 @@ namespace Prism
|
||||
if (!envFilteringShader)
|
||||
envFilteringShader = Shader::Create("assets/shaders/EnvironmentMipFilter.glsl");
|
||||
|
||||
Ref<TextureCube> envFiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize);
|
||||
Ref<TextureCube> envFiltered = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize);
|
||||
|
||||
Renderer::Submit([envUnfiltered, envFiltered]()
|
||||
{
|
||||
@ -377,7 +384,7 @@ namespace Prism
|
||||
if (!envIrradianceShader)
|
||||
envIrradianceShader = Shader::Create("assets/shaders/EnvironmentIrradiance.glsl");
|
||||
|
||||
Ref<TextureCube> irradianceMap = TextureCube::Create(TextureFormat::Float16, irradianceMapSize, irradianceMapSize);
|
||||
Ref<TextureCube> irradianceMap = TextureCube::Create(TextureFormat::RGBA16F, irradianceMapSize, irradianceMapSize);
|
||||
envIrradianceShader->Bind();
|
||||
envFiltered->Bind();
|
||||
Renderer::Submit([irradianceMap]()
|
||||
@ -393,19 +400,18 @@ namespace Prism
|
||||
|
||||
static Ref<Shader> preethamSkyShader;
|
||||
|
||||
Ref<TextureCube> Renderer3D::CreatePreethamSky(float turbidity, float azimuth, float inclination)
|
||||
Ref<TextureCube> Renderer3D::CreatePreethamSky(const glm::vec3& turbidityAzimuthInclination)
|
||||
{
|
||||
constexpr uint32_t cubemapSize = 2048;
|
||||
|
||||
Ref<TextureCube> environmentMap = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize);
|
||||
Ref<TextureCube> environmentMap = TextureCube::Create(TextureFormat::RGBA16F, 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);
|
||||
preethamSkyShader->SetFloat3("u_TurbidityAzimuthInclination", turbidityAzimuthInclination);
|
||||
|
||||
Renderer::Submit([environmentMap, cubemapSize]()
|
||||
{
|
||||
@ -418,13 +424,6 @@ namespace Prism
|
||||
return environmentMap;
|
||||
}
|
||||
|
||||
/*
|
||||
Ref<RenderPass> Renderer3D::GetFinalRenderPass()
|
||||
{
|
||||
return s_Data.CompositePass;
|
||||
}
|
||||
*/
|
||||
|
||||
Ref<RenderPass> Renderer3D::GetGeoPass()
|
||||
{
|
||||
return s_Data.GeoPass;
|
||||
@ -441,12 +440,6 @@ namespace Prism
|
||||
s_Data.FocusPoint = point;
|
||||
}
|
||||
|
||||
/*
|
||||
uint32_t Renderer3D::GetFinalColorBufferRendererID()
|
||||
{
|
||||
return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
||||
}
|
||||
*/
|
||||
|
||||
SceneRendererOptions& Renderer3D::GetOptions()
|
||||
{
|
||||
@ -475,6 +468,8 @@ namespace Prism
|
||||
Renderer::Submit([] { s_Stats.GeometryPass = s_Stats.GeometryPassTimer.ElapsedMillis(); });
|
||||
}
|
||||
|
||||
ResolveMSAA();
|
||||
|
||||
// Compute average luminance and update exposure (GPU-copy + mipmap -> read 1 texel)
|
||||
{
|
||||
Renderer::Submit([]() { s_Stats.AutoExposurePassTimer.Reset(); });
|
||||
@ -482,30 +477,13 @@ namespace Prism
|
||||
Renderer::Submit([] { s_Stats.AutoExposurePass = s_Stats.AutoExposurePassTimer.ElapsedMillis(); });
|
||||
}
|
||||
|
||||
BloomBlurPass();
|
||||
|
||||
OverlayPass();
|
||||
|
||||
{
|
||||
Renderer::Submit([]() { s_Stats.CompositePassTimer.Reset(); });
|
||||
// CompositePass();
|
||||
{
|
||||
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->SetFloat("u_EnableBloom", s_Data.EnableBloom);
|
||||
|
||||
s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture();
|
||||
Renderer::Submit([]()
|
||||
{
|
||||
glBindTextureUnit(1, s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID());
|
||||
});
|
||||
|
||||
Renderer::SubmitFullscreenQuad(nullptr);
|
||||
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
CompositePass(outRenderPass);
|
||||
Renderer::Submit([] { s_Stats.CompositePass = s_Stats.CompositePassTimer.ElapsedMillis(); });
|
||||
// BloomBlurPass();
|
||||
}
|
||||
@ -517,6 +495,119 @@ namespace Prism
|
||||
s_Data.SceneData = {};
|
||||
}
|
||||
|
||||
void Renderer3D::AutoExposurePass()
|
||||
{
|
||||
auto& ae = s_Data.AutoExposureData;
|
||||
if (!ae.EnableAutoExposure)
|
||||
return;
|
||||
|
||||
auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
||||
auto dstFB = ae.LuminancePass->GetSpecification().TargetFramebuffer;
|
||||
if (!srcFB || !dstFB) return;
|
||||
|
||||
float dt = ae.ExposureTimer;
|
||||
ae.ExposureTimer.Reset();
|
||||
|
||||
Renderer::Submit([srcFB, dstFB, logMin = ae.LogMin, logMax = ae.LogMax, histCS = ae.HistogramCS, histSSBO = ae.HistogramSSBO]() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
0, 0, dstFB->GetWidth(), dstFB->GetHeight(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
const uint32_t zero = 0;
|
||||
glClearNamedBufferData(histSSBO->GetRendererID(), GL_R32UI, GL_RED, GL_UNSIGNED_INT, &zero);
|
||||
|
||||
glUseProgram(histCS->GetRendererID());
|
||||
glBindTextureUnit(0, dstFB->GetColorAttachmentRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, histSSBO->GetRendererID());
|
||||
|
||||
const GLint locLogMin = glGetUniformLocation(histCS->GetRendererID(), "u_LogMin");
|
||||
const GLint locLogMax = glGetUniformLocation(histCS->GetRendererID(), "u_LogMax");
|
||||
if (locLogMin != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMin, logMin);
|
||||
if (locLogMax != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMax, logMax);
|
||||
|
||||
const uint32_t groupsX = (dstFB->GetWidth() + 15) / 16;
|
||||
const uint32_t groupsY = (dstFB->GetHeight() + 15) / 16;
|
||||
glDispatchCompute(groupsX, groupsY, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
});
|
||||
|
||||
Renderer::Submit([&ae, dt]() {
|
||||
glUseProgram(ae.ExposureCS->GetRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ae.HistogramSSBO->GetRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ae.ExposureSSBO->GetRendererID());
|
||||
|
||||
auto setUniform = [&](const char* name, const float value) {
|
||||
const GLint loc = glGetUniformLocation(ae.ExposureCS->GetRendererID(), name);
|
||||
if (loc != -1) glProgramUniform1f(ae.ExposureCS->GetRendererID(), loc, value);
|
||||
};
|
||||
|
||||
setUniform("u_SpeedUp", ae.SpeedUp);
|
||||
setUniform("u_SpeedDown", ae.SpeedDown);
|
||||
setUniform("u_Key", ae.Key);
|
||||
setUniform("u_LowPercent", ae.LowPercent);
|
||||
setUniform("u_HighPercent", ae.HighPercent);
|
||||
setUniform("u_MinExposure", ae.MinExposure);
|
||||
setUniform("u_MaxExposure", ae.MaxExposure);
|
||||
setUniform("u_DeltaTime", dt);
|
||||
setUniform("u_LogMin", ae.LogMin);
|
||||
setUniform("u_LogMax", ae.LogMax);
|
||||
|
||||
glDispatchCompute(1, 1, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer3D::ShadowMapPass()
|
||||
{
|
||||
const auto& directionalLights = s_Data.SceneData.SceneLightEnvironment.DirectionalLights;
|
||||
if (!s_Data.ShadowEnabled || directionalLights[0].Intensity == 0.0f || !directionalLights[0].CastShadows)
|
||||
{
|
||||
// Clear shadow maps
|
||||
Renderer::BeginRenderPass(s_Data.ShadowMapRenderPass);
|
||||
Renderer::EndRenderPass();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: this will not be hardcode
|
||||
const glm::vec3 lightDir = glm::normalize(directionalLights[0].Direction); // 光线方向(从光源指向场景)
|
||||
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));
|
||||
|
||||
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([]()
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
});
|
||||
|
||||
{
|
||||
Renderer::BeginRenderPass(s_Data.ShadowMapRenderPass);
|
||||
|
||||
s_Data.LightMatrices = lightSpaceMatrix;
|
||||
|
||||
|
||||
// Render entities
|
||||
for (auto& dc : s_Data.ShadowPassDrawList)
|
||||
{
|
||||
Ref<Shader> shader = dc.mesh->IsAnimated() ? s_Data.ShadowMapAnimShader : s_Data.ShadowMapShader;
|
||||
shader->SetMat4("u_LightViewProjection", lightSpaceMatrix);
|
||||
Renderer::SubmitMeshWithShader(dc.mesh, dc.Transform, shader);
|
||||
}
|
||||
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer3D::GeometryPass()
|
||||
{
|
||||
const bool outline = !s_Data.SelectedMeshDrawList.empty();
|
||||
@ -549,7 +640,6 @@ namespace Prism
|
||||
|
||||
|
||||
// Skybox
|
||||
auto skyboxShader = s_Data.SceneData.SkyboxMaterial->GetShader();
|
||||
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);
|
||||
@ -830,24 +920,7 @@ namespace Prism
|
||||
|
||||
|
||||
// Grid
|
||||
const auto option = GetOptions();
|
||||
if (option.ShowGrid)
|
||||
{
|
||||
s_Data.GridData.GridMaterial->Set("u_View", sceneCamera.ViewMatrix);
|
||||
s_Data.GridData.GridMaterial->Set("u_Projection", cameraProjection);
|
||||
s_Data.GridData.GridMaterial->Set("u_CameraPosition", cameraPosition);
|
||||
|
||||
// grid config
|
||||
s_Data.GridData.GridMaterial->Set("u_GridPlane", s_Data.GridData.GridPlane);
|
||||
s_Data.GridData.GridMaterial->Set("u_GridScale", s_Data.GridData.GridScale);
|
||||
s_Data.GridData.GridMaterial->Set("u_GridColorThin", s_Data.GridData.GridColorThin);
|
||||
s_Data.GridData.GridMaterial->Set("u_GridColorThick", s_Data.GridData.GridColorThick);
|
||||
s_Data.GridData.GridMaterial->Set("u_AxisColorX", s_Data.GridData.AxisColorX);
|
||||
s_Data.GridData.GridMaterial->Set("u_AxisColorZ", s_Data.GridData.AxisColorZ);
|
||||
s_Data.GridData.GridMaterial->Set("u_FadeDistance", s_Data.GridData.FadeDistance);
|
||||
|
||||
Renderer::SubmitFullscreenQuad(s_Data.GridData.GridMaterial);
|
||||
}
|
||||
const auto option = GetOptions();
|
||||
|
||||
if (option.ShowBoundingBoxes)
|
||||
{
|
||||
@ -860,74 +933,174 @@ namespace Prism
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
void Renderer3D::AutoExposurePass()
|
||||
void Renderer3D::BloomBlurPass()
|
||||
{
|
||||
auto& ae = s_Data.AutoExposureData;
|
||||
if (!ae.EnableAutoExposure)
|
||||
if (!s_Data.EnableBloom)
|
||||
{
|
||||
// 如果关闭 Bloom,可以清除 BloomBlendPass(避免使用旧数据)
|
||||
Renderer::BeginRenderPass(s_Data.BloomBlendPass);
|
||||
Renderer::EndRenderPass();
|
||||
return;
|
||||
}
|
||||
|
||||
auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
||||
auto dstFB = ae.LuminancePass->GetSpecification().TargetFramebuffer;
|
||||
if (!srcFB || !dstFB) return;
|
||||
uint32_t srcTex = s_Data.ResolvedHDRTexture->GetRendererID();
|
||||
const int iterations = 5; // 模糊迭代次数,可调
|
||||
|
||||
float dt = ae.ExposureTimer;
|
||||
ae.ExposureTimer.Reset();
|
||||
// 第一次:提取高光 + 水平模糊
|
||||
{
|
||||
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);
|
||||
Renderer::Submit([srcTex]() { glBindTextureUnit(0, srcTex); });
|
||||
Renderer::SubmitFullscreenQuad(nullptr);
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
Renderer::Submit([srcFB, dstFB, logMin = ae.LogMin, logMax = ae.LogMax, histCS = ae.HistogramCS, histSSBO = ae.HistogramSSBO]() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
0, 0, dstFB->GetWidth(), dstFB->GetHeight(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
// 后续迭代
|
||||
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];
|
||||
|
||||
const uint32_t zero = 0;
|
||||
glClearNamedBufferData(histSSBO->GetRendererID(), GL_R32UI, GL_RED, GL_UNSIGNED_INT, &zero);
|
||||
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();
|
||||
}
|
||||
|
||||
glUseProgram(histCS->GetRendererID());
|
||||
glBindTextureUnit(0, dstFB->GetColorAttachmentRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, histSSBO->GetRendererID());
|
||||
// 将最终模糊结果拷贝到 BloomBlendPass(供合成使用)
|
||||
uint32_t finalBlurTex = (iterations % 2 == 0) ?
|
||||
s_Data.BloomBlurPass[1]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID() :
|
||||
s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
||||
|
||||
const GLint locLogMin = glGetUniformLocation(histCS->GetRendererID(), "u_LogMin");
|
||||
const GLint locLogMax = glGetUniformLocation(histCS->GetRendererID(), "u_LogMax");
|
||||
if (locLogMin != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMin, logMin);
|
||||
if (locLogMax != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMax, logMax);
|
||||
|
||||
const uint32_t groupsX = (dstFB->GetWidth() + 15) / 16;
|
||||
const uint32_t groupsY = (dstFB->GetHeight() + 15) / 16;
|
||||
glDispatchCompute(groupsX, groupsY, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
});
|
||||
|
||||
Renderer::Submit([&ae, dt]() {
|
||||
glUseProgram(ae.ExposureCS->GetRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ae.HistogramSSBO->GetRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ae.ExposureSSBO->GetRendererID());
|
||||
|
||||
auto setUniform = [&](const char* name, const float value) {
|
||||
const GLint loc = glGetUniformLocation(ae.ExposureCS->GetRendererID(), name);
|
||||
if (loc != -1) glProgramUniform1f(ae.ExposureCS->GetRendererID(), loc, value);
|
||||
};
|
||||
|
||||
setUniform("u_SpeedUp", ae.SpeedUp);
|
||||
setUniform("u_SpeedDown", ae.SpeedDown);
|
||||
setUniform("u_Key", ae.Key);
|
||||
setUniform("u_LowPercent", ae.LowPercent);
|
||||
setUniform("u_HighPercent", ae.HighPercent);
|
||||
setUniform("u_MinExposure", ae.MinExposure);
|
||||
setUniform("u_MaxExposure", ae.MaxExposure);
|
||||
setUniform("u_DeltaTime", dt);
|
||||
setUniform("u_LogMin", ae.LogMin);
|
||||
setUniform("u_LogMax", ae.LogMax);
|
||||
|
||||
glDispatchCompute(1, 1, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
});
|
||||
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);
|
||||
Renderer::Submit([finalBlurTex]() { glBindTextureUnit(0, finalBlurTex); });
|
||||
Renderer::SubmitFullscreenQuad(nullptr);
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
void Renderer3D::OverlayPass()
|
||||
{
|
||||
Renderer::BeginRenderPass(s_Data.GeoPass, false);
|
||||
|
||||
if (const auto option = GetOptions(); option.ShowGrid)
|
||||
{
|
||||
const auto& sceneCamera = s_Data.SceneData.SceneCamera;
|
||||
|
||||
const auto cameraProjection = sceneCamera.Camera.GetProjectionMatrix();
|
||||
const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3]; // TODO: Negate instead
|
||||
|
||||
s_Data.GridData.GridMaterial->Set("u_View", sceneCamera.ViewMatrix);
|
||||
s_Data.GridData.GridMaterial->Set("u_Projection", cameraProjection);
|
||||
s_Data.GridData.GridMaterial->Set("u_CameraPosition", cameraPosition);
|
||||
|
||||
// grid config
|
||||
s_Data.GridData.GridMaterial->Set("u_GridPlane", s_Data.GridData.GridPlane);
|
||||
s_Data.GridData.GridMaterial->Set("u_GridScale", s_Data.GridData.GridScale);
|
||||
s_Data.GridData.GridMaterial->Set("u_GridColorThin", s_Data.GridData.GridColorThin);
|
||||
s_Data.GridData.GridMaterial->Set("u_GridColorThick", s_Data.GridData.GridColorThick);
|
||||
s_Data.GridData.GridMaterial->Set("u_AxisColorX", s_Data.GridData.AxisColorX);
|
||||
s_Data.GridData.GridMaterial->Set("u_AxisColorZ", s_Data.GridData.AxisColorZ);
|
||||
s_Data.GridData.GridMaterial->Set("u_FadeDistance", s_Data.GridData.FadeDistance);
|
||||
|
||||
Renderer::SubmitFullscreenQuad(s_Data.GridData.GridMaterial);
|
||||
}
|
||||
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
void Renderer3D::CompositePass(const Ref<RenderPass>& 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<RenderPass>& 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
|
||||
{
|
||||
@ -1084,61 +1257,47 @@ namespace Prism
|
||||
return corners;
|
||||
}
|
||||
|
||||
void Renderer3D::ShadowMapPass()
|
||||
|
||||
void Renderer3D::ResolveMSAA()
|
||||
{
|
||||
const auto& directionalLights = s_Data.SceneData.SceneLightEnvironment.DirectionalLights;
|
||||
if (directionalLights[0].Intensity == 0.0f || !directionalLights[0].CastShadows)
|
||||
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)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Clear shadow maps
|
||||
Renderer::BeginRenderPass(s_Data.ShadowMapRenderPass);
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
return;
|
||||
s_Data.ResolvedHDRTexture = Texture2D::Create(TextureFormat::RGBA16F, width, height);
|
||||
}
|
||||
|
||||
// TODO: this will not be hardcode
|
||||
const glm::vec3 lightDir = glm::normalize(directionalLights[0].Direction); // 光线方向(从光源指向场景)
|
||||
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));
|
||||
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);
|
||||
|
||||
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;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
Renderer::Submit([]()
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
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);
|
||||
});
|
||||
|
||||
{
|
||||
Renderer::BeginRenderPass(s_Data.ShadowMapRenderPass);
|
||||
|
||||
s_Data.LightMatrices = lightSpaceMatrix;
|
||||
|
||||
|
||||
// Render entities
|
||||
for (auto& dc : s_Data.ShadowPassDrawList)
|
||||
{
|
||||
Ref<Shader> shader = dc.mesh->IsAnimated() ? s_Data.ShadowMapAnimShader : s_Data.ShadowMapShader;
|
||||
shader->SetMat4("u_LightViewProjection", lightSpaceMatrix);
|
||||
Renderer::SubmitMeshWithShader(dc.mesh, dc.Transform, shader);
|
||||
}
|
||||
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SceneRenderer::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Scene Renderer");
|
||||
|
||||
|
||||
UI::Property("Composite Pass time", s_Stats.CompositePass);
|
||||
UI::Property("Geometry Pass time", s_Stats.GeometryPass);
|
||||
UI::Property("Composite Pass time", s_Stats.CompositePass);
|
||||
UI::Property("Shadow Pass time", s_Stats.ShadowPass);
|
||||
UI::Property("AutoExposure Pass time", s_Stats.AutoExposurePass);
|
||||
|
||||
@ -1207,10 +1366,15 @@ namespace Prism
|
||||
auto fb = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer;
|
||||
const auto id = fb->GetColorAttachmentRendererID();
|
||||
|
||||
auto fb2 = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer;
|
||||
const auto id2 = fb2->GetColorAttachmentRendererID();
|
||||
|
||||
const float size = ImGui::GetContentRegionAvail().x; // (float)fb->GetWidth() * 0.5f, (float)fb->GetHeight() * 0.5f
|
||||
float w = size;
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +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<TextureCube> CreatePreethamSky(const glm::vec3& turbidityAzimuthInclination);
|
||||
|
||||
// static Ref<RenderPass> GetFinalRenderPass();
|
||||
static Ref<RenderPass> GetGeoPass();
|
||||
@ -59,10 +59,15 @@ namespace Prism
|
||||
static void FlushDrawList(Ref<RenderPass>& outRenderPass);
|
||||
|
||||
static void AutoExposurePass();
|
||||
static void GeometryPass();
|
||||
// static void CompositePass();
|
||||
// static void BloomBlurPass();
|
||||
static void ShadowMapPass();
|
||||
static void GeometryPass();
|
||||
static void BloomBlurPass();
|
||||
static void OverlayPass();
|
||||
|
||||
static void CompositePass(const Ref<RenderPass>& outRenderPass);
|
||||
|
||||
|
||||
static void ResolveMSAA();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -23,9 +23,6 @@ namespace Prism
|
||||
{
|
||||
Prism::Camera Camera;
|
||||
glm::mat4 ViewMatrix;
|
||||
|
||||
float Near, Far;
|
||||
float FOV;
|
||||
};
|
||||
|
||||
class PRISM_API SceneRenderer
|
||||
|
||||
@ -18,7 +18,7 @@ namespace Prism
|
||||
None = 0,
|
||||
RGB = 1,
|
||||
RGBA = 2,
|
||||
Float16 = 3,
|
||||
RGBA16F = 3,
|
||||
};
|
||||
|
||||
enum class TextureWrap
|
||||
@ -62,6 +62,7 @@ namespace Prism
|
||||
|
||||
virtual void Lock() = 0;
|
||||
virtual void Unlock() = 0;
|
||||
virtual void SetData(const void* data, int count) = 0;
|
||||
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
||||
virtual Buffer GetWriteableBuffer() = 0;
|
||||
|
||||
|
||||
@ -91,13 +91,32 @@ namespace Prism
|
||||
struct MeshComponent
|
||||
{
|
||||
Ref<Mesh> Mesh;
|
||||
// std::vector<Ref<MaterialInstance>> Materials;
|
||||
|
||||
MeshComponent() = default;
|
||||
MeshComponent(const MeshComponent& other) = default;
|
||||
MeshComponent(const Ref<Prism::Mesh>& mesh)
|
||||
: Mesh(mesh) {}
|
||||
: Mesh(mesh) {}
|
||||
|
||||
operator Ref<Prism::Mesh> () { return Mesh; }
|
||||
|
||||
/*
|
||||
MeshComponent(Ref<Prism::Mesh> mesh)
|
||||
: Mesh(mesh)
|
||||
{
|
||||
// 复制 Mesh 的材质实例,每个实体拥有独立副本
|
||||
if (mesh)
|
||||
{
|
||||
const auto& srcMaterials = mesh->GetMaterials();
|
||||
Materials.reserve(srcMaterials.size());
|
||||
for (auto& srcMat : srcMaterials)
|
||||
{
|
||||
auto newMat = MaterialInstance::Copy(srcMat);
|
||||
Materials.push_back(newMat);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
struct AnimationComponent
|
||||
@ -126,6 +145,7 @@ namespace Prism
|
||||
{
|
||||
SceneCamera Camera;
|
||||
bool Primary = true;
|
||||
bool ShowIcon = true;
|
||||
|
||||
CameraComponent() = default;
|
||||
CameraComponent(const CameraComponent& other) = default;
|
||||
@ -373,6 +393,7 @@ namespace Prism
|
||||
bool CastShadows = true;
|
||||
bool SoftShadows = true;
|
||||
float LightSize = 0.5f; // For PCSS
|
||||
bool ShowIcon = true;
|
||||
};
|
||||
|
||||
struct PointLightComponent
|
||||
@ -381,6 +402,7 @@ namespace Prism
|
||||
float Radius = 10.0f;
|
||||
float Intensity = 1.0f;
|
||||
uint32_t CastShadows;
|
||||
bool ShowIcon = true;
|
||||
|
||||
PointLightComponent() = default;
|
||||
PointLightComponent(const PointLightComponent& other) = default;
|
||||
@ -395,6 +417,7 @@ namespace Prism
|
||||
float InnerConeAngle = glm::radians(30.0f); // 内锥角(半角)
|
||||
float OuterConeAngle = glm::radians(45.0f); // 外锥角(半角)
|
||||
bool CastShadows = true; // 聚光通常需要阴影
|
||||
bool ShowIcon = true;
|
||||
|
||||
SpotLightComponent() = default;
|
||||
SpotLightComponent(const SpotLightComponent& other) = default;
|
||||
@ -405,6 +428,7 @@ namespace Prism
|
||||
Ref<Environment> SceneEnvironment;
|
||||
float Intensity = 1.0f;
|
||||
float Angle = 0.0f;
|
||||
bool ShowIcon = false;
|
||||
|
||||
bool DynamicSky = false;
|
||||
glm::vec3 TurbidityAzimuthInclination = { 2.0, 0.0, 0.0 };
|
||||
|
||||
@ -159,34 +159,15 @@ namespace Prism
|
||||
return;
|
||||
|
||||
const glm::mat4 cameraViewMatrix = glm::inverse(GetTransformRelativeToParent(cameraEntity));
|
||||
PM_CORE_ASSERT(cameraEntity, "Scene does not contain any cameras!");
|
||||
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
||||
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 3D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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(0.0f, 0.0f, -1.0f));
|
||||
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||
{
|
||||
direction,
|
||||
lightComponent.Radiance,
|
||||
lightComponent.Intensity,
|
||||
lightComponent.CastShadows
|
||||
};
|
||||
}
|
||||
}
|
||||
UpdateLights();
|
||||
|
||||
// TODO: only one sky light at the moment!
|
||||
{
|
||||
@ -248,70 +229,9 @@ namespace Prism
|
||||
|
||||
void Scene::OnRenderEditor(const TimeStep ts, const EditorCamera& editorCamera)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 3D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Process lights
|
||||
{
|
||||
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(0.0f, 0.0f,1.0f));
|
||||
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||
{
|
||||
direction,
|
||||
lightComponent.Radiance,
|
||||
lightComponent.Intensity,
|
||||
lightComponent.CastShadows
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
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 ++;
|
||||
}
|
||||
}
|
||||
// Process lights Direction, Point, Spot
|
||||
UpdateLights();
|
||||
|
||||
// TODO: only one sky light at the moment!
|
||||
{
|
||||
@ -325,7 +245,7 @@ namespace Prism
|
||||
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);
|
||||
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(skyLightComponent.TurbidityAzimuthInclination);
|
||||
skyLightComponent.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
|
||||
}
|
||||
|
||||
@ -341,8 +261,13 @@ namespace Prism
|
||||
|
||||
// TODO: this value should be storage and can modify
|
||||
// TODO: Renderer2D cannot blend with Renderer3D
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f}, false);
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix()}, false);
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 3D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
{
|
||||
for (const auto [entity, meshComponent, transformComponent]: group.each())
|
||||
@ -400,23 +325,57 @@ namespace Prism
|
||||
|
||||
// render camera icon
|
||||
{
|
||||
const auto editorCameraPosition = editorCamera.GetPosition();
|
||||
const auto editorCameraUpDirection = editorCamera.GetUpDirection();
|
||||
|
||||
const auto cameras = m_Registry.view<CameraComponent>();
|
||||
if (!cameras.empty())
|
||||
{
|
||||
for (auto& entity : cameras)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_CameraIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||
if (!e.GetComponent<CameraComponent>().ShowIcon) continue;
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_CameraIcon, editorCameraPosition, editorCameraUpDirection);
|
||||
}
|
||||
}
|
||||
|
||||
const auto lights = m_Registry.view<SkyLightComponent>();
|
||||
if (!lights.empty())
|
||||
if (const auto skyLights = m_Registry.view<SkyLightComponent>(); !skyLights.empty())
|
||||
{
|
||||
for (auto& entity : lights)
|
||||
for (auto& entity : skyLights)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||
if (!e.GetComponent<SkyLightComponent>().ShowIcon) continue;
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCameraPosition, editorCameraUpDirection);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto directionLight = m_Registry.view<DirectionalLightComponent>(); !directionLight.empty())
|
||||
{
|
||||
for (auto& entity : directionLight)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
if (!e.GetComponent<DirectionalLightComponent>().ShowIcon) continue;
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCameraPosition, editorCameraUpDirection);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto pointLight = m_Registry.view<PointLightComponent>(); !pointLight.empty())
|
||||
{
|
||||
for (auto& entity : pointLight )
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
if (!e.GetComponent<PointLightComponent>().ShowIcon) continue;
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCameraPosition, editorCameraUpDirection);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto spotLight = m_Registry.view<SpotLightComponent>(); !spotLight.empty())
|
||||
{
|
||||
for (auto& entity : spotLight )
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
if (!e.GetComponent<SpotLightComponent>().ShowIcon) continue;
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCameraPosition, editorCameraUpDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -446,6 +405,7 @@ namespace Prism
|
||||
// Box2D physics
|
||||
Physics2D::CreateBody(this);
|
||||
|
||||
// PhyX
|
||||
{
|
||||
auto view = m_Registry.view<RigidBodyComponent>();
|
||||
// Physics3D::ExpandEntityBuffer(static_cast<uint32_t>(view.size()));
|
||||
@ -485,11 +445,10 @@ namespace Prism
|
||||
|
||||
Entity Scene::GetMainCameraEntity()
|
||||
{
|
||||
auto view = m_Registry.view<CameraComponent>();
|
||||
const auto view = m_Registry.view<CameraComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& comp = view.get<CameraComponent>(entity);
|
||||
if (comp.Primary)
|
||||
if (const auto& comp = view.get<CameraComponent>(entity); comp.Primary)
|
||||
return { entity, this };
|
||||
}
|
||||
return {};
|
||||
@ -577,33 +536,6 @@ namespace Prism
|
||||
newEntity = CreateEntity();
|
||||
|
||||
CopyComponentIfExists(AllComponent{},newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
/*
|
||||
CopyComponentIfExists<TransformComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
|
||||
CopyComponentIfExists<RelationshipComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
|
||||
CopyComponentIfExists<MeshComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<DirectionalLightComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<SkyLightComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<ScriptComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<CameraComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<SpriteRendererComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<RigidBody2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<BoxCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<CircleCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<RigidBodyComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<BoxColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<SphereColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<CapsuleColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<MeshColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<AnimationComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<DistanceJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<RevoluteJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<PrismaticJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<WeldJoint2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
Entity Scene::FindEntityByTag(const std::string &tag) {
|
||||
@ -613,7 +545,7 @@ namespace Prism
|
||||
{
|
||||
const auto& canditate = view.get<TagComponent>(entity).Tag;
|
||||
if (canditate == tag)
|
||||
return Entity(entity, this);
|
||||
return {entity, this};
|
||||
}
|
||||
|
||||
return Entity{};
|
||||
@ -625,8 +557,7 @@ namespace Prism
|
||||
auto view = m_Registry.view<IDComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& idComponent = m_Registry.get<IDComponent>(entity);
|
||||
if (idComponent.ID == uuid)
|
||||
if (auto& idComponent = m_Registry.get<IDComponent>(entity); idComponent.ID == uuid)
|
||||
return {entity, this};
|
||||
}
|
||||
|
||||
@ -660,32 +591,7 @@ namespace Prism
|
||||
enttMap[uuid] = e.m_EntityHandle;
|
||||
}
|
||||
CopyComponent(AllComponent{},target->m_Registry, m_Registry, enttMap);
|
||||
/*
|
||||
CopyComponent<TagComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<TransformComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
CopyComponent<RelationshipComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
CopyComponent<MeshComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<DirectionalLightComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<SkyLightComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<ScriptComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<CameraComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<SpriteRendererComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<RigidBody2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<BoxCollider2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<CircleCollider2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<RigidBodyComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<BoxColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<SphereColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<CapsuleColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<MeshColliderComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<AnimationComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<DistanceJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<RevoluteJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<PrismaticJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<WeldJoint2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
*/
|
||||
|
||||
const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap();
|
||||
if (entityInstanceMap.find(target->GetUUID()) != entityInstanceMap.end())
|
||||
@ -717,6 +623,72 @@ namespace Prism
|
||||
b2World_SetGravity(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World, {0.0f, gravity});
|
||||
}
|
||||
|
||||
void Scene::UpdateLights()
|
||||
{
|
||||
// direction Light
|
||||
{
|
||||
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(0.0f, 0.0f,1.0f));
|
||||
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||
{
|
||||
direction,
|
||||
lightComponent.Radiance,
|
||||
lightComponent.Intensity,
|
||||
lightComponent.CastShadows
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Point Light
|
||||
{
|
||||
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 ++;
|
||||
}
|
||||
}
|
||||
|
||||
// Spot Light
|
||||
{
|
||||
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 ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Scene::DestroyEntity(Entity entity)
|
||||
{
|
||||
|
||||
@ -139,6 +139,9 @@ namespace Prism
|
||||
// Editor-specific
|
||||
void SetSelectedEntity(const entt::entity entity) { m_SelectedEntity = entity; }
|
||||
|
||||
private:
|
||||
void UpdateLights();
|
||||
|
||||
private:
|
||||
UUID m_SceneID;
|
||||
entt::entity m_SceneEntity;
|
||||
|
||||
@ -291,6 +291,9 @@ namespace Prism
|
||||
out << YAML::Key << "Intensity" << YAML::Value << skyLightComponent.Intensity;
|
||||
out << YAML::Key << "Angle" << YAML::Value << skyLightComponent.Angle;
|
||||
|
||||
out << YAML::Key << "DynamicSky" << YAML::Value << skyLightComponent.DynamicSky;
|
||||
out << YAML::Key << "TurbidityAzimuthInclination" << YAML::Value << skyLightComponent.TurbidityAzimuthInclination;
|
||||
|
||||
out << YAML::EndMap; // SkyLightComponent
|
||||
}
|
||||
|
||||
@ -855,7 +858,7 @@ namespace Prism
|
||||
AssetHandle assetHandle;
|
||||
if (skyLightComponent["EnvironmentAssetPath"])
|
||||
{
|
||||
const std::string filePath = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
||||
const auto filePath = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
||||
assetHandle = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
||||
}
|
||||
else
|
||||
@ -870,6 +873,10 @@ namespace Prism
|
||||
|
||||
component.Intensity = skyLightComponent["Intensity"].as<float>();
|
||||
component.Angle = skyLightComponent["Angle"].as<float>();
|
||||
|
||||
component.DynamicSky = skyLightComponent["DynamicSky"].as<bool>();
|
||||
component.TurbidityAzimuthInclination = skyLightComponent["TurbidityAzimuthInclination"].as<glm::vec3>();
|
||||
|
||||
}
|
||||
|
||||
if (auto cameraComponent = entity["CameraComponent"])
|
||||
|
||||
@ -781,25 +781,7 @@ namespace Prism { namespace Script {
|
||||
void Prism_Texture2D_SetData(Ref<Texture2D>* _this, MonoArray* inData, int32_t count)
|
||||
{
|
||||
Ref<Texture2D>& instance = *_this;
|
||||
|
||||
const uint32_t dataSize = count * sizeof(glm::vec4) / 4;
|
||||
|
||||
instance->Lock();
|
||||
const Buffer buffer = instance->GetWriteableBuffer();
|
||||
PM_CORE_ASSERT(dataSize <= buffer.Size);
|
||||
// Convert RGBA32F color to RGBA8
|
||||
auto pixels = static_cast<uint8_t*>(buffer.Data);
|
||||
|
||||
for (uint32_t i = 0; i < instance->GetWidth() * instance->GetHeight(); i++)
|
||||
{
|
||||
const glm::vec4& value = mono_array_get(inData, glm::vec4, i);
|
||||
*pixels++ = static_cast<uint32_t>(value.x * 255.0f);
|
||||
*pixels++ = static_cast<uint32_t>(value.y * 255.0f);
|
||||
*pixels++ = static_cast<uint32_t>(value.z * 255.0f);
|
||||
*pixels++ = static_cast<uint32_t>(value.w * 255.0f);
|
||||
}
|
||||
|
||||
instance->Unlock();
|
||||
instance->SetData(inData, count);
|
||||
}
|
||||
|
||||
void Prism_Material_Destructor(const Ref<Material>* _this)
|
||||
|
||||
Reference in New Issue
Block a user