Compositor: Display generated inputs in Viewers and Previews

Currently viewers and previews only display node trees that have at least one node with fixed resolution size. When all inputs are generated, nothing is displayed in most cases (RGB Node is displayed as a single pixel on previews). By generated I mean inputs not having resolution on their own, they create content dynamically given an output resolution.

This patch adds support for those cases by using an appropriate preferred resolution on Viewers/Previews which propagates to generated inputs as output resolution. Now:
- Viewers will display generated inputs with scene render resolution.
- Previews will display them with scene aspect ratio.
This is consistent with final render result and respects relative space.

The benefit for the user is being able to compose images without any input source. For example for creating mask images or simple backgrounds.

Reviewed By: Jeroen Bakker

Differential Revision: https://developer.blender.org/D10611
This commit is contained in:
Manuel Castilla 2021-03-23 12:04:34 +01:00 committed by Jeroen Bakker
parent 8cac85abfe
commit 9fb5559a0f
7 changed files with 46 additions and 21 deletions

@ -1 +1 @@
Subproject commit ef74c1b861a1b05c2483a2c045a6380704167491
Subproject commit 2cef4877edc40875978c4e95322bb5193f5815bf

@ -1 +1 @@
Subproject commit 6dfba915743b67aff99ddcc19c0807d339a87c96
Subproject commit bcd08a9506d33bdd7358201031b04d041ef22d94

View File

@ -195,7 +195,9 @@ PreviewOperation *NodeOperationBuilder::make_preview_operation() const
bNodeInstanceHash *previews = m_context->getPreviewHash();
if (previews) {
PreviewOperation *operation = new PreviewOperation(m_context->getViewSettings(),
m_context->getDisplaySettings());
m_context->getDisplaySettings(),
m_current_node->getbNode()->preview_xsize,
m_current_node->getbNode()->preview_ysize);
operation->setbNodeTree(m_context->getbNodeTree());
operation->verifyPreview(previews, m_current_node->getInstanceKey());
return operation;

View File

@ -34,7 +34,9 @@
#include "IMB_imbuf_types.h"
PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings)
const ColorManagedDisplaySettings *displaySettings,
const unsigned int defaultWidth,
const unsigned int defaultHeight)
{
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
@ -44,6 +46,8 @@ PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings,
this->m_divider = 1.0f;
this->m_viewSettings = viewSettings;
this->m_displaySettings = displaySettings;
this->m_defaultWidth = defaultWidth;
this->m_defaultHeight = defaultHeight;
}
void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key)
@ -123,30 +127,33 @@ bool PreviewOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void PreviewOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
unsigned int /*preferredResolution*/[2])
{
NodeOperation::determineResolution(resolution, preferredResolution);
/* Use default preview resolution as preferred ensuring it has size so that
* generated inputs (which don't have resolution on their own) are displayed */
BLI_assert(this->m_defaultWidth > 0 && this->m_defaultHeight > 0);
unsigned int previewPreferredRes[2] = {this->m_defaultWidth, this->m_defaultHeight};
NodeOperation::determineResolution(resolution, previewPreferredRes);
/* If resolution is 0 there are two possible scenarios:
* - Either node is not connected at all
* - It is connected to input which doesn't have own resolution (i.e. color input).
* - Or it is connected to an input which has no resolution.
*
* In the former case we rely on the execution system to not evaluate this node.
*
* For the latter case we use 1 pixel preview, so that it's possible to see preview color in the
* preview. This is how final F12 render will behave (flood-fill final frame with the color).
*
* Having things consistent in terms that node preview is scaled down F12 render is a very
* natural thing to do. */
int width = max_ii(1, resolution[0]);
int height = max_ii(1, resolution[1]);
* The latter case would only happen if an input doesn't set any resolution ignoring output
* preferred resolution. In such case preview size will be 0 too.
*/
int width = resolution[0];
int height = resolution[1];
this->m_divider = 0.0f;
if (width > height) {
this->m_divider = (float)COM_PREVIEW_SIZE / (width);
}
else {
this->m_divider = (float)COM_PREVIEW_SIZE / (height);
if (width > 0 && height > 0) {
if (width > height) {
this->m_divider = (float)COM_PREVIEW_SIZE / (width);
}
else {
this->m_divider = (float)COM_PREVIEW_SIZE / (height);
}
}
width = width * this->m_divider;
height = height * this->m_divider;

View File

@ -34,13 +34,17 @@ class PreviewOperation : public NodeOperation {
bNodePreview *m_preview;
SocketReader *m_input;
float m_divider;
unsigned int m_defaultWidth;
unsigned int m_defaultHeight;
const ColorManagedViewSettings *m_viewSettings;
const ColorManagedDisplaySettings *m_displaySettings;
public:
PreviewOperation(const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings);
const ColorManagedDisplaySettings *displaySettings,
unsigned int defaultWidth,
unsigned int defaultHeight);
void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key);
bool isOutputOperation(bool /*rendering*/) const

View File

@ -118,6 +118,17 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
updateImage(rect);
}
void ViewerOperation::determineResolution(unsigned int resolution[2],
unsigned int /*preferredResolution*/[2])
{
const int sceneRenderWidth = this->m_rd->xsch * this->m_rd->size / 100;
const int sceneRenderHeight = this->m_rd->ysch * this->m_rd->size / 100;
unsigned int localPrefRes[2] = {static_cast<unsigned int>(sceneRenderWidth),
static_cast<unsigned int>(sceneRenderHeight)};
NodeOperation::determineResolution(resolution, localPrefRes);
}
void ViewerOperation::initImage()
{
Image *ima = this->m_image;

View File

@ -51,6 +51,7 @@ class ViewerOperation : public NodeOperation {
void initExecution();
void deinitExecution();
void executeRegion(rcti *rect, unsigned int tileNumber);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
bool isOutputOperation(bool /*rendering*/) const
{
if (G.background) {