BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
Binary file not shown.
@@ -21,7 +21,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPU_CB_STRUCT(Data {
|
GPU_CB_STRUCT(Data {
|
||||||
Matrix WVP;
|
Matrix WorldViewProjection;
|
||||||
|
Matrix InvViewProjection;
|
||||||
Float3 ViewOffset;
|
Float3 ViewOffset;
|
||||||
float Padding;
|
float Padding;
|
||||||
ShaderGBufferData GBuffer;
|
ShaderGBufferData GBuffer;
|
||||||
@@ -30,9 +31,6 @@ GPU_CB_STRUCT(Data {
|
|||||||
|
|
||||||
Sky::Sky(const SpawnParams& params)
|
Sky::Sky(const SpawnParams& params)
|
||||||
: Actor(params)
|
: Actor(params)
|
||||||
, _shader(nullptr)
|
|
||||||
, _psSky(nullptr)
|
|
||||||
, _psFog(nullptr)
|
|
||||||
{
|
{
|
||||||
_drawNoCulling = 1;
|
_drawNoCulling = 1;
|
||||||
_drawCategory = SceneRendering::PreRender;
|
_drawCategory = SceneRendering::PreRender;
|
||||||
@@ -52,7 +50,6 @@ Sky::Sky(const SpawnParams& params)
|
|||||||
Sky::~Sky()
|
Sky::~Sky()
|
||||||
{
|
{
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psSky);
|
SAFE_DELETE_GPU_RESOURCE(_psSky);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psFog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sky::InitConfig(ShaderAtmosphericFogData& config) const
|
void Sky::InitConfig(ShaderAtmosphericFogData& config) const
|
||||||
@@ -91,7 +88,7 @@ void Sky::Draw(RenderContext& renderContext)
|
|||||||
if (HasContentLoaded() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
if (HasContentLoaded() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
||||||
{
|
{
|
||||||
// Ensure to have pipeline state cache created
|
// Ensure to have pipeline state cache created
|
||||||
if (_psSky == nullptr || _psFog == nullptr)
|
if (_psSky == nullptr)
|
||||||
{
|
{
|
||||||
const auto shader = _shader->GetShader();
|
const auto shader = _shader->GetShader();
|
||||||
|
|
||||||
@@ -113,21 +110,6 @@ void Sky::Draw(RenderContext& renderContext)
|
|||||||
LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString());
|
LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_psFog == nullptr)
|
|
||||||
{
|
|
||||||
_psFog = GPUDevice::Instance->CreatePipelineState();
|
|
||||||
|
|
||||||
GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
|
||||||
psDesc.PS = shader->GetPS("PS_Fog");
|
|
||||||
psDesc.DepthWriteEnable = false;
|
|
||||||
psDesc.DepthClipEnable = false;
|
|
||||||
psDesc.BlendMode = BlendingMode::Additive;
|
|
||||||
|
|
||||||
if (_psFog->Init(psDesc))
|
|
||||||
{
|
|
||||||
LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register for the sky and fog pass
|
// Register for the sky and fog pass
|
||||||
@@ -139,7 +121,6 @@ void Sky::Draw(RenderContext& renderContext)
|
|||||||
|
|
||||||
void Sky::Serialize(SerializeStream& stream, const void* otherObj)
|
void Sky::Serialize(SerializeStream& stream, const void* otherObj)
|
||||||
{
|
{
|
||||||
// Base
|
|
||||||
Actor::Serialize(stream, otherObj);
|
Actor::Serialize(stream, otherObj);
|
||||||
|
|
||||||
SERIALIZE_GET_OTHER_OBJ(Sky);
|
SERIALIZE_GET_OTHER_OBJ(Sky);
|
||||||
@@ -152,7 +133,6 @@ void Sky::Serialize(SerializeStream& stream, const void* otherObj)
|
|||||||
|
|
||||||
void Sky::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
void Sky::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||||
{
|
{
|
||||||
// Base
|
|
||||||
Actor::Deserialize(stream, modifier);
|
Actor::Deserialize(stream, modifier);
|
||||||
|
|
||||||
DESERIALIZE_MEMBER(Sun, SunLight);
|
DESERIALIZE_MEMBER(Sun, SunLight);
|
||||||
@@ -173,39 +153,7 @@ bool Sky::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal)
|
|||||||
|
|
||||||
void Sky::DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureView* output)
|
void Sky::DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureView* output)
|
||||||
{
|
{
|
||||||
// Get precomputed cache and bind it to the pipeline
|
MISSING_CODE("sky fog");
|
||||||
AtmosphereCache cache;
|
|
||||||
if (!AtmospherePreCompute::GetCache(&cache))
|
|
||||||
return;
|
|
||||||
context->BindSR(4, cache.Transmittance);
|
|
||||||
context->BindSR(5, cache.Irradiance);
|
|
||||||
context->BindSR(6, cache.Inscatter->ViewVolume());
|
|
||||||
|
|
||||||
// Bind GBuffer inputs
|
|
||||||
context->BindSR(0, renderContext.Buffers->GBuffer0);
|
|
||||||
context->BindSR(1, renderContext.Buffers->GBuffer1);
|
|
||||||
context->BindSR(2, renderContext.Buffers->GBuffer2);
|
|
||||||
context->BindSR(3, renderContext.Buffers->DepthBuffer);
|
|
||||||
|
|
||||||
// Setup constants data
|
|
||||||
Data data;
|
|
||||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
|
||||||
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
|
||||||
InitConfig(data.Fog);
|
|
||||||
data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
|
||||||
bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight);
|
|
||||||
if (!useSpecularLight)
|
|
||||||
{
|
|
||||||
data.Fog.AtmosphericFogSunDiscScale = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind pipeline
|
|
||||||
auto cb = _shader->GetShader()->GetCB(0);
|
|
||||||
context->UpdateCB(cb, &data);
|
|
||||||
context->BindCB(0, cb);
|
|
||||||
context->SetState(_psFog);
|
|
||||||
context->SetRenderTarget(output);
|
|
||||||
context->DrawFullscreenTriangle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sky::IsDynamicSky() const
|
bool Sky::IsDynamicSky() const
|
||||||
@@ -231,14 +179,14 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr
|
|||||||
// Setup constants data
|
// Setup constants data
|
||||||
Matrix m;
|
Matrix m;
|
||||||
Data data;
|
Data data;
|
||||||
Matrix::Multiply(world, renderContext.View.Frustum.GetMatrix(), m);
|
Matrix::Multiply(world, renderContext.View.ViewProjection(), m);
|
||||||
Matrix::Transpose(m, data.WVP);
|
Matrix::Transpose(m, data.WorldViewProjection);
|
||||||
|
Matrix::Transpose(renderContext.View.IVP, data.InvViewProjection);
|
||||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||||
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
||||||
InitConfig(data.Fog);
|
InitConfig(data.Fog);
|
||||||
//data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
//data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
||||||
bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight);
|
if (EnumHasNoneFlags(renderContext.View.Flags, ViewFlags::SpecularLight))
|
||||||
if (!useSpecularLight)
|
|
||||||
{
|
{
|
||||||
// Hide sun disc if specular light is disabled
|
// Hide sun disc if specular light is disabled
|
||||||
data.Fog.AtmosphericFogSunDiscScale = 0;
|
data.Fog.AtmosphericFogSunDiscScale = 0;
|
||||||
@@ -253,11 +201,8 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr
|
|||||||
|
|
||||||
void Sky::EndPlay()
|
void Sky::EndPlay()
|
||||||
{
|
{
|
||||||
// Cleanup
|
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psSky);
|
SAFE_DELETE_GPU_RESOURCE(_psSky);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psFog);
|
|
||||||
|
|
||||||
// Base
|
|
||||||
Actor::EndPlay();
|
Actor::EndPlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +213,6 @@ void Sky::OnEnable()
|
|||||||
GetSceneRendering()->AddViewportIcon(this);
|
GetSceneRendering()->AddViewportIcon(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Base
|
|
||||||
Actor::OnEnable();
|
Actor::OnEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,13 +223,11 @@ void Sky::OnDisable()
|
|||||||
#endif
|
#endif
|
||||||
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
|
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
|
||||||
|
|
||||||
// Base
|
|
||||||
Actor::OnDisable();
|
Actor::OnDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sky::OnTransformChanged()
|
void Sky::OnTransformChanged()
|
||||||
{
|
{
|
||||||
// Base
|
|
||||||
Actor::OnTransformChanged();
|
Actor::OnTransformChanged();
|
||||||
|
|
||||||
_box = BoundingBox(_transform.Translation);
|
_box = BoundingBox(_transform.Translation);
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public
|
|||||||
DECLARE_SCENE_OBJECT(Sky);
|
DECLARE_SCENE_OBJECT(Sky);
|
||||||
private:
|
private:
|
||||||
AssetReference<Shader> _shader;
|
AssetReference<Shader> _shader;
|
||||||
GPUPipelineState* _psSky;
|
GPUPipelineState* _psSky = nullptr;
|
||||||
GPUPipelineState* _psFog;
|
|
||||||
int32 _sceneRenderingKey = -1;
|
int32 _sceneRenderingKey = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -57,7 +56,6 @@ private:
|
|||||||
void OnShaderReloading(Asset* obj)
|
void OnShaderReloading(Asset* obj)
|
||||||
{
|
{
|
||||||
_psSky = nullptr;
|
_psSky = nullptr;
|
||||||
_psFog = nullptr;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void InitConfig(ShaderAtmosphericFogData& config) const;
|
void InitConfig(ShaderAtmosphericFogData& config) const;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Content/Assets/Model.h"
|
#include "Engine/Content/Assets/Model.h"
|
||||||
#include "Engine/Level/Actors/Decal.h"
|
#include "Engine/Level/Actors/Decal.h"
|
||||||
|
#include "Engine/Level/Actors/Sky.h"
|
||||||
#include "Engine/Engine/Engine.h"
|
#include "Engine/Engine/Engine.h"
|
||||||
|
|
||||||
GPU_CB_STRUCT(GBufferPassData {
|
GPU_CB_STRUCT(GBufferPassData {
|
||||||
@@ -416,8 +417,17 @@ void GBufferPass::DrawSky(RenderContext& renderContext, GPUContext* context)
|
|||||||
|
|
||||||
// Calculate sphere model transform to cover far plane
|
// Calculate sphere model transform to cover far plane
|
||||||
Matrix m1, m2;
|
Matrix m1, m2;
|
||||||
Matrix::Scaling(renderContext.View.Far / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum
|
float size = renderContext.View.Far;
|
||||||
Matrix::CreateWorld(renderContext.View.Position, Float3::Up, Float3::Backward, m2); // Rotate sphere model
|
Float3 origin = renderContext.View.Position;
|
||||||
|
if (dynamic_cast<Sky*>(renderContext.List->Sky)) // TODO: refactor sky rendering (eg. let sky draw with custom projection)
|
||||||
|
{
|
||||||
|
BoundingSphere frustumBounds;
|
||||||
|
renderContext.View.CullingFrustum.GetSphere(frustumBounds);
|
||||||
|
origin = frustumBounds.Center;
|
||||||
|
size = frustumBounds.Radius;
|
||||||
|
}
|
||||||
|
Matrix::Scaling(size / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum
|
||||||
|
Matrix::CreateWorld(origin, Float3::Up, Float3::Backward, m2); // Rotate sphere model
|
||||||
m1 *= m2;
|
m1 *= m2;
|
||||||
|
|
||||||
// Draw sky
|
// Draw sky
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#include "./Flax/AtmosphereFog.hlsl"
|
#include "./Flax/AtmosphereFog.hlsl"
|
||||||
|
|
||||||
META_CB_BEGIN(0, Data)
|
META_CB_BEGIN(0, Data)
|
||||||
float4x4 WVP;
|
float4x4 WorldViewProjection;
|
||||||
|
float4x4 InvViewProjection;
|
||||||
float3 ViewOffset;
|
float3 ViewOffset;
|
||||||
float Padding;
|
float Padding;
|
||||||
GBufferData GBuffer;
|
GBufferData GBuffer;
|
||||||
@@ -18,7 +19,7 @@ DECLARE_GBUFFERDATA_ACCESS(GBuffer)
|
|||||||
|
|
||||||
struct MaterialInput
|
struct MaterialInput
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
float4 ScreenPos : TEXCOORD0;
|
float4 ScreenPos : TEXCOORD0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,12 +31,9 @@ MaterialInput VS(ModelInput_PosOnly input)
|
|||||||
MaterialInput output;
|
MaterialInput output;
|
||||||
|
|
||||||
// Compute vertex position
|
// Compute vertex position
|
||||||
output.Position = mul(float4(input.Position.xyz, 1), WVP);
|
output.Position = mul(float4(input.Position.xyz, 1), WorldViewProjection);
|
||||||
output.ScreenPos = output.Position;
|
output.ScreenPos = output.Position;
|
||||||
|
|
||||||
// Place pixels on the far plane
|
|
||||||
output.Position = output.Position.xyzz;
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,15 +43,15 @@ GBufferOutput PS_Sky(MaterialInput input)
|
|||||||
{
|
{
|
||||||
GBufferOutput output;
|
GBufferOutput output;
|
||||||
|
|
||||||
// Obtain UVs corresponding to the current pixel
|
// Calculate view vector (unproject at the far plane)
|
||||||
float2 uv = (input.ScreenPos.xy / input.ScreenPos.w) * float2(0.5, -0.5) + float2(0.5, 0.5);
|
GBufferData gBufferData = GetGBufferData();
|
||||||
|
float4 clipPos = float4(input.ScreenPos.xy / input.ScreenPos.w, 1.0, 1.0);
|
||||||
|
clipPos = mul(clipPos, InvViewProjection);
|
||||||
|
float3 worldPos = clipPos.xyz / clipPos.w;
|
||||||
|
float3 viewVector = normalize(worldPos - gBufferData.ViewPos);
|
||||||
|
|
||||||
// Sample atmosphere color
|
// Sample atmosphere color
|
||||||
GBufferData gBufferData = GetGBufferData();
|
float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, gBufferData.ViewPos + ViewOffset, viewVector, gBufferData.ViewFar, float3(0, 0, 0));
|
||||||
float3 vsPos = GetViewPos(gBufferData, uv, LinearZ2DeviceDepth(gBufferData, 1));
|
|
||||||
float3 wsPos = mul(float4(vsPos, 1), gBufferData.InvViewMatrix).xyz;
|
|
||||||
float3 viewVector = wsPos - gBufferData.ViewPos;
|
|
||||||
float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, wsPos + ViewOffset, gBufferData.ViewPos + ViewOffset);
|
|
||||||
|
|
||||||
// Pack GBuffer
|
// Pack GBuffer
|
||||||
output.Light = color;
|
output.Light = color;
|
||||||
@@ -64,36 +62,3 @@ GBufferOutput PS_Sky(MaterialInput input)
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
|
||||||
float4 PS_Fog(Quad_VS2PS input) : SV_Target0
|
|
||||||
{
|
|
||||||
float4 result;
|
|
||||||
/*
|
|
||||||
// Sample GBuffer
|
|
||||||
GBufferSample gBuffer = SampleGBuffer(GBuffer, input.TexCoord);
|
|
||||||
|
|
||||||
// TODO: set valid scene color for better inscatter reflectance
|
|
||||||
//float3 sceneColor = gBuffer.Color * AtmosphericFogDensityOffset;
|
|
||||||
float3 sceneColor = float3(0, 0, 0);
|
|
||||||
|
|
||||||
// Sample atmosphere color
|
|
||||||
float3 viewVector = gBuffer.WorldPos - GBuffer.ViewPos;
|
|
||||||
float SceneDepth = length(ViewVector);
|
|
||||||
result = GetAtmosphericFog(AtmosphericFog, GBuffer.ViewFar, GBuffer.ViewPos, viewVector, SceneDepth, sceneColor);
|
|
||||||
|
|
||||||
//result.rgb = normalize(ViewVector);
|
|
||||||
//result.rgb = ViewVector;
|
|
||||||
//result.rgb = SceneDepth.xxx / GBuffer.ViewFar * 0.5f;
|
|
||||||
|
|
||||||
//result = float4(input.TexCoord, 0, 1);
|
|
||||||
//result = AtmosphereTransmittanceTexture.Sample(SamplerLinearClamp, input.TexCoord);
|
|
||||||
//result = float4(AtmosphereIrradianceTexture.Sample(SamplerLinearClamp, input.TexCoord).rgb*5.0, 1.0);
|
|
||||||
//result = AtmosphereInscatterTexture.Sample(SamplerLinearClamp, float3(input.TexCoord.xy, (AtmosphericFogSunDirection.x+1.0)/2.0));
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: finish fog
|
|
||||||
result = float4(1, 0, 0, 1);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user