Merge pull request #6688 from Atlante45/graphics

Added live custom debug shader support
This commit is contained in:
samcake 2015-12-17 16:19:49 -08:00
commit e179326e58
6 changed files with 172 additions and 87 deletions

View file

@ -1,6 +1,7 @@
// //
// SunLightExample.js // renderEngineDebug.js
// examples // examples/utilities/tools
//
// Sam Gateau // Sam Gateau
// Copyright 2015 High Fidelity, Inc. // Copyright 2015 High Fidelity, Inc.
// //
@ -12,6 +13,7 @@ Script.include("cookies.js");
var MENU = "Developer>Render>Debug Deferred Buffer"; var MENU = "Developer>Render>Debug Deferred Buffer";
var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"]; var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"];
var SETTINGS_KEY = "EngineDebugScript.DebugMode";
Number.prototype.clamp = function(min, max) { Number.prototype.clamp = function(min, max) {
return Math.min(Math.max(this, min), max); return Math.min(Math.max(this, min), max);
@ -69,6 +71,9 @@ var overlaysCounter = new CounterWidget(panel, "Overlays",
); );
var resizing = false; var resizing = false;
var previousMode = Settings.getValue(SETTINGS_KEY, -1);
Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]);
Scene.setEngineDeferredDebugMode(previousMode);
Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size
function setEngineDeferredDebugSize(eventX) { function setEngineDeferredDebugSize(eventX) {
@ -85,7 +90,6 @@ function menuItemEvent(menuItem) {
var index = ACTIONS.indexOf(menuItem); var index = ACTIONS.indexOf(menuItem);
if (index >= 0) { if (index >= 0) {
Scene.setEngineDeferredDebugMode(index - 1); Scene.setEngineDeferredDebugMode(index - 1);
print(menuItem);
} }
} }
@ -152,11 +156,11 @@ Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Menu.menuItemEvent.connect(menuItemEvent); Menu.menuItemEvent.connect(menuItemEvent);
Menu.addActionGroup(MENU, ACTIONS, ACTIONS[0]);
function scriptEnding() { function scriptEnding() {
panel.destroy(); panel.destroy();
Menu.removeActionGroup(MENU); Menu.removeActionGroup(MENU);
Settings.setValue(SETTINGS_KEY, Scene.getEngineDeferredDebugMode());
Scene.setEngineDeferredDebugMode(-1); Scene.setEngineDeferredDebugMode(-1);
Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size
} }

View file

@ -23,7 +23,7 @@ Shader::Shader(Type type, const Source& source):
{ {
} }
Shader::Shader(Type type, Pointer& vertex, Pointer& pixel): Shader::Shader(Type type, const Pointer& vertex, const Pointer& pixel):
_type(type) _type(type)
{ {
_shaders.resize(2); _shaders.resize(2);
@ -44,7 +44,7 @@ Shader::Pointer Shader::createPixel(const Source& source) {
return Pointer(new Shader(PIXEL, source)); return Pointer(new Shader(PIXEL, source));
} }
Shader::Pointer Shader::createProgram(Pointer& vertexShader, Pointer& pixelShader) { Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
if (vertexShader && vertexShader->getType() == VERTEX && if (vertexShader && vertexShader->getType() == VERTEX &&
pixelShader && pixelShader->getType() == PIXEL) { pixelShader && pixelShader->getType() == PIXEL) {
return Pointer(new Shader(PROGRAM, vertexShader, pixelShader)); return Pointer(new Shader(PROGRAM, vertexShader, pixelShader));

View file

@ -111,7 +111,7 @@ public:
static Pointer createVertex(const Source& source); static Pointer createVertex(const Source& source);
static Pointer createPixel(const Source& source); static Pointer createPixel(const Source& source);
static Pointer createProgram(Pointer& vertexShader, Pointer& pixelShader); static Pointer createProgram(const Pointer& vertexShader, const Pointer& pixelShader);
~Shader(); ~Shader();
@ -157,7 +157,7 @@ public:
protected: protected:
Shader(Type type, const Source& source); Shader(Type type, const Source& source);
Shader(Type type, Pointer& vertex, Pointer& pixel); Shader(Type type, const Pointer& vertex, const Pointer& pixel);
Shader(const Shader& shader); // deep copy of the sysmem shader Shader(const Shader& shader); // deep copy of the sysmem shader
Shader& operator=(const Shader& shader); // deep copy of the sysmem texture Shader& operator=(const Shader& shader); // deep copy of the sysmem texture

View file

@ -11,7 +11,7 @@
#include "DebugDeferredBuffer.h" #include "DebugDeferredBuffer.h"
#include <QString> #include <QFile>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <gpu/Context.h> #include <gpu/Context.h>
@ -31,89 +31,160 @@ enum Slots {
Normal, Normal,
Specular, Specular,
Depth, Depth,
Lighting, Lighting
NUM_SLOTS
}; };
static const std::array<std::string, Slots::NUM_SLOTS> SLOT_NAMES {{
"diffuseMap",
"normalMap",
"specularMap",
"depthMap",
"lightingMap"
}};
static const std::string COMPUTE_PLACEHOLDER { "/*COMPUTE_PLACEHOLDER*/" }; // required static const std::string DEEFAULT_DIFFUSE_SHADER {
static const std::string FUNCTIONS_PLACEHOLDER { "/*FUNCTIONS_PLACEHOLDER*/" }; // optional "vec4 getFragmentColor() {"
" return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
" }"
};
static const std::string DEEFAULT_ALPHA_SHADER {
"vec4 getFragmentColor() {"
" return vec4(vec3(texture(diffuseMap, uv).a), 1.0);"
" }"
};
static const std::string DEEFAULT_SPECULAR_SHADER {
"vec4 getFragmentColor() {"
" return vec4(texture(specularMap, uv).xyz, 1.0);"
" }"
};
static const std::string DEEFAULT_ROUGHNESS_SHADER {
"vec4 getFragmentColor() {"
" return vec4(vec3(texture(specularMap, uv).a), 1.0);"
" }"
};
static const std::string DEEFAULT_NORMAL_SHADER {
"vec4 getFragmentColor() {"
" return vec4(texture(normalMap, uv).xyz, 1.0);"
" }"
};
static const std::string DEEFAULT_DEPTH_SHADER {
"vec4 getFragmentColor() {"
" return vec4(vec3(texture(depthMap, uv).x), 1.0);"
" }"
};
static const std::string DEEFAULT_LIGHTING_SHADER {
"vec4 getFragmentColor() {"
" return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
" }"
};
static const std::string DEEFAULT_CUSTOM_SHADER {
"vec4 getFragmentColor() {"
" return vec4(1.0, 0.0, 0.0, 1.0);"
" }"
};
std::string DebugDeferredBuffer::getCode(Modes mode) { static std::string getFileContent(std::string fileName, std::string defaultContent = std::string()) {
switch (mode) { QFile customFile(QString::fromStdString(fileName));
case DiffuseMode: { if (customFile.open(QIODevice::ReadOnly)) {
QString code = "return vec4(pow(texture(%1, uv).xyz, vec3(1.0 / 2.2)), 1.0);"; return customFile.readAll().toStdString();
return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString();
}
case AlphaMode: {
QString code = "return vec4(vec3(texture(%1, uv).a), 1.0);";
return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString();
}
case SpecularMode: {
QString code = "return vec4(texture(%1, uv).xyz, 1.0);";
return code.arg(SLOT_NAMES[Specular].c_str()).toStdString();
}
case RoughnessMode: {
QString code = "return vec4(vec3(texture(%1, uv).a), 1.0);";
return code.arg(SLOT_NAMES[Specular].c_str()).toStdString();
}
case NormalMode: {
QString code = "return vec4(texture(%1, uv).xyz, 1.0);";
return code.arg(SLOT_NAMES[Normal].c_str()).toStdString();
}
case DepthMode: {
QString code = "return vec4(vec3(texture(%1, uv).x), 1.0);";
return code.arg(SLOT_NAMES[Depth].c_str()).toStdString();
}
case LightingMode: {
QString code = "return vec4(pow(texture(%1, uv).xyz, vec3(1.0 / 2.2)), 1.0);";
return code.arg(SLOT_NAMES[Lighting].c_str()).toStdString();
}
case CustomMode:
return std::string("return vec4(1.0);");
case NUM_MODES:
Q_UNIMPLEMENTED();
return std::string("return vec4(1.0);");
} }
qWarning() << "DebugDeferredBuffer::getFileContent(): Could not open"
<< QString::fromStdString(fileName);
return defaultContent;
} }
const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { #include <QStandardPaths> // TODO REMOVE: Temporary until UI
if (!_pipelines[mode]) { DebugDeferredBuffer::DebugDeferredBuffer() {
std::string fragmentShader = debug_deferred_buffer_frag; // TODO REMOVE: Temporary until UI
fragmentShader.replace(fragmentShader.find(COMPUTE_PLACEHOLDER), COMPUTE_PLACEHOLDER.size(), static const auto DESKTOP_PATH = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
getCode(mode)); static const auto CUSTOM_FILE = DESKTOP_PATH.toStdString() + "/custom.slh";
CustomPipeline pipeline;
pipeline.info = QFileInfo(QString::fromStdString(CUSTOM_FILE));
_customPipelines.emplace(CUSTOM_FILE, pipeline);
}
std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode, std::string customFile) {
switch (mode) {
case DiffuseMode:
return DEEFAULT_DIFFUSE_SHADER;
case AlphaMode:
return DEEFAULT_ALPHA_SHADER;
case SpecularMode:
return DEEFAULT_SPECULAR_SHADER;
case RoughnessMode:
return DEEFAULT_ROUGHNESS_SHADER;
case NormalMode:
return DEEFAULT_NORMAL_SHADER;
case DepthMode:
return DEEFAULT_DEPTH_SHADER;
case LightingMode:
return DEEFAULT_LIGHTING_SHADER;
case CustomMode:
return getFileContent(customFile, DEEFAULT_CUSTOM_SHADER);
}
Q_UNREACHABLE();
return std::string();
}
bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode, std::string customFile) const {
if (mode != CustomMode) {
return !_pipelines[mode];
}
auto it = _customPipelines.find(customFile);
if (it != _customPipelines.end() && it->second.pipeline) {
auto& info = it->second.info;
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex({ debug_deferred_buffer_vert })); auto lastModified = info.lastModified();
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(fragmentShader)); info.refresh();
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); return lastModified != info.lastModified();
}
return true;
}
const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::string customFile) {
if (pipelineNeedsUpdate(mode, customFile)) {
static const std::string VERTEX_SHADER { debug_deferred_buffer_vert };
static const std::string FRAGMENT_SHADER { debug_deferred_buffer_frag };
static const std::string SOURCE_PLACEHOLDER { "//SOURCE_PLACEHOLDER" };
static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER);
Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO,
"Could not find source placeholder");
auto bakedFragmentShader = FRAGMENT_SHADER;
bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(),
getShaderSourceCode(mode, customFile));
static const auto vs = gpu::Shader::createVertex(VERTEX_SHADER);
const auto ps = gpu::Shader::createPixel(bakedFragmentShader);
const auto program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
for (int slot = 0; slot < NUM_SLOTS; ++slot) { slotBindings.insert(gpu::Shader::Binding("diffuseMap", Diffuse));
slotBindings.insert(gpu::Shader::Binding(SLOT_NAMES[slot], slot)); slotBindings.insert(gpu::Shader::Binding("normalMap", Normal));
} slotBindings.insert(gpu::Shader::Binding("specularMap", Specular));
slotBindings.insert(gpu::Shader::Binding("depthMap", Depth));
slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting));
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);
auto pipeline = gpu::Pipeline::create(program, std::make_shared<gpu::State>());
// Good to go add the brand new pipeline // Good to go add the brand new pipeline
_pipelines[mode] = gpu::Pipeline::create(program, std::make_shared<gpu::State>()); if (mode != CustomMode) {
_pipelines[mode] = pipeline;
} else {
_customPipelines[customFile].pipeline = pipeline;
}
}
if (mode != CustomMode) {
return _pipelines[mode];
} else {
return _customPipelines[customFile].pipeline;
} }
return _pipelines[mode];
} }
void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
RenderArgs* args = renderContext->args; const RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
auto geometryBuffer = DependencyManager::get<GeometryCache>(); const auto geometryBuffer = DependencyManager::get<GeometryCache>();
auto framebufferCache = DependencyManager::get<FramebufferCache>(); const auto framebufferCache = DependencyManager::get<FramebufferCache>();
glm::mat4 projMat; glm::mat4 projMat;
@ -123,8 +194,11 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
batch.setModelTransform(Transform()); batch.setModelTransform(Transform());
// TODO REMOVE: Temporary until UI
auto first = _customPipelines.begin()->first;
batch.setPipeline(getPipeline(Modes(renderContext->_deferredDebugMode))); batch.setPipeline(getPipeline(Modes(renderContext->_deferredDebugMode), first));
batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture());
batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture());
@ -132,9 +206,9 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture()); batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture());
batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture()); batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture());
glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y); const glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y);
glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w); const glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w);
geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color);
}); });
} }

View file

@ -12,16 +12,20 @@
#ifndef hifi_DebugDeferredBuffer_h #ifndef hifi_DebugDeferredBuffer_h
#define hifi_DebugDeferredBuffer_h #define hifi_DebugDeferredBuffer_h
#include <QFileInfo>
#include <render/DrawTask.h> #include <render/DrawTask.h>
class DebugDeferredBuffer { class DebugDeferredBuffer {
public: public:
using JobModel = render::Job::Model<DebugDeferredBuffer>; using JobModel = render::Job::Model<DebugDeferredBuffer>;
DebugDeferredBuffer();
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
private: private:
enum Modes : int { enum Modes : uint8_t {
DiffuseMode = 0, DiffuseMode = 0,
AlphaMode, AlphaMode,
SpecularMode, SpecularMode,
@ -29,15 +33,22 @@ private:
NormalMode, NormalMode,
DepthMode, DepthMode,
LightingMode, LightingMode,
CustomMode,
NUM_MODES CustomMode // Needs to stay last
}; };
struct CustomPipeline {
gpu::PipelinePointer pipeline;
mutable QFileInfo info;
};
using StandardPipelines = std::array<gpu::PipelinePointer, CustomMode>;
using CustomPipelines = std::unordered_map<std::string, CustomPipeline>;
const gpu::PipelinePointer& getPipeline(Modes mode); bool pipelineNeedsUpdate(Modes mode, std::string customFile = std::string()) const;
std::string getCode(Modes mode); const gpu::PipelinePointer& getPipeline(Modes mode, std::string customFile = std::string());
std::string getShaderSourceCode(Modes mode, std::string customFile = std::string());
std::array<gpu::PipelinePointer, NUM_MODES> _pipelines; StandardPipelines _pipelines;
CustomPipelines _customPipelines;
}; };
#endif // hifi_DebugDeferredBuffer_h #endif // hifi_DebugDeferredBuffer_h

View file

@ -17,11 +17,7 @@
in vec2 uv; in vec2 uv;
out vec4 outFragColor; out vec4 outFragColor;
/*FUNCTIONS_PLACEHOLDER*/ //SOURCE_PLACEHOLDER
vec4 getFragmentColor() {
/*COMPUTE_PLACEHOLDER*/
}
void main(void) { void main(void) {
outFragColor = getFragmentColor(); outFragColor = getFragmentColor();