engine: sync editor rendering and ui changes
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Math.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Math {
|
||||
|
||||
@@ -22,7 +22,7 @@ enum class KeyCode : Core::uint8 {
|
||||
Up = 126, Down = 125, Left = 123, Right = 124,
|
||||
|
||||
Home = 115, End = 119, PageUp = 116, PageDown = 121,
|
||||
Delete = 51, Backspace = 51,
|
||||
Delete = 117, Backspace = 51,
|
||||
|
||||
Zero = 39, One = 30, Two = 31, Three = 32,
|
||||
Four = 33, Five = 34, Six = 35, Seven = 37,
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
bool IsValid() const override;
|
||||
|
||||
void SetViewType(ResourceViewType type) { m_viewType = type; }
|
||||
void SetFormat(Format format) { m_format = format; }
|
||||
ResourceViewType GetViewType() const override { return m_viewType; }
|
||||
ResourceViewDimension GetDimension() const override { return m_dimension; }
|
||||
Format GetFormat() const override { return m_format; }
|
||||
|
||||
@@ -19,10 +19,14 @@ struct OpenGLDepthStencilState {
|
||||
uint8_t stencilReadMask = 0xFF;
|
||||
uint8_t stencilWriteMask = 0xFF;
|
||||
int stencilRef = 0;
|
||||
ComparisonFunc stencilFunc = ComparisonFunc::Always;
|
||||
StencilOp stencilFailOp = StencilOp::Keep;
|
||||
StencilOp stencilDepthFailOp = StencilOp::Keep;
|
||||
StencilOp stencilDepthPassOp = StencilOp::Keep;
|
||||
ComparisonFunc frontStencilFunc = ComparisonFunc::Always;
|
||||
StencilOp frontStencilFailOp = StencilOp::Keep;
|
||||
StencilOp frontStencilDepthFailOp = StencilOp::Keep;
|
||||
StencilOp frontStencilDepthPassOp = StencilOp::Keep;
|
||||
ComparisonFunc backStencilFunc = ComparisonFunc::Always;
|
||||
StencilOp backStencilFailOp = StencilOp::Keep;
|
||||
StencilOp backStencilDepthFailOp = StencilOp::Keep;
|
||||
StencilOp backStencilDepthPassOp = StencilOp::Keep;
|
||||
};
|
||||
|
||||
struct OpenGLBlendState {
|
||||
|
||||
@@ -87,6 +87,7 @@ private:
|
||||
bool m_renderPassActive = false;
|
||||
bool m_hasViewport = false;
|
||||
bool m_hasScissor = false;
|
||||
uint32_t m_stencilRef = 0;
|
||||
VkViewport m_viewport = {};
|
||||
VkRect2D m_scissor = {};
|
||||
std::vector<VkFramebuffer> m_transientFramebuffers;
|
||||
|
||||
@@ -18,6 +18,9 @@ enum class BuiltinMaterialPass : Core::uint32 {
|
||||
DepthOnly,
|
||||
ShadowCaster,
|
||||
ObjectId,
|
||||
Skybox,
|
||||
PostProcess,
|
||||
FinalColor,
|
||||
Forward = ForwardLit
|
||||
};
|
||||
|
||||
@@ -36,7 +39,12 @@ enum class BuiltinPassResourceSemantic : Core::uint8 {
|
||||
Material,
|
||||
Lighting,
|
||||
ShadowReceiver,
|
||||
Environment,
|
||||
PassConstants,
|
||||
BaseColorTexture,
|
||||
SourceColorTexture,
|
||||
SkyboxPanoramicTexture,
|
||||
SkyboxTexture,
|
||||
ShadowMapTexture,
|
||||
LinearClampSampler,
|
||||
ShadowMapSampler
|
||||
@@ -60,7 +68,12 @@ struct BuiltinPassResourceBindingPlan {
|
||||
PassResourceBindingLocation material = {};
|
||||
PassResourceBindingLocation lighting = {};
|
||||
PassResourceBindingLocation shadowReceiver = {};
|
||||
PassResourceBindingLocation environment = {};
|
||||
PassResourceBindingLocation passConstants = {};
|
||||
PassResourceBindingLocation baseColorTexture = {};
|
||||
PassResourceBindingLocation sourceColorTexture = {};
|
||||
PassResourceBindingLocation skyboxPanoramicTexture = {};
|
||||
PassResourceBindingLocation skyboxTexture = {};
|
||||
PassResourceBindingLocation linearClampSampler = {};
|
||||
PassResourceBindingLocation shadowMapTexture = {};
|
||||
PassResourceBindingLocation shadowMapSampler = {};
|
||||
@@ -85,8 +98,13 @@ struct BuiltinPassSetLayoutMetadata {
|
||||
bool usesMaterial = false;
|
||||
bool usesLighting = false;
|
||||
bool usesShadowReceiver = false;
|
||||
bool usesEnvironment = false;
|
||||
bool usesPassConstants = false;
|
||||
bool usesTexture = false;
|
||||
bool usesBaseColorTexture = false;
|
||||
bool usesSourceColorTexture = false;
|
||||
bool usesSkyboxPanoramicTexture = false;
|
||||
bool usesSkyboxTexture = false;
|
||||
bool usesShadowMapTexture = false;
|
||||
bool usesSampler = false;
|
||||
bool usesLinearClampSampler = false;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <XCEngine/RHI/RHICommandList.h>
|
||||
#include <XCEngine/RHI/RHITypes.h>
|
||||
#include <XCEngine/Resources/Material/Material.h>
|
||||
#include <XCEngine/Resources/Shader/Shader.h>
|
||||
@@ -97,6 +100,28 @@ inline RHI::BlendOp ToRHIBlendOp(Resources::MaterialBlendOp op) {
|
||||
}
|
||||
}
|
||||
|
||||
inline RHI::StencilOp ToRHIStencilOp(Resources::MaterialStencilOp op) {
|
||||
switch (op) {
|
||||
case Resources::MaterialStencilOp::Zero:
|
||||
return RHI::StencilOp::Zero;
|
||||
case Resources::MaterialStencilOp::Replace:
|
||||
return RHI::StencilOp::Replace;
|
||||
case Resources::MaterialStencilOp::IncrSat:
|
||||
return RHI::StencilOp::IncrSat;
|
||||
case Resources::MaterialStencilOp::DecrSat:
|
||||
return RHI::StencilOp::DecrSat;
|
||||
case Resources::MaterialStencilOp::Invert:
|
||||
return RHI::StencilOp::Invert;
|
||||
case Resources::MaterialStencilOp::IncrWrap:
|
||||
return RHI::StencilOp::Incr;
|
||||
case Resources::MaterialStencilOp::DecrWrap:
|
||||
return RHI::StencilOp::Decr;
|
||||
case Resources::MaterialStencilOp::Keep:
|
||||
default:
|
||||
return RHI::StencilOp::Keep;
|
||||
}
|
||||
}
|
||||
|
||||
inline Resources::MaterialRenderState ResolveEffectiveRenderState(
|
||||
const Resources::ShaderPass* shaderPass,
|
||||
const Resources::Material* material) {
|
||||
@@ -122,6 +147,8 @@ inline RHI::RasterizerDesc BuildRasterizerState(const Resources::MaterialRenderS
|
||||
desc.frontFace = static_cast<uint32_t>(RHI::FrontFace::CounterClockwise);
|
||||
desc.depthClipEnable = true;
|
||||
desc.cullMode = static_cast<uint32_t>(ToRHICullMode(renderState.cullMode));
|
||||
desc.depthBias = renderState.depthBiasUnits;
|
||||
desc.slopeScaledDepthBias = renderState.depthBiasFactor;
|
||||
|
||||
return desc;
|
||||
}
|
||||
@@ -145,7 +172,17 @@ inline RHI::DepthStencilStateDesc BuildDepthStencilState(const Resources::Materi
|
||||
desc.depthTestEnable = renderState.depthTestEnable;
|
||||
desc.depthWriteEnable = renderState.depthWriteEnable;
|
||||
desc.depthFunc = static_cast<uint32_t>(ToRHIComparisonFunc(renderState.depthFunc));
|
||||
desc.stencilEnable = false;
|
||||
desc.stencilEnable = renderState.stencil.enabled;
|
||||
desc.stencilReadMask = renderState.stencil.readMask;
|
||||
desc.stencilWriteMask = renderState.stencil.writeMask;
|
||||
desc.front.failOp = static_cast<uint32_t>(ToRHIStencilOp(renderState.stencil.front.failOp));
|
||||
desc.front.passOp = static_cast<uint32_t>(ToRHIStencilOp(renderState.stencil.front.passOp));
|
||||
desc.front.depthFailOp = static_cast<uint32_t>(ToRHIStencilOp(renderState.stencil.front.depthFailOp));
|
||||
desc.front.func = static_cast<uint32_t>(ToRHIComparisonFunc(renderState.stencil.front.func));
|
||||
desc.back.failOp = static_cast<uint32_t>(ToRHIStencilOp(renderState.stencil.back.failOp));
|
||||
desc.back.passOp = static_cast<uint32_t>(ToRHIStencilOp(renderState.stencil.back.passOp));
|
||||
desc.back.depthFailOp = static_cast<uint32_t>(ToRHIStencilOp(renderState.stencil.back.depthFailOp));
|
||||
desc.back.func = static_cast<uint32_t>(ToRHIComparisonFunc(renderState.stencil.back.func));
|
||||
|
||||
return desc;
|
||||
}
|
||||
@@ -167,12 +204,32 @@ inline void ApplyResolvedRenderState(
|
||||
ApplyRenderState(ResolveEffectiveRenderState(shaderPass, material), pipelineDesc);
|
||||
}
|
||||
|
||||
inline void ApplyDynamicRenderState(
|
||||
const Resources::MaterialRenderState& renderState,
|
||||
RHI::RHICommandList& commandList) {
|
||||
if (renderState.stencil.enabled) {
|
||||
commandList.SetStencilRef(renderState.stencil.reference);
|
||||
}
|
||||
}
|
||||
|
||||
inline Resources::MaterialRenderState BuildStaticPipelineRenderStateKey(
|
||||
const Resources::MaterialRenderState& renderState) {
|
||||
Resources::MaterialRenderState keyState = renderState;
|
||||
keyState.stencil.reference = 0;
|
||||
return keyState;
|
||||
}
|
||||
|
||||
struct MaterialRenderStateHash {
|
||||
size_t operator()(const Resources::MaterialRenderState& state) const noexcept {
|
||||
size_t hash = 2166136261u;
|
||||
auto combine = [&hash](size_t value) {
|
||||
hash ^= value + 0x9e3779b9u + (hash << 6) + (hash >> 2);
|
||||
};
|
||||
auto combineFloat = [&combine](float value) {
|
||||
Core::uint32 bits = 0;
|
||||
std::memcpy(&bits, &value, sizeof(bits));
|
||||
combine(static_cast<size_t>(bits));
|
||||
};
|
||||
|
||||
combine(static_cast<size_t>(state.blendEnable));
|
||||
combine(static_cast<size_t>(state.srcBlend));
|
||||
@@ -186,6 +243,20 @@ struct MaterialRenderStateHash {
|
||||
combine(static_cast<size_t>(state.depthWriteEnable));
|
||||
combine(static_cast<size_t>(state.depthFunc));
|
||||
combine(static_cast<size_t>(state.cullMode));
|
||||
combineFloat(state.depthBiasFactor);
|
||||
combine(static_cast<size_t>(state.depthBiasUnits));
|
||||
combine(static_cast<size_t>(state.stencil.enabled));
|
||||
combine(static_cast<size_t>(state.stencil.readMask));
|
||||
combine(static_cast<size_t>(state.stencil.writeMask));
|
||||
combine(static_cast<size_t>(state.stencil.reference));
|
||||
combine(static_cast<size_t>(state.stencil.front.failOp));
|
||||
combine(static_cast<size_t>(state.stencil.front.passOp));
|
||||
combine(static_cast<size_t>(state.stencil.front.depthFailOp));
|
||||
combine(static_cast<size_t>(state.stencil.front.func));
|
||||
combine(static_cast<size_t>(state.stencil.back.failOp));
|
||||
combine(static_cast<size_t>(state.stencil.back.passOp));
|
||||
combine(static_cast<size_t>(state.stencil.back.depthFailOp));
|
||||
combine(static_cast<size_t>(state.stencil.back.func));
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,16 +102,6 @@ public:
|
||||
bool HasRenderStateOverride() const { return m_hasRenderStateOverride; }
|
||||
void SetRenderStateOverrideEnabled(bool enabled);
|
||||
|
||||
// Legacy-only compatibility hint for older material assets that still
|
||||
// select a builtin pass by serialized name.
|
||||
void SetLegacyShaderPassHint(const Containers::String& shaderPass);
|
||||
const Containers::String& GetLegacyShaderPassHint() const { return m_legacyShaderPassHint; }
|
||||
bool HasLegacyShaderPassHint() const { return !m_legacyShaderPassHint.Empty(); }
|
||||
void ClearLegacyShaderPassHint();
|
||||
|
||||
void SetShaderPass(const Containers::String& shaderPass);
|
||||
const Containers::String& GetShaderPass() const { return GetLegacyShaderPassHint(); }
|
||||
|
||||
void SetTag(const Containers::String& name, const Containers::String& value);
|
||||
Containers::String GetTag(const Containers::String& name) const;
|
||||
bool HasTag(const Containers::String& name) const;
|
||||
@@ -186,7 +176,6 @@ private:
|
||||
Core::int32 m_renderQueue = static_cast<Core::int32>(MaterialRenderQueue::Geometry);
|
||||
MaterialRenderState m_renderState;
|
||||
bool m_hasRenderStateOverride = false;
|
||||
Containers::String m_legacyShaderPassHint;
|
||||
Containers::Array<MaterialTagEntry> m_tags;
|
||||
ShaderKeywordSet m_keywordSet;
|
||||
Containers::HashMap<Containers::String, MaterialProperty> m_properties;
|
||||
|
||||
@@ -50,6 +50,57 @@ enum class MaterialBlendFactor : Core::uint8 {
|
||||
InvSrc1Alpha = 16
|
||||
};
|
||||
|
||||
enum class MaterialStencilOp : Core::uint8 {
|
||||
Keep = 0,
|
||||
Zero = 1,
|
||||
Replace = 2,
|
||||
IncrSat = 3,
|
||||
DecrSat = 4,
|
||||
Invert = 5,
|
||||
IncrWrap = 6,
|
||||
DecrWrap = 7
|
||||
};
|
||||
|
||||
struct MaterialStencilFaceState {
|
||||
MaterialStencilOp failOp = MaterialStencilOp::Keep;
|
||||
MaterialStencilOp passOp = MaterialStencilOp::Keep;
|
||||
MaterialStencilOp depthFailOp = MaterialStencilOp::Keep;
|
||||
MaterialComparisonFunc func = MaterialComparisonFunc::Always;
|
||||
|
||||
bool operator==(const MaterialStencilFaceState& other) const {
|
||||
return failOp == other.failOp &&
|
||||
passOp == other.passOp &&
|
||||
depthFailOp == other.depthFailOp &&
|
||||
func == other.func;
|
||||
}
|
||||
|
||||
bool operator!=(const MaterialStencilFaceState& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct MaterialStencilState {
|
||||
bool enabled = false;
|
||||
Core::uint8 readMask = 0xFF;
|
||||
Core::uint8 writeMask = 0xFF;
|
||||
Core::uint8 reference = 0;
|
||||
MaterialStencilFaceState front = {};
|
||||
MaterialStencilFaceState back = {};
|
||||
|
||||
bool operator==(const MaterialStencilState& other) const {
|
||||
return enabled == other.enabled &&
|
||||
readMask == other.readMask &&
|
||||
writeMask == other.writeMask &&
|
||||
reference == other.reference &&
|
||||
front == other.front &&
|
||||
back == other.back;
|
||||
}
|
||||
|
||||
bool operator!=(const MaterialStencilState& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct MaterialRenderState {
|
||||
bool blendEnable = false;
|
||||
MaterialBlendFactor srcBlend = MaterialBlendFactor::One;
|
||||
@@ -65,6 +116,9 @@ struct MaterialRenderState {
|
||||
MaterialComparisonFunc depthFunc = MaterialComparisonFunc::Less;
|
||||
|
||||
MaterialCullMode cullMode = MaterialCullMode::None;
|
||||
float depthBiasFactor = 0.0f;
|
||||
Core::int32 depthBiasUnits = 0;
|
||||
MaterialStencilState stencil = {};
|
||||
|
||||
bool operator==(const MaterialRenderState& other) const {
|
||||
return blendEnable == other.blendEnable &&
|
||||
@@ -78,7 +132,10 @@ struct MaterialRenderState {
|
||||
depthTestEnable == other.depthTestEnable &&
|
||||
depthWriteEnable == other.depthWriteEnable &&
|
||||
depthFunc == other.depthFunc &&
|
||||
cullMode == other.cullMode;
|
||||
cullMode == other.cullMode &&
|
||||
depthBiasFactor == other.depthBiasFactor &&
|
||||
depthBiasUnits == other.depthBiasUnits &&
|
||||
stencil == other.stencil;
|
||||
}
|
||||
|
||||
bool operator!=(const MaterialRenderState& other) const {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Mutex.h"
|
||||
#include "SpinLock.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
@@ -102,7 +103,9 @@ void TaskSystem::ParallelFor(int32_t start, int32_t end, Func&& func) {
|
||||
}
|
||||
|
||||
for (auto& task : tasks) {
|
||||
Submit(std::make_unique<LambdaTask<std::function<void()>>>(std::move(task), TaskPriority::High));
|
||||
Submit(std::make_unique<::XCEngine::Threading::LambdaTask<std::function<void()>>>(
|
||||
std::move(task),
|
||||
TaskPriority::High));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,21 @@ struct UIColor {
|
||||
enum class UIDrawCommandType : std::uint8_t {
|
||||
FilledRect = 0,
|
||||
RectOutline,
|
||||
FilledRectLinearGradient,
|
||||
Line,
|
||||
FilledCircle,
|
||||
CircleOutline,
|
||||
Text,
|
||||
Image,
|
||||
PushClipRect,
|
||||
PopClipRect
|
||||
};
|
||||
|
||||
enum class UILinearGradientDirection : std::uint8_t {
|
||||
Horizontal = 0,
|
||||
Vertical
|
||||
};
|
||||
|
||||
struct UIDrawCommand {
|
||||
UIDrawCommandType type = UIDrawCommandType::FilledRect;
|
||||
UIRect rect = {};
|
||||
@@ -42,10 +51,13 @@ struct UIDrawCommand {
|
||||
UIPoint uvMin = {};
|
||||
UIPoint uvMax = UIPoint(1.0f, 1.0f);
|
||||
UIColor color = {};
|
||||
UIColor secondaryColor = {};
|
||||
float thickness = 1.0f;
|
||||
float rounding = 0.0f;
|
||||
float radius = 0.0f;
|
||||
float fontSize = 0.0f;
|
||||
bool intersectWithCurrentClip = true;
|
||||
UILinearGradientDirection gradientDirection = UILinearGradientDirection::Horizontal;
|
||||
UITextureHandle texture = {};
|
||||
std::string text;
|
||||
};
|
||||
@@ -107,6 +119,62 @@ public:
|
||||
return AddCommand(std::move(command));
|
||||
}
|
||||
|
||||
UIDrawCommand& AddFilledRectLinearGradient(
|
||||
const UIRect& rect,
|
||||
const UIColor& startColor,
|
||||
const UIColor& endColor,
|
||||
UILinearGradientDirection direction = UILinearGradientDirection::Horizontal,
|
||||
float rounding = 0.0f) {
|
||||
UIDrawCommand command = {};
|
||||
command.type = UIDrawCommandType::FilledRectLinearGradient;
|
||||
command.rect = rect;
|
||||
command.color = startColor;
|
||||
command.secondaryColor = endColor;
|
||||
command.rounding = rounding;
|
||||
command.gradientDirection = direction;
|
||||
return AddCommand(std::move(command));
|
||||
}
|
||||
|
||||
UIDrawCommand& AddLine(
|
||||
const UIPoint& start,
|
||||
const UIPoint& end,
|
||||
const UIColor& color,
|
||||
float thickness = 1.0f) {
|
||||
UIDrawCommand command = {};
|
||||
command.type = UIDrawCommandType::Line;
|
||||
command.position = start;
|
||||
command.uvMin = end;
|
||||
command.color = color;
|
||||
command.thickness = thickness;
|
||||
return AddCommand(std::move(command));
|
||||
}
|
||||
|
||||
UIDrawCommand& AddFilledCircle(
|
||||
const UIPoint& center,
|
||||
float radius,
|
||||
const UIColor& color) {
|
||||
UIDrawCommand command = {};
|
||||
command.type = UIDrawCommandType::FilledCircle;
|
||||
command.position = center;
|
||||
command.radius = radius;
|
||||
command.color = color;
|
||||
return AddCommand(std::move(command));
|
||||
}
|
||||
|
||||
UIDrawCommand& AddCircleOutline(
|
||||
const UIPoint& center,
|
||||
float radius,
|
||||
const UIColor& color,
|
||||
float thickness = 1.0f) {
|
||||
UIDrawCommand command = {};
|
||||
command.type = UIDrawCommandType::CircleOutline;
|
||||
command.position = center;
|
||||
command.radius = radius;
|
||||
command.color = color;
|
||||
command.thickness = thickness;
|
||||
return AddCommand(std::move(command));
|
||||
}
|
||||
|
||||
UIDrawCommand& AddText(
|
||||
const UIPoint& position,
|
||||
std::string text,
|
||||
|
||||
32
engine/include/XCEngine/UI/Widgets/UIScrollModel.h
Normal file
32
engine/include/XCEngine/UI/Widgets/UIScrollModel.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
namespace XCEngine {
|
||||
namespace UI {
|
||||
namespace Widgets {
|
||||
|
||||
struct UIScrollWheelResult {
|
||||
bool changed = false;
|
||||
float overflow = 0.0f;
|
||||
float offsetBefore = 0.0f;
|
||||
float offsetAfter = 0.0f;
|
||||
};
|
||||
|
||||
float ComputeUIScrollOverflow(float contentExtent, float viewportExtent);
|
||||
float ClampUIScrollOffset(float offset, float contentExtent, float viewportExtent);
|
||||
UIScrollWheelResult ApplyUIScrollWheel(
|
||||
float offset,
|
||||
float wheelDelta,
|
||||
float contentExtent,
|
||||
float viewportExtent,
|
||||
float wheelStep = 48.0f,
|
||||
float epsilon = 0.01f);
|
||||
float EnsureUIScrollOffsetVisible(
|
||||
float offset,
|
||||
float itemStart,
|
||||
float itemExtent,
|
||||
float contentExtent,
|
||||
float viewportExtent);
|
||||
|
||||
} // namespace Widgets
|
||||
} // namespace UI
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user