Merge branch 'main' into Prism/gem-db
commit
ffdce2ef7f
@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.02554 10L9 15.0362V18L0 9L9 0V2.98885L4 8H18V10H4.02554Z" fill="#1e70eb"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 230 B |
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 17L15 14H9L12 17Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 190 B |
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f82f22df64b93d4bec91e56b60efa3d5ce2915ce388a2dc627f1ab720678e3d5
|
||||
size 334987
|
||||
oid sha256:4a5881b8d6cfbc4ceefb14ab96844484fe19407ee030824768f9fcce2f729d35
|
||||
size 2949
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8358f4dad9878c662b9819b2b346622af691eb45f8eddc28fff79a50650ae6cf
|
||||
size 2503
|
||||
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.5714 6.7619H16.7619C16.7619 4.13333 14.6286 2 12 2C9.37145 2 7.23811 4.13333 7.23811 6.7619H3.42859V22H20.5714V6.7619ZM12 3.90476C13.581 3.90476 14.8572 5.18095 14.8572 6.7619H9.14287C9.14287 5.18095 10.4191 3.90476 12 3.90476ZM13.7997 11.7424L12.0288 9.24095H11.9712L10.2003 11.7424H13.7997ZM5.00002 12.4335L10.9158 19.4063L9.03253 12.4335H5.00002ZM10.14 12.4335L11.9356 19.5147C11.9548 19.5189 11.974 19.521 11.9959 19.521C12.0178 19.521 12.0398 19.5189 12.0617 19.5147L13.86 12.4335H10.14ZM14.9675 12.4335H18.8547H19L13.0842 19.398L14.9675 12.4335ZM8.26457 9.24095H11.075L9.52787 11.4253L8.26457 9.24095ZM8.83789 11.7424L7.5193 9.46191L5.01921 11.7424H5.14804H8.83789ZM18.9808 11.7424H18.8547H15.1512L16.4286 9.41397L18.9808 11.7424ZM15.6558 9.24095H12.9252L14.4647 11.4146L15.6558 9.24095Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 966 B |
@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5507 19.5506L19.5213 2.58008L21.289 4.34785L4.31846 21.3184L2.5507 19.5506Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.28706 2.65015L21.2576 19.6207L19.4899 21.3885L2.51929 4.41791L4.28706 2.65015Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 394 B |
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ProjectBuilder.h>
|
||||
#include <ProjectButtonWidget.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
|
||||
#include <QProcess>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <QDir>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
|
||||
//#define MOCK_BUILD_PROJECT true
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
// 10 Minutes
|
||||
constexpr int MaxBuildTimeMSecs = 600000;
|
||||
static const QString BuildPathPostfix = "windows_vs2019";
|
||||
static const QString ErrorLogPathPostfix = "CMakeFiles/CMakeProjectBuildError.log";
|
||||
|
||||
ProjectBuilderWorker::ProjectBuilderWorker(const ProjectInfo& projectInfo)
|
||||
: QObject()
|
||||
, m_projectInfo(projectInfo)
|
||||
{
|
||||
}
|
||||
|
||||
void ProjectBuilderWorker::BuildProject()
|
||||
{
|
||||
#ifdef MOCK_BUILD_PROJECT
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
QThread::sleep(1);
|
||||
UpdateProgress(i * 10);
|
||||
}
|
||||
Done(m_projectPath);
|
||||
#else
|
||||
EngineInfo engineInfo;
|
||||
|
||||
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||
if (engineInfoResult.IsSuccess())
|
||||
{
|
||||
engineInfo = engineInfoResult.GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit Done(tr("Failed to get engine info."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Show some kind of progress with very approximate estimates
|
||||
UpdateProgress(1);
|
||||
|
||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
||||
// Append cmake path to PATH incase it is missing
|
||||
QDir cmakePath(engineInfo.m_path);
|
||||
cmakePath.cd("cmake/runtime/bin");
|
||||
QString pathValue = currentEnvironment.value("PATH");
|
||||
pathValue += ";" + cmakePath.path();
|
||||
currentEnvironment.insert("PATH", pathValue);
|
||||
|
||||
QProcess configProjectProcess;
|
||||
configProjectProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
configProjectProcess.setWorkingDirectory(m_projectInfo.m_path);
|
||||
configProjectProcess.setProcessEnvironment(currentEnvironment);
|
||||
|
||||
configProjectProcess.start(
|
||||
"cmake",
|
||||
QStringList
|
||||
{
|
||||
"-B",
|
||||
QDir(m_projectInfo.m_path).filePath(BuildPathPostfix),
|
||||
"-S",
|
||||
m_projectInfo.m_path,
|
||||
"-G",
|
||||
"Visual Studio 16",
|
||||
"-DLY_3RDPARTY_PATH=" + engineInfo.m_thirdPartyPath
|
||||
});
|
||||
|
||||
if (!configProjectProcess.waitForStarted())
|
||||
{
|
||||
emit Done(tr("Configuring project failed to start."));
|
||||
return;
|
||||
}
|
||||
if (!configProjectProcess.waitForFinished(MaxBuildTimeMSecs))
|
||||
{
|
||||
WriteErrorLog(configProjectProcess.readAllStandardOutput());
|
||||
emit Done(tr("Configuring project timed out. See log for details"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString configProjectOutput(configProjectProcess.readAllStandardOutput());
|
||||
if (configProjectProcess.exitCode() != 0 || !configProjectOutput.contains("Generating done"))
|
||||
{
|
||||
WriteErrorLog(configProjectOutput);
|
||||
emit Done(tr("Configuring project failed. See log for details."));
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateProgress(20);
|
||||
|
||||
QProcess buildProjectProcess;
|
||||
buildProjectProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
buildProjectProcess.setWorkingDirectory(m_projectInfo.m_path);
|
||||
buildProjectProcess.setProcessEnvironment(currentEnvironment);
|
||||
|
||||
buildProjectProcess.start(
|
||||
"cmake",
|
||||
QStringList
|
||||
{
|
||||
"--build",
|
||||
QDir(m_projectInfo.m_path).filePath(BuildPathPostfix),
|
||||
"--target",
|
||||
m_projectInfo.m_projectName + ".GameLauncher",
|
||||
"Editor",
|
||||
"--config",
|
||||
"profile"
|
||||
});
|
||||
|
||||
if (!buildProjectProcess.waitForStarted())
|
||||
{
|
||||
emit Done(tr("Building project failed to start."));
|
||||
return;
|
||||
}
|
||||
if (!buildProjectProcess.waitForFinished(MaxBuildTimeMSecs))
|
||||
{
|
||||
WriteErrorLog(configProjectProcess.readAllStandardOutput());
|
||||
emit Done(tr("Building project timed out. See log for details"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString buildProjectOutput(buildProjectProcess.readAllStandardOutput());
|
||||
if (configProjectProcess.exitCode() != 0)
|
||||
{
|
||||
WriteErrorLog(buildProjectOutput);
|
||||
emit Done(tr("Building project failed. See log for details."));
|
||||
}
|
||||
else
|
||||
{
|
||||
emit Done("");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString ProjectBuilderWorker::LogFilePath() const
|
||||
{
|
||||
QDir logFilePath(m_projectInfo.m_path);
|
||||
logFilePath.cd(BuildPathPostfix);
|
||||
return logFilePath.filePath(ErrorLogPathPostfix);
|
||||
}
|
||||
|
||||
void ProjectBuilderWorker::WriteErrorLog(const QString& log)
|
||||
{
|
||||
QFile logFile(LogFilePath());
|
||||
// Overwrite file with truncate
|
||||
if (logFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||
{
|
||||
QTextStream output(&logFile);
|
||||
output << log;
|
||||
logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
ProjectBuilderController::ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent)
|
||||
: QObject()
|
||||
, m_projectInfo(projectInfo)
|
||||
, m_projectButton(projectButton)
|
||||
, m_parent(parent)
|
||||
{
|
||||
m_worker = new ProjectBuilderWorker(m_projectInfo);
|
||||
m_worker->moveToThread(&m_workerThread);
|
||||
|
||||
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
|
||||
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
|
||||
connect(m_worker, &ProjectBuilderWorker::Done, this, &ProjectBuilderController::HandleResults);
|
||||
connect(m_worker, &ProjectBuilderWorker::UpdateProgress, this, &ProjectBuilderController::UpdateUIProgress);
|
||||
}
|
||||
|
||||
ProjectBuilderController::~ProjectBuilderController()
|
||||
{
|
||||
m_workerThread.quit();
|
||||
m_workerThread.wait();
|
||||
}
|
||||
|
||||
void ProjectBuilderController::Start()
|
||||
{
|
||||
m_workerThread.start();
|
||||
UpdateUIProgress(0);
|
||||
}
|
||||
|
||||
void ProjectBuilderController::SetProjectButton(ProjectButton* projectButton)
|
||||
{
|
||||
m_projectButton = projectButton;
|
||||
}
|
||||
|
||||
QString ProjectBuilderController::GetProjectPath() const
|
||||
{
|
||||
return m_projectInfo.m_path;
|
||||
}
|
||||
|
||||
void ProjectBuilderController::UpdateUIProgress(int progress)
|
||||
{
|
||||
if (m_projectButton)
|
||||
{
|
||||
m_projectButton->SetButtonOverlayText(QString("%1 (%2%)\n\n").arg(tr("Building Project..."), QString::number(progress)));
|
||||
m_projectButton->SetProgressBarValue(progress);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectBuilderController::HandleResults(const QString& result)
|
||||
{
|
||||
if (!result.isEmpty())
|
||||
{
|
||||
if (result.contains(tr("log")))
|
||||
{
|
||||
QMessageBox::StandardButton openLog = QMessageBox::critical(
|
||||
m_parent,
|
||||
tr("Project Failed to Build!"),
|
||||
result + tr("\n\nWould you like to view log?"),
|
||||
QMessageBox::No | QMessageBox::Yes);
|
||||
|
||||
if (openLog == QMessageBox::Yes)
|
||||
{
|
||||
// Open application assigned to this file type
|
||||
QDesktopServices::openUrl(QUrl("file:///" + m_worker->LogFilePath()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(m_parent, tr("Project Failed to Build!"), result);
|
||||
}
|
||||
}
|
||||
|
||||
emit Done();
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ProjectInfo.h>
|
||||
|
||||
#include <QThread>
|
||||
#endif
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
QT_FORWARD_DECLARE_CLASS(ProjectButton)
|
||||
|
||||
class ProjectBuilderWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProjectBuilderWorker(const ProjectInfo& projectInfo);
|
||||
~ProjectBuilderWorker() = default;
|
||||
|
||||
QString LogFilePath() const;
|
||||
|
||||
public slots:
|
||||
void BuildProject();
|
||||
|
||||
signals:
|
||||
void UpdateProgress(int progress);
|
||||
void Done(QString result);
|
||||
|
||||
private:
|
||||
void WriteErrorLog(const QString& log);
|
||||
|
||||
ProjectInfo m_projectInfo;
|
||||
};
|
||||
|
||||
class ProjectBuilderController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent = nullptr);
|
||||
~ProjectBuilderController();
|
||||
|
||||
void SetProjectButton(ProjectButton* projectButton);
|
||||
QString GetProjectPath() const;
|
||||
|
||||
public slots:
|
||||
void Start();
|
||||
void UpdateUIProgress(int progress);
|
||||
void HandleResults(const QString& result);
|
||||
|
||||
signals:
|
||||
void Done();
|
||||
|
||||
private:
|
||||
ProjectInfo m_projectInfo;
|
||||
ProjectBuilderWorker* m_worker;
|
||||
QThread m_workerThread;
|
||||
ProjectButton* m_projectButton;
|
||||
QWidget* m_parent;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TemplateButtonWidget.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPixmap>
|
||||
#include <QAbstractButton>
|
||||
#include <QStyle>
|
||||
#include <QVariant>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
|
||||
TemplateButton::TemplateButton(const QString& imagePath, const QString& labelText, QWidget* parent)
|
||||
: QPushButton(parent)
|
||||
{
|
||||
setAutoExclusive(true);
|
||||
|
||||
setObjectName("templateButton");
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(vLayout);
|
||||
|
||||
QLabel* image = new QLabel(this);
|
||||
image->setObjectName("templateImage");
|
||||
image->setPixmap(
|
||||
QPixmap(imagePath).scaled(QSize(s_templateImageWidth,s_templateImageHeight) , Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
vLayout->addWidget(image);
|
||||
|
||||
QLabel* label = new QLabel(labelText, this);
|
||||
label->setObjectName("templateLabel");
|
||||
vLayout->addWidget(label);
|
||||
|
||||
connect(this, &QAbstractButton::toggled, this, &TemplateButton::onToggled);
|
||||
}
|
||||
|
||||
void TemplateButton::onToggled()
|
||||
{
|
||||
setProperty("Checked", isChecked());
|
||||
|
||||
// we must unpolish/polish every child after changing a property
|
||||
// or else they won't use the correct stylesheet selector
|
||||
for (auto child : findChildren<QWidget*>())
|
||||
{
|
||||
child->style()->unpolish(child);
|
||||
child->style()->polish(child);
|
||||
}
|
||||
|
||||
style()->unpolish(this);
|
||||
style()->polish(this);
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QPushButton>
|
||||
#endif
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class TemplateButton
|
||||
: public QPushButton
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
explicit TemplateButton(const QString& imagePath, const QString& labelText, QWidget* parent = nullptr);
|
||||
~TemplateButton() = default;
|
||||
|
||||
protected slots:
|
||||
void onToggled();
|
||||
|
||||
private:
|
||||
inline constexpr static int s_templateImageWidth = 92;
|
||||
inline constexpr static int s_templateImageHeight = 122;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"materialType": "Materials\\Types\\StandardPBR.materialtype",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"general": {
|
||||
"enableShadows": false,
|
||||
"enableDirectionalLights": false,
|
||||
"enablePunctualLights": false,
|
||||
"enableAreaLights": false,
|
||||
"enableIBL": true
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [ 0.0, 1.0, 0.0 ]
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "None",
|
||||
"doubleSided": true,
|
||||
"factor": 0.25,
|
||||
"mode": "TintedTransparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"materialType": "Materials\\Types\\StandardPBR.materialtype",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"general": {
|
||||
"enableShadows": false,
|
||||
"enableDirectionalLights": false,
|
||||
"enablePunctualLights": false,
|
||||
"enableAreaLights": false,
|
||||
"enableIBL": true
|
||||
},
|
||||
"baseColor": {
|
||||
"color": [ 0.0, 1.0, 0.0 ]
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "None",
|
||||
"doubleSided": true,
|
||||
"factor": 1.0,
|
||||
"mode": "TintedTransparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:75cdf73fcb9698a76a38294a1cf927a4fb41a34869e0429e1f02bf8d361a7258
|
||||
size 20400
|
||||
@ -0,0 +1,75 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "ContrastAdaptiveSharpeningTemplate",
|
||||
"PassClass": "ComputePass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "InputColor",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_inputColor",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "OutputColor",
|
||||
"SlotType": "Output",
|
||||
"ShaderInputName": "m_outputColor",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
{
|
||||
"Name": "Output",
|
||||
"FormatSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "InputColor"
|
||||
},
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "This",
|
||||
"Attachment": "InputColor"
|
||||
}
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"BindFlags": "3",
|
||||
"SharedQueueMask": "1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "OutputColor",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
],
|
||||
"FallbackConnections": [
|
||||
{
|
||||
"Input": "InputColor",
|
||||
"Output": "OutputColor"
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "ComputePassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/Postprocessing/ContrastAdaptiveSharpening.shader"
|
||||
},
|
||||
"Make Fullscreen Pass": true,
|
||||
"ShaderDataMappings": {
|
||||
"FloatMappings": [
|
||||
{
|
||||
"Name": "m_strength",
|
||||
"Value": 0.25
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "TaaTemplate",
|
||||
"PassClass": "TaaPass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "InputColor",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_inputColor",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "InputDepth",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_inputDepth",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "MotionVectors",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_motionVectors",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "LastFrameAccumulation",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_lastFrameAccumulation",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "OutputColor",
|
||||
"SlotType": "Output",
|
||||
"ShaderInputName": "m_outputColor",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
{
|
||||
"Name": "Accumulation1",
|
||||
"Lifetime": "Imported",
|
||||
"FormatSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "InputColor"
|
||||
},
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "This",
|
||||
"Attachment": "InputColor"
|
||||
}
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"BindFlags": "3",
|
||||
"SharedQueueMask": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Accumulation2",
|
||||
"Lifetime": "Imported",
|
||||
"FormatSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "InputColor"
|
||||
},
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "This",
|
||||
"Attachment": "InputColor"
|
||||
}
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"BindFlags": "3",
|
||||
"SharedQueueMask": "1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"FallbackConnections": [
|
||||
{
|
||||
"Input": "InputColor",
|
||||
"Output": "OutputColor"
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "TaaPassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/Postprocessing/Taa.shader"
|
||||
},
|
||||
"Make Fullscreen Pass": true,
|
||||
"ShaderDataMappings": {
|
||||
"FloatMappings": [
|
||||
{
|
||||
"Name": "m_currentFrameContribution",
|
||||
"Value": 0.1
|
||||
},
|
||||
{
|
||||
"Name": "m_clampGamma",
|
||||
"Value": 1.0
|
||||
},
|
||||
{
|
||||
"Name": "m_maxDeviationBeforeDampening",
|
||||
"Value": 0.5
|
||||
}
|
||||
]
|
||||
},
|
||||
"NumJitterPositions": 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <scenesrg.srgi>
|
||||
#include <Atom/Features/PostProcessing/PostProcessUtil.azsli>
|
||||
|
||||
#define TILE_DIM_X 16
|
||||
#define TILE_DIM_Y 16
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
{
|
||||
Texture2D<float4> m_inputColor;
|
||||
RWTexture2D<float4> m_outputColor;
|
||||
|
||||
float m_strength; // Strength of the sharpening effect. Range from 0 to 1.
|
||||
}
|
||||
|
||||
|
||||
// Constrast Adaptive Sharpening, based on AMD FidelityFX CAS - https://gpuopen.com/fidelityfx-cas/
|
||||
|
||||
// This shader sharpens the input based on the contrast of the local neighborhood
|
||||
// so that only areas that need sharpening are sharpened, while high constast areas
|
||||
// are mostly left alone.
|
||||
|
||||
[numthreads(TILE_DIM_X, TILE_DIM_Y, 1)]
|
||||
void MainCS(
|
||||
uint3 dispatchThreadID : SV_DispatchThreadID,
|
||||
uint3 groupID : SV_GroupID,
|
||||
uint groupIndex : SV_GroupIndex)
|
||||
{
|
||||
uint2 pixelCoord = dispatchThreadID.xy;
|
||||
|
||||
// Fetch local neighborhood to determin sharpening weight.
|
||||
// a
|
||||
// b c d
|
||||
// e
|
||||
|
||||
float3 sampleA = PassSrg::m_inputColor[pixelCoord + int2( 0, -1)].rgb;
|
||||
float3 sampleB = PassSrg::m_inputColor[pixelCoord + int2(-1, 0)].rgb;
|
||||
float3 sampleC = PassSrg::m_inputColor[pixelCoord + int2( 0, 0)].rgb;
|
||||
float3 sampleD = PassSrg::m_inputColor[pixelCoord + int2( 1, 0)].rgb;
|
||||
float3 sampleE = PassSrg::m_inputColor[pixelCoord + int2( 0, 1)].rgb;
|
||||
|
||||
float lumA = GetLuminance(sampleA);
|
||||
float lumB = GetLuminance(sampleB);
|
||||
float lumC = GetLuminance(sampleC);
|
||||
float lumD = GetLuminance(sampleD);
|
||||
float lumE = GetLuminance(sampleE);
|
||||
|
||||
// Get the min and max. Just use the green channel for luminance.
|
||||
float minLum = min(min(lumA, lumB), min(lumC, min(lumD, lumE)));
|
||||
float maxLum = max(max(lumA, lumB), max(lumC, max(lumD, lumE)));
|
||||
|
||||
float dMinLum = minLum; // Distance from 0 to minimum
|
||||
float dMaxLum = 1.0 - maxLum; // Distance from 1 to the maximum
|
||||
|
||||
// baseSharpening is higher when local contrast is lower to avoid over-sharpening.
|
||||
float baseSharpening = min(dMinLum, dMaxLum) / max(maxLum, 0.0001);
|
||||
baseSharpening = sqrt(baseSharpening); // bias towards more sharpening
|
||||
|
||||
// Negative weights for sharpening effect, center pixel is always weighted 1.
|
||||
float developerMaximum = lerp(-0.125, -0.2, PassSrg::m_strength);
|
||||
float weight = baseSharpening * developerMaximum;
|
||||
float totalWeight = weight * 4 + 1.0;
|
||||
|
||||
float3 output =
|
||||
(
|
||||
sampleA * weight +
|
||||
sampleB * weight +
|
||||
sampleC +
|
||||
sampleD * weight +
|
||||
sampleE * weight
|
||||
) / totalWeight;
|
||||
|
||||
PassSrg::m_outputColor[pixelCoord] = float4(output, 1.0);
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"Source": "ContrastAdaptiveSharpening",
|
||||
"ProgramSettings": {
|
||||
"EntryPoints": [
|
||||
{
|
||||
"name": "MainCS",
|
||||
"type": "Compute"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <scenesrg.srgi>
|
||||
#include <Atom/Features/PostProcessing/PostProcessUtil.azsli>
|
||||
|
||||
#define TILE_DIM_X 16
|
||||
#define TILE_DIM_Y 16
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
{
|
||||
Texture2D<float4> m_inputColor;
|
||||
Texture2D<float4> m_inputDepth;
|
||||
Texture2D<float2> m_motionVectors;
|
||||
Texture2D<float4> m_lastFrameAccumulation;
|
||||
|
||||
RWTexture2D<float4> m_outputColor;
|
||||
|
||||
Sampler LinearSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Linear;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
// Current frame's default contribution to the history.
|
||||
float m_currentFrameContribution;
|
||||
|
||||
// Increase this value for weaker clamping, decrease for stronger clamping, default 1.0.
|
||||
float m_clampGamma;
|
||||
|
||||
// Default 0.5, used for flicker reduction. Any sample further than this many standard deviations outside the neighborhood
|
||||
// will have its weight decreased. The further outside the max deviation, the more its weight is reduced.
|
||||
float m_maxDeviationBeforeDampening;
|
||||
|
||||
struct Constants
|
||||
{
|
||||
uint2 m_inputColorSize;
|
||||
float2 m_inputColorRcpSize;
|
||||
|
||||
// 3x3 filter weights
|
||||
// 8 2 6
|
||||
// 3 0 1
|
||||
// 7 4 5
|
||||
float4 m_weights1; // 0 1 2 3
|
||||
float4 m_weights2; // 4 5 6 7
|
||||
float4 m_weights3; // 8 x x x
|
||||
};
|
||||
Constants m_constantData;
|
||||
}
|
||||
|
||||
static const int2 offsets[9] =
|
||||
{
|
||||
// Center
|
||||
int2(0, 0),
|
||||
// Cross
|
||||
int2( 1, 0),
|
||||
int2( 0,-1),
|
||||
int2(-1, 0),
|
||||
int2( 0, 1),
|
||||
// Diagonals
|
||||
int2( 1,-1),
|
||||
int2( 1, 1),
|
||||
int2(-1,-1),
|
||||
int2(-1, 1),
|
||||
};
|
||||
|
||||
float3 RgbToYCoCg(float3 rgb)
|
||||
{
|
||||
const float3x3 conversionMatrix =
|
||||
{
|
||||
0.25, 0.50, 0.25,
|
||||
0.50, 0.00, -0.50,
|
||||
-0.25, 0.50, -0.25
|
||||
};
|
||||
return mul(conversionMatrix, rgb);
|
||||
}
|
||||
|
||||
float3 YCoCgToRgb(float3 yCoCg)
|
||||
{
|
||||
const float3x3 conversionMatrix =
|
||||
{
|
||||
1.0, 1.0, -1.0,
|
||||
1.0, 0.0, 1.0,
|
||||
1.0, -1.0, -1.0
|
||||
};
|
||||
return mul(conversionMatrix, yCoCg);
|
||||
}
|
||||
|
||||
// Sample a texture with a 5 tap Catmull-Rom. Consider ripping this out and putting in a more general location.
|
||||
// This function samples a 4x4 neighborhood around the uv. By taking advantage of bilinear filtering this can be
|
||||
// done with only 9 taps on the edges between pixels. The cost is further reduced by dropping the 4 diagonal
|
||||
// samples as their influence is negligible.
|
||||
float4 SampleCatmullRom5Tap(Texture2D<float4> texture, SamplerState linearSampler, float2 uv, float2 textureSize, float2 rcpTextureSize, float sharpness)
|
||||
{
|
||||
// Think of sample locations in the 4x4 neighborhood as having a top left coordinate of 0,0 and
|
||||
// a bottom right coordinate of 3,3.
|
||||
|
||||
// Find the position in texture space then round it to get the center of the 1,1 pixel (tc1)
|
||||
float2 texelPos = uv * textureSize;
|
||||
float2 tc1= floor(texelPos - 0.5) + 0.5;
|
||||
|
||||
// Offset from center position to texel
|
||||
float2 f = texelPos - tc1;
|
||||
|
||||
// Compute Catmull-Rom weights based on the offset and sharpness
|
||||
float c = sharpness;
|
||||
float2 w0 = f * (-c + f * (2.0 * c - c * f));
|
||||
float2 w1 = 1.0 + f * f * (c -3.0 + (2.0 - c) * f);
|
||||
float2 w2 = f * (c + f * ((3.0 - 2.0 * c) - (2.0 - c) * f));
|
||||
float2 w3 = f * f * (c * f - c);
|
||||
|
||||
float2 w12 = w1 + w2;
|
||||
|
||||
// Compute uv coordinates for sampling the texture
|
||||
float2 tc0 = (tc1 - 1.0f) * rcpTextureSize;
|
||||
float2 tc3 = (tc1 + 2.0f) * rcpTextureSize;
|
||||
float2 tc12 = (tc1 + w2 / w12) * rcpTextureSize;
|
||||
|
||||
// Compute sample weights
|
||||
float sw0 = w12.x * w0.y;
|
||||
float sw1 = w0.x * w12.y;
|
||||
float sw2 = w12.x * w12.y;
|
||||
float sw3 = w3.x * w12.y;
|
||||
float sw4 = w12.x * w3.y;
|
||||
|
||||
// total weight of samples to normalize result.
|
||||
float totalWeight = sw0 + sw1 + sw2 + sw3 + sw4;
|
||||
|
||||
float4 result = 0.0f;
|
||||
result += texture.SampleLevel(linearSampler, float2(tc12.x, tc0.y), 0.0) * sw0;
|
||||
result += texture.SampleLevel(linearSampler, float2( tc0.x, tc12.y), 0.0) * sw1;
|
||||
result += texture.SampleLevel(linearSampler, float2(tc12.x, tc12.y), 0.0) * sw2;
|
||||
result += texture.SampleLevel(linearSampler, float2( tc3.x, tc12.y), 0.0) * sw3;
|
||||
result += texture.SampleLevel(linearSampler, float2(tc12.x, tc3.y), 0.0) * sw4;
|
||||
|
||||
return result / totalWeight;
|
||||
}
|
||||
|
||||
[numthreads(TILE_DIM_X, TILE_DIM_Y, 1)]
|
||||
void MainCS(
|
||||
uint3 dispatchThreadID : SV_DispatchThreadID,
|
||||
uint3 groupID : SV_GroupID,
|
||||
uint groupIndex : SV_GroupIndex)
|
||||
{
|
||||
uint2 pixelCoord = dispatchThreadID.xy;
|
||||
|
||||
const float filterWeights[9] =
|
||||
{
|
||||
PassSrg::m_constantData.m_weights1.x,
|
||||
PassSrg::m_constantData.m_weights1.y,
|
||||
PassSrg::m_constantData.m_weights1.z,
|
||||
PassSrg::m_constantData.m_weights1.w,
|
||||
PassSrg::m_constantData.m_weights2.x,
|
||||
PassSrg::m_constantData.m_weights2.y,
|
||||
PassSrg::m_constantData.m_weights2.z,
|
||||
PassSrg::m_constantData.m_weights2.w,
|
||||
PassSrg::m_constantData.m_weights3.x,
|
||||
};
|
||||
|
||||
float3 sum = 0.0;
|
||||
float3 sumOfSquares = 0.0;
|
||||
float nearestDepth = 1.0;
|
||||
uint2 nearestDepthPixelCoord;
|
||||
|
||||
float3 thisFrameColor = float3(0.0, 0.0, 0.0);
|
||||
|
||||
// Sample the neighborhood to filter the current pixel, gather statistics about
|
||||
// its neighbors, and find the closest neighbor to choose a motion vector.
|
||||
[unroll] for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
uint2 neighborhoodPixelCoord = pixelCoord + offsets[i];
|
||||
float3 neighborhoodColor = PassSrg::m_inputColor[neighborhoodPixelCoord].rgb;
|
||||
|
||||
// Convert to YCoCg space for better clipping.
|
||||
neighborhoodColor = RgbToYCoCg(neighborhoodColor);
|
||||
|
||||
sum += neighborhoodColor;
|
||||
sumOfSquares += neighborhoodColor * neighborhoodColor;
|
||||
thisFrameColor += neighborhoodColor * filterWeights[i];
|
||||
|
||||
// Find the coordinate of the nearest depth
|
||||
float neighborhoodDepth = PassSrg::m_inputDepth[neighborhoodPixelCoord].r;
|
||||
if (neighborhoodDepth < nearestDepth)
|
||||
{
|
||||
nearestDepth = neighborhoodDepth;
|
||||
nearestDepthPixelCoord = neighborhoodPixelCoord;
|
||||
}
|
||||
}
|
||||
|
||||
// Variance clipping, see http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf
|
||||
float3 mean = sum / 9.0;
|
||||
float3 standardDeviation = max(0.0, sqrt(sumOfSquares / 9.0 - mean * mean));
|
||||
standardDeviation *= PassSrg::m_clampGamma;
|
||||
|
||||
// Grab the motion vector from the closest pixel in the 3x3 neighborhood. This is done so that motion vectors correctly
|
||||
// track edges. For instance, if a pixel lies on the edge of a moving object, where the color is a blend of the
|
||||
// forground and background, it's possible for the pixel center to hit the (not moving) background. However, the correct
|
||||
// history for this pixel will be the location this edge was the previous frame. By choosing the motion of the nearest
|
||||
// pixel in the neighborhood that edge will be correctly tracked.
|
||||
|
||||
// Motion vectors store the direction of movement, so to look up where things were in the previous frame, it's negated.
|
||||
float2 previousPositionOffset = -PassSrg::m_motionVectors[nearestDepthPixelCoord];
|
||||
|
||||
// Get the uv coordinate for the previous frame.
|
||||
float2 rcpSize = PassSrg::m_constantData.m_inputColorRcpSize;
|
||||
float2 uvCoord = (pixelCoord + 0.5f) * rcpSize;
|
||||
float2 uvOld = uvCoord + previousPositionOffset;
|
||||
float2 previousPositionOffsetInPixels = float2(PassSrg::m_constantData.m_inputColorSize) * previousPositionOffset;
|
||||
|
||||
// Sample the last frame using a 5-tap Catmull-Rom
|
||||
float3 lastFrameColor = SampleCatmullRom5Tap(PassSrg::m_lastFrameAccumulation, PassSrg::LinearSampler, uvOld, PassSrg::m_constantData.m_inputColorSize, PassSrg::m_constantData.m_inputColorRcpSize, 0.5).rgb;
|
||||
lastFrameColor = RgbToYCoCg(lastFrameColor);
|
||||
|
||||
// Last frame color relative to mean
|
||||
float3 centerColorOffset = lastFrameColor - mean;
|
||||
float3 colorOffsetStandardDeviationRatio = abs(standardDeviation / centerColorOffset);
|
||||
|
||||
// Clamp the color by the aabb of the standardDeviation. Can never be greater than 1, so will always be inside or on the bounds of the aabb.
|
||||
float clampedColorLength = min(min(min(1, colorOffsetStandardDeviationRatio.x), colorOffsetStandardDeviationRatio.y), colorOffsetStandardDeviationRatio.z);
|
||||
|
||||
// Calculate the true clamped color by offsetting it back from the mean.
|
||||
float3 lastFrameClampedColor = mean + centerColorOffset * clampedColorLength;
|
||||
|
||||
// Anti-flickering - Reduce current frame weight the more it deviates from the history based on the standard deviation of the neighborhood.
|
||||
// Start reducing weight at differences greater than m_maxDeviationBeforeDampening standard deviations in luminance.
|
||||
float standardDeviationWeight = standardDeviation.r * PassSrg::m_maxDeviationBeforeDampening;
|
||||
float3 sdFromLastFrame = standardDeviationWeight / abs(lastFrameClampedColor.r - thisFrameColor.r);
|
||||
|
||||
float currentFrameWeight = PassSrg::m_currentFrameContribution;
|
||||
currentFrameWeight *= saturate(sdFromLastFrame * sdFromLastFrame);
|
||||
|
||||
// Back to Rgb space
|
||||
thisFrameColor = YCoCgToRgb(thisFrameColor);
|
||||
lastFrameClampedColor = YCoCgToRgb(lastFrameClampedColor);
|
||||
|
||||
// Out of bounds protection.
|
||||
if (any(uvOld > 1.0) || any(uvOld < 0.0))
|
||||
{
|
||||
currentFrameWeight = 1.0f;
|
||||
}
|
||||
|
||||
// Blend should be in perceptual space, so tonemap first
|
||||
float luminance = GetLuminance(thisFrameColor);
|
||||
thisFrameColor = thisFrameColor / (1 + luminance);
|
||||
lastFrameClampedColor = lastFrameClampedColor / (1 + luminance);
|
||||
|
||||
// Blend color with history
|
||||
float3 color = lerp(lastFrameClampedColor, thisFrameColor, currentFrameWeight);
|
||||
|
||||
// Un-tonemap color
|
||||
color = color * (1.0 + luminance);
|
||||
|
||||
// NaN protection (without this NaNs could get in the history buffer and quickly consume the frame)
|
||||
color = max(0.0, color);
|
||||
|
||||
PassSrg::m_outputColor[pixelCoord].rgb = color;
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"Source": "Taa",
|
||||
"ProgramSettings": {
|
||||
"EntryPoints": [
|
||||
{
|
||||
"name": "MainCS",
|
||||
"type": "Compute"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <Atom/RPI.Public/FeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
enum class DiffuseGlobalIlluminationQualityLevel : uint8_t
|
||||
{
|
||||
Low,
|
||||
Medium,
|
||||
High
|
||||
};
|
||||
|
||||
//! This class provides general features and configuration for the diffuse global illumination environment,
|
||||
//! which consists of DiffuseProbeGrids and the diffuse Global IBL cubemap.
|
||||
class DiffuseGlobalIlluminationFeatureProcessorInterface
|
||||
: public RPI::FeatureProcessor
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::DiffuseProbeGridFeatureProcessorInterface, "{BD8CA35A-47C3-4FD8-932B-18495EF07527}");
|
||||
|
||||
virtual void SetQualityLevel(DiffuseGlobalIlluminationQualityLevel qualityLevel) = 0;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <Atom/RPI.Public/FeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
class OcclusionCullingPlane;
|
||||
|
||||
using OcclusionCullingPlaneHandle = AZStd::shared_ptr<OcclusionCullingPlane>;
|
||||
|
||||
// OcclusionCullingPlaneFeatureProcessorInterface provides an interface to the feature processor for code outside of Atom
|
||||
class OcclusionCullingPlaneFeatureProcessorInterface
|
||||
: public RPI::FeatureProcessor
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::OcclusionCullingPlaneFeatureProcessorInterface, "{50F6B45E-A622-44EC-B962-DE25FBD44095}");
|
||||
|
||||
virtual OcclusionCullingPlaneHandle AddOcclusionCullingPlane(const AZ::Transform& transform) = 0;
|
||||
virtual void RemoveOcclusionCullingPlane(OcclusionCullingPlaneHandle& handle) = 0;
|
||||
virtual bool IsValidOcclusionCullingPlaneHandle(const OcclusionCullingPlaneHandle& occlusionCullingPlane) const = 0;
|
||||
virtual void SetTransform(const OcclusionCullingPlaneHandle& occlusionCullingPlane, const AZ::Transform& transform) = 0;
|
||||
virtual void SetEnabled(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool enabled) = 0;
|
||||
virtual void ShowVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool showVisualization) = 0;
|
||||
virtual void SetTransparentVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool transparentVisualization) = 0;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <Atom/RPI.Public/RPIUtils.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFilter.h>
|
||||
#include <Atom/RPI.Public/Pass/FullscreenTrianglePass.h>
|
||||
#include <DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::Reflect(ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serializeContext
|
||||
->Class<DiffuseGlobalIlluminationFeatureProcessor, FeatureProcessor>()
|
||||
->Version(0);
|
||||
}
|
||||
}
|
||||
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::Activate()
|
||||
{
|
||||
EnableSceneNotification();
|
||||
}
|
||||
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::Deactivate()
|
||||
{
|
||||
DisableSceneNotification();
|
||||
}
|
||||
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::SetQualityLevel(DiffuseGlobalIlluminationQualityLevel qualityLevel)
|
||||
{
|
||||
m_qualityLevel = qualityLevel;
|
||||
|
||||
UpdatePasses();
|
||||
}
|
||||
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::OnRenderPipelinePassesChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline)
|
||||
{
|
||||
UpdatePasses();
|
||||
}
|
||||
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::OnRenderPipelineAdded([[maybe_unused]] RPI::RenderPipelinePtr pipeline)
|
||||
{
|
||||
UpdatePasses();
|
||||
}
|
||||
|
||||
void DiffuseGlobalIlluminationFeatureProcessor::UpdatePasses()
|
||||
{
|
||||
float sizeMultiplier = 0.0f;
|
||||
switch (m_qualityLevel)
|
||||
{
|
||||
case DiffuseGlobalIlluminationQualityLevel::Low:
|
||||
sizeMultiplier = 0.25f;
|
||||
break;
|
||||
case DiffuseGlobalIlluminationQualityLevel::Medium:
|
||||
sizeMultiplier = 0.5f;
|
||||
break;
|
||||
case DiffuseGlobalIlluminationQualityLevel::High:
|
||||
sizeMultiplier = 1.0f;
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Unknown DiffuseGlobalIlluminationQualityLevel [%d]", m_qualityLevel);
|
||||
break;
|
||||
}
|
||||
|
||||
// update the size multiplier on the DiffuseProbeGridDownsamplePass output
|
||||
AZStd::vector<Name> downsamplePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseProbeGridDownsamplePass") };
|
||||
RPI::PassHierarchyFilter downsamplePassFilter(downsamplePassHierarchy);
|
||||
const AZStd::vector<RPI::Pass*>& downsamplePasses = RPI::PassSystemInterface::Get()->FindPasses(downsamplePassFilter);
|
||||
for (RPI::Pass* pass : downsamplePasses)
|
||||
{
|
||||
for (uint32_t outputIndex = 0; outputIndex < pass->GetOutputCount(); ++outputIndex)
|
||||
{
|
||||
RPI::Ptr<RPI::PassAttachment> outputAttachment = pass->GetOutputBinding(outputIndex).m_attachment;
|
||||
RPI::PassAttachmentSizeMultipliers& sizeMultipliers = outputAttachment->m_sizeMultipliers;
|
||||
|
||||
sizeMultipliers.m_widthMultiplier = sizeMultiplier;
|
||||
sizeMultipliers.m_heightMultiplier = sizeMultiplier;
|
||||
}
|
||||
|
||||
// set the output scale on the PassSrg
|
||||
RPI::FullscreenTrianglePass* downsamplePass = static_cast<RPI::FullscreenTrianglePass*>(pass);
|
||||
auto constantIndex = downsamplePass->GetShaderResourceGroup()->FindShaderInputConstantIndex(Name("m_outputImageScale"));
|
||||
downsamplePass->GetShaderResourceGroup()->SetConstant(constantIndex, aznumeric_cast<uint32_t>(1.0f / sizeMultiplier));
|
||||
}
|
||||
|
||||
// update the image scale on the DiffuseComposite pass
|
||||
AZStd::vector<Name> compositePassHierarchy = { Name("DiffuseGlobalIlluminationPass"), Name("DiffuseCompositePass") };
|
||||
RPI::PassHierarchyFilter compositePassFilter(compositePassHierarchy);
|
||||
const AZStd::vector<RPI::Pass*>& compositePasses = RPI::PassSystemInterface::Get()->FindPasses(compositePassFilter);
|
||||
for (RPI::Pass* pass : compositePasses)
|
||||
{
|
||||
RPI::FullscreenTrianglePass* compositePass = static_cast<RPI::FullscreenTrianglePass*>(pass);
|
||||
auto constantIndex = compositePass->GetShaderResourceGroup()->FindShaderInputConstantIndex(Name("m_imageScale"));
|
||||
compositePass->GetShaderResourceGroup()->SetConstant(constantIndex, aznumeric_cast<uint32_t>(1.0f / sizeMultiplier));
|
||||
}
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Feature/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessorInterface.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
//! This class provides general features and configuration for the diffuse global illumination environment,
|
||||
//! which consists of DiffuseProbeGrids and the diffuse Global IBL cubemap.
|
||||
class DiffuseGlobalIlluminationFeatureProcessor final
|
||||
: public DiffuseGlobalIlluminationFeatureProcessorInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::DiffuseGlobalIlluminationFeatureProcessor, "{14F7DF46-AA2C-49EF-8A2C-0A7CB7390BB7}", DiffuseGlobalIlluminationFeatureProcessorInterface);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
DiffuseGlobalIlluminationFeatureProcessor() = default;
|
||||
virtual ~DiffuseGlobalIlluminationFeatureProcessor() = default;
|
||||
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
// DiffuseGlobalIlluminationFeatureProcessorInterface overrides
|
||||
void SetQualityLevel(DiffuseGlobalIlluminationQualityLevel qualityLevel) override;
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(DiffuseGlobalIlluminationFeatureProcessor);
|
||||
|
||||
// RPI::SceneNotificationBus::Handler overrides
|
||||
void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override;
|
||||
void OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) override;
|
||||
|
||||
void UpdatePasses();
|
||||
|
||||
DiffuseGlobalIlluminationQualityLevel m_qualityLevel = DiffuseGlobalIlluminationQualityLevel::Low;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue