It seems there is no bug, doing it
correctly (
) in the code with a compositor seems to be equal to altering the original (createOriginalScene) compositor.
I found that it matters where I use the CompositorManager::getSingleton().addCompositor.
When I wrote that using it as a real compositor only increased FPS by 10%, that was because it was not added as the first compositor (another compositor was added before this one).
When I add it as the first compositor, I do get the same results as when I altered the "createOriginalScene" compositor.
So it seems to only be an application-specific issue.
Though I do not understand how that compositor can make the original (createOriginalScene) compositor not have any effect, but as you said, it is only used for "input previous", so I guess it looks on my real compositor and sees that while only rendering it at the scale I want it rendered at, and ignoring the first full-window render that it would have used normally.
Below is an adjusted version (so it should work for anyone) of my "minimum FPS with dynamic resolution" feature.
Just supply the "m_dynamicResolution" with a minimum FPS value (0 is disabled and is default in the code).
Compositor:
Code: Select all
compositor DynamicResolution
{
technique
{
texture scene 1 1 PF_R8G8B8
target scene
{
input previous
}
target_output
{
input none
pass render_quad
{
material DynamicResolution
input 0 scene
}
}
}
}
Material:
Code: Select all
material DynamicResolution
{
technique
{
pass
{
lighting off
cull_hardware none
cull_software none
depth_check off
polygon_mode_overrideable false
texture_unit
{
filtering none
}
}
}
}
C++:
Code: Select all
class CDynamicResolution
{
public:
float m_lastRenderScaleValue;
clock_t m_lastTime;
int m_updateCounter;
bool m_active;
bool m_compositorAdded;
int m_dynamicResolution;
Camera* m_camera;
RenderWindow* m_window;
// Constructor for the CDynamicResolution
CDynamicResolution(Camera* camera, RenderWindow* window)
{
// Get the camera
m_camera = camera;
// Get the window
m_window = window;
// Reset the last render scale value
m_lastRenderScaleValue = 1.0f;
// Reset the last time
m_lastTime = clock();
// Reset the update counter
m_updateCounter = 0;
// Set that we are not active
m_active = false;
// Add the compositor to the main camera
m_compositorAdded = CompositorManager::getSingleton().addCompositor(m_camera->getViewport(), "DynamicResolution", 0) != NULL;
// Reset the dynamic resolution option
m_dynamicResolution = 0;
}
// Destructor for the CDynamicResolution
~CDynamicResolution()
{
// Check if the current validated effect is a valid compositor
if (m_compositorAdded && CompositorManager::getSingleton().getByName("DynamicResolution"))
// Remove the current compositor
CompositorManager::getSingleton().removeCompositor(m_camera->getViewport(), "DynamicResolution");
}
// Updates the CDynamicResolutionManager
void Update()
{
// Check if we are using the dynamic resolution option
if (m_dynamicResolution > 0)
// Set that we are active
m_active = true;
// Check if we are not active
if (!m_active)
// Return the function, we are done
return;
// Add one to the number of updates
m_updateCounter++;
// Check if enough time has elapsed
int tmpFPS = 0;
clock_t tmpCurrentTime = clock();
const clock_t tmpWaitTime = 100;
if (tmpCurrentTime - m_lastTime > tmpWaitTime)
{
// Calculate the FPS
tmpFPS = int(float(m_updateCounter) / (float(tmpWaitTime) * 0.001f));
// Reset the last time
m_lastTime = tmpCurrentTime;
// Reset the update counter
m_updateCounter = 0;
}
else
// Return the function, we are done
return;
// Set the current render scale value
float tmpCurrentRenderScaleValue = m_lastRenderScaleValue;
// Check if we are using dynamic resolution
if (m_dynamicResolution > 0)
{
// Check if the FPS is far off from the wanted FPS
float tmpPercentageOff = float(min(tmpFPS, m_dynamicResolution)) / float(max(tmpFPS, m_dynamicResolution));
if (tmpPercentageOff < 0.8f) // 47 / 60 = 0.78, so this will then alter the render scale
{
// Check if the FPS is lower than the wanted FPS
if (tmpFPS < m_dynamicResolution)
// Make the render scale lower
tmpCurrentRenderScaleValue = m_lastRenderScaleValue * 0.8f;
else
// Make the render scale higher
tmpCurrentRenderScaleValue = m_lastRenderScaleValue * 1.1f;
}
}
else
// Set the render scale value to its maximum value
tmpCurrentRenderScaleValue = 1.0f;
// Limit the render scale
tmpCurrentRenderScaleValue = max(tmpCurrentRenderScaleValue, 0.2f);
tmpCurrentRenderScaleValue = min(tmpCurrentRenderScaleValue, 1.0f);
// Check if the render scale value has changed
if (m_lastRenderScaleValue != tmpCurrentRenderScaleValue)
{
// Set the new last render scale value value
bool tmpOldUseCompositor = m_lastRenderScaleValue != 1.0f;
m_lastRenderScaleValue = tmpCurrentRenderScaleValue;
// Check if we have changed the compositor target
bool tmpUseCompositor = m_lastRenderScaleValue != 1.0f;
if (tmpUseCompositor != tmpOldUseCompositor)
// Enable/disable the compositor
CompositorManager::getSingleton().setCompositorEnabled(m_camera->getViewport(), "DynamicResolution", tmpUseCompositor);
// Check if we are using the compositor
if (tmpUseCompositor)
{
// Get the compositor chain from the camera and check if it is valid
CompositorChain* tmpCompositorChain = CompositorManager::getSingleton().getCompositorChain(m_camera->getViewport());
if (tmpCompositorChain)
{
// Get the compositor instance and check if it is valid
CompositorInstance* tmpCompositorInstance = tmpCompositorChain->getCompositor("DynamicResolution");
if (tmpCompositorInstance)
{
// Get the compositor technique and check if it is valid
CompositionTechnique* tmpCompositorTechnique = tmpCompositorInstance->getTechnique();
if (tmpCompositorTechnique)
{
// Get the scene texture definition and check if it is valid
CompositionTechnique::TextureDefinition* tmpTextureDefinition = tmpCompositorTechnique->getTextureDefinition("scene");
if (tmpTextureDefinition)
{
// Update the compositor render scale
tmpTextureDefinition->width = size_t(float(m_window->getWidth()) * m_lastRenderScaleValue);
tmpTextureDefinition->height = size_t(float(m_window->getHeight()) * m_lastRenderScaleValue);
// Adjust the pixels to become as close to the wanted aspect ratio of the window
const int tmpMinMaxValue = 10;
if (tmpTextureDefinition->width > tmpMinMaxValue &&
tmpTextureDefinition->height > tmpMinMaxValue)
{
//float tmpBeforeAspectRatio = float(tmpTextureDefinition->width) / float(tmpTextureDefinition->height);
float tmpWantedAspectRatio = float(m_window->getWidth()) / float(m_window->getHeight());
float tmpClosest = FLT_MAX;
int tmpClosestX = 0;
int tmpClosestY = 0;
for (int x = -tmpMinMaxValue; x <= tmpMinMaxValue; x++)
{
for (int y = -tmpMinMaxValue; y <= tmpMinMaxValue; y++)
{
float tmpCurrentAspectRatio = float(tmpTextureDefinition->width + x) / float(tmpTextureDefinition->height + y);
float tmpDistanceCurrent = abs(tmpWantedAspectRatio - tmpCurrentAspectRatio);
if (tmpDistanceCurrent < tmpClosest)
{
tmpClosest = tmpDistanceCurrent;
tmpClosestX = x;
tmpClosestY = y;
}
}
}
if (tmpClosest != FLT_MAX)
{
tmpTextureDefinition->width += tmpClosestX;
tmpTextureDefinition->height += tmpClosestY;
}
}
// Make sure the textures are created
tmpCompositorInstance->setAlive(false);
tmpCompositorInstance->setAlive(true);
tmpCompositorInstance->setEnabled(true);
}
}
}
}
}
else
// Set that we are not active
m_active = false;
}
}
};