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:
parent
8cac85abfe
commit
9fb5559a0f
|
@ -1 +1 @@
|
|||
Subproject commit ef74c1b861a1b05c2483a2c045a6380704167491
|
||||
Subproject commit 2cef4877edc40875978c4e95322bb5193f5815bf
|
|
@ -1 +1 @@
|
|||
Subproject commit 6dfba915743b67aff99ddcc19c0807d339a87c96
|
||||
Subproject commit bcd08a9506d33bdd7358201031b04d041ef22d94
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue