Procedural texture


#1

Hello! I’m trying to create a texture by means of simple post-processing effect on the auxiliary viewport. Here’s the code

SharedPtr<Texture2D> Game::CreateTexture(int width, int height)
{
    //Get the Resource Cache subsystem
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    
    SharedPtr<Texture2D> renderTexture(new Texture2D(context_));
    renderTexture->SetSize(width, height, Graphics::GetRGBFormat(), TEXTURE_RENDERTARGET);
    renderTexture->SetFilterMode(FILTER_BILINEAR);

    // Create the scene which will be rendered to a texture
    rttScene_ = new Scene(context_);
    
    // Create a camera for the render-to-texture scene.
    rttCameraNode_ = rttScene_->CreateChild("Camera");
    auto* rttCamera = rttCameraNode_->CreateComponent<Camera>();

    RenderSurface* surface = renderTexture->GetRenderSurface();
    SharedPtr<Viewport> rttViewport(new Viewport(context_, rttScene_, rttCameraNode_->GetComponent<Camera>()));
    surface->SetViewport(0, rttViewport);

    SharedPtr<RenderPath> effectRenderPath = rttViewport->GetRenderPath()->Clone();
    effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/BasicPP.xml"));
    rttViewport->SetRenderPath(effectRenderPath);

    surface->QueueUpdate();

    return renderTexture;
}

I’ve created BasicPP.xml and the corresponding BasicPP.glsl which creates a simple gradient by using gl_FragColor. The effect is working as expected on the main viewport. Also, when I attach a .png texture to my sprite, it gets shown on the screen.

So what am I missing?


#2

What results do you get and how do they not match up with your expectations?


#3

For a 128x128 texture I get a black rectangle. I render the effect on the renderer’s viewport to be sure that it’s working, so I’m expecting to see a mini-version of the background where the black 128x128 rectangle is.

If I don’t set size with sprite->SetSize(IntVector2(128, 128)); I don’t get anything… Just a background with a post processing gradient. So, obviously, the post-processing effect is not rendered on the created texture.


#4

I think you may need to add an octree to the scene, possibly also a zone.


#5

The Renderer has a default Zone (which can be accessed and modified through GetSubsystem<Renderer>()->GetDefaultZone()) so that should not be the problem.
Indeed the Scene does not seems to have an Octree component added. @Lunarovich Your program should output an error about this to the console/terminal/IDE (if it contains Drawables).

ERROR: No Octree component in scene, drawable will not render


#6

Thanx. I’ll try the solution and inform about the results.


#7

Your intent seems to be to use - the currently unused - auto* rttCamera here, btw. This should not be causing any trouble, though.


#8

Is single shader all you want to draw into this texture? Or you also want to draw some 3d geometry there? If first, you don’t really need a scene, viewport, camera and all that stuff. You can draw a quad right into render target.

here is the code for that:

Graphics* graphics = context_->GetSubsystem<Graphics>();
graphics->SetClipPlane(false);
graphics->SetScissorTest(false);
graphics->SetStencilTest(false);
graphics->SetDepthWrite(false);
graphics->SetDepthTest(CMP_ALWAYS);
graphics->SetCullMode(CULL_NONE);
graphics->SetFillMode(FILL_SOLID);
graphics->SetBlendMode(BLEND_REPLACE);
graphics->ResetRenderTargets();
graphics->ClearTransformSources();

WeakPtr<Texture2D> renderTarget(renderTexture);

graphics->SetRenderTarget(0, renderTarget);
graphics->SetViewport(IntRect(0, 0, TEX_X, TEX_Y));
graphics->Clear(CLEAR_COLOR, Color(9e99, 0.0f, 0.0f, 0.0f));
ShaderVariation* vs = graphics->GetShader(VS, "SdfCalculator" );
ShaderVariation* ps = graphics->GetShader(PS, "SdfCalculator", this->GetDefines());
graphics->SetShaders(vs, ps);

Matrix3x4 modelMatrix = Matrix3x4::IDENTITY;
modelMatrix.m23_ = 0.0f;
graphics->SetShaderParameter(VSP_MODEL, modelMatrix);
graphics->SetShaderParameter(VSP_VIEWPROJ, Matrix4::IDENTITY);

graphics->SetTexture(TU_DIFFUSE, upldTexture);
Renderer* renderer = context_->GetSubsystem<Renderer>();
Geometry* geometry = renderer->GetQuadGeometry();
geometry->Draw(graphics);