bluenoise-raytracer/raytracer/nvpro_core/nvvkhl/sky.hpp
2024-05-25 11:53:25 +02:00

168 lines
7 KiB
C++

/*
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: Copyright (c) 2014-2022 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <glm/glm.hpp>
#include <cstdint> // so uint32_t is available for device_host.h below
#include "shaders/dh_sky.h"
#include "imgui/imgui_helper.h"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/resourceallocator_vk.hpp"
#include "shaders/dh_lighting.h"
#include "vulkan/vulkan_core.h"
//////////////////////////////////////////////////////////////////////////
namespace nvvk {
class Context;
}
namespace nvvkhl {
struct SkyParameters
{
glm::vec3 skyColor{0.17F, 0.37F, 0.65F};
glm::vec3 horizonColor{0.50F, 0.70F, 0.92F};
glm::vec3 groundColor{0.62F, 0.59F, 0.55F};
glm::vec3 directionUp{0.F, 1.F, 0.F};
float brightness = 0.3F; // scaler for sky brightness
float horizonSize = 30.F; // +/- degrees
float glowSize = 5.F; // degrees, starting from the edge of the light disk
float glowIntensity = 0.1F; // [0-1] relative to light intensity
float glowSharpness = 4.F; // [1-10] is the glow power exponent
float maxLightRadiance = 100.F; // clamp for light radiance derived from its angular size, 0 = no clamp
// Sun
float angularSize = glm::radians(0.53F);
float intensity = 1.0F;
glm::vec3 direction = glm::normalize(glm::vec3{0.0F, -.7F, -.7F});
glm::vec3 color = {1.0F, 1.0F, 1.0F};
};
inline nvvkhl_shaders::ProceduralSkyShaderParameters fillSkyShaderParameters(const SkyParameters& input)
{
nvvkhl_shaders::ProceduralSkyShaderParameters output{};
auto square = [](auto a) { return a * a; };
float light_angular_size = glm::clamp(input.angularSize, glm::radians(0.1F), glm::radians(90.F));
float light_solid_angle = 4.0F * glm::pi<float>() * square(sinf(light_angular_size * 0.5F));
float light_radiance = input.intensity / light_solid_angle;
if(input.maxLightRadiance > 0.F)
{
light_radiance = std::min(light_radiance, input.maxLightRadiance);
}
output.directionToLight = glm::normalize(-input.direction);
output.angularSizeOfLight = light_angular_size;
output.lightColor = light_radiance * input.color;
output.glowSize = glm::radians(glm::clamp(input.glowSize, 0.F, 90.F));
output.skyColor = input.skyColor * input.brightness;
output.glowIntensity = glm::clamp(input.glowIntensity, 0.F, 1.F);
output.horizonColor = input.horizonColor * input.brightness;
output.horizonSize = glm::radians(glm::clamp(input.horizonSize, 0.F, 90.F));
output.groundColor = input.groundColor * input.brightness;
output.glowSharpness = glm::clamp(input.glowSharpness, 1.F, 10.F);
output.directionUp = normalize(input.directionUp);
return output;
}
inline bool skyParametersUI(SkyParameters& skyParams)
{
using PE = ImGuiH::PropertyEditor;
bool changed{false};
glm::vec3 dir = skyParams.direction;
changed |= ImGuiH::azimuthElevationSliders(dir, true, skyParams.directionUp.y == 1.0F);
skyParams.direction = dir;
// clang-format off
changed |= PE::entry("Color", [&]() { return ImGui::ColorEdit3("##1", &skyParams.color.x, ImGuiColorEditFlags_Float); });
changed |= PE::entry("Irradiance", [&]() { return ImGui::SliderFloat("##1", &skyParams.intensity, 0.F, 100.F, "%.2f", ImGuiSliderFlags_Logarithmic); });
changed |= PE::entry("Angular Size", [&]() { return ImGui::SliderAngle("##1", &skyParams.angularSize, 0.1F, 20.F); });
// clang-format on
if(PE::treeNode("Extra"))
{
// clang-format off
changed |= PE::entry("Brightness", [&]() { return ImGui::SliderFloat("Brightness", &skyParams.brightness, 0.F, 1.F); });
changed |= PE::entry("Glow Size", [&]() { return ImGui::SliderFloat("Glow Size", &skyParams.glowSize, 0.F, 90.F); });
changed |= PE::entry("Glow Sharpness", [&]() { return ImGui::SliderFloat("Glow Sharpness", &skyParams.glowSharpness, 1.F, 10.F); });
changed |= PE::entry("Glow Intensity", [&]() { return ImGui::SliderFloat("Glow Intensity", &skyParams.glowIntensity, 0.F, 1.F); });
changed |= PE::entry("Horizon Size", [&]() { return ImGui::SliderFloat("Horizon Size", &skyParams.horizonSize, 0.F, 90.F); });
changed |= PE::entry("Sky Color", [&]() { return ImGui::ColorEdit3("Sky Color", &skyParams.skyColor.x, ImGuiColorEditFlags_Float); });
changed |= PE::entry("Horizon Color", [&]() { return ImGui::ColorEdit3("Horizon Color", &skyParams.horizonColor.x, ImGuiColorEditFlags_Float); });
changed |= PE::entry("Ground Color", [&]() { return ImGui::ColorEdit3("Ground Color", &skyParams.groundColor.x, ImGuiColorEditFlags_Float); });
// clang-format on
PE::treePop();
}
return changed;
}
/** @DOC_START
# class nvvkhl::SkyDome
> This class is responsible for the sky dome.
This class can render a sky dome with a sun, for both the rasterizer and the ray tracer.
The `draw` method is responsible for rendering the sky dome for the rasterizer. For ray tracing, there is no need to call this method, as the sky dome is part of the ray tracing shaders (see shaders/dh_sky.h).
@DOC_END */
class SkyDome
{
public:
SkyDome(nvvk::Context* ctx, nvvk::ResourceAllocator* allocator);
void setup(const VkDevice& device, nvvk::ResourceAllocator* allocator);
void setOutImage(const VkDescriptorImageInfo& outimage);
void draw(const VkCommandBuffer& cmd, const glm::mat4& view, const glm::mat4& proj, const VkExtent2D& size);
void destroy();
void updateParameterBuffer(VkCommandBuffer cmd) const;
bool onUI();
nvvkhl_shaders::Light getSun() const;
VkDescriptorSetLayout getDescriptorSetLayout() const { return m_skyDLayout; };
VkDescriptorSet getDescriptorSet() const { return m_skyDSet; };
SkyParameters& skyParams() { return m_skyParams; }
private:
// Resources
VkDevice m_device{VK_NULL_HANDLE};
nvvk::ResourceAllocator* m_alloc{nullptr};
nvvk::DebugUtil m_debug;
// To draw the Sky in image
VkDescriptorSet m_skyDSet{VK_NULL_HANDLE};
VkDescriptorSetLayout m_skyDLayout{VK_NULL_HANDLE};
VkDescriptorPool m_skyDPool{VK_NULL_HANDLE};
VkPipeline m_skyPipeline{VK_NULL_HANDLE};
VkPipelineLayout m_skyPipelineLayout{VK_NULL_HANDLE};
nvvk::Buffer m_skyInfoBuf; // Device-Host of Sky Params
SkyParameters m_skyParams{};
};
} // namespace nvvkhl