Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Derive from RenderTarget - override Draw() method  (Read 2163 times)

0 Members and 1 Guest are viewing this topic.

Vincentus

  • Newbie
  • *
  • Posts: 5
    • View Profile
    • Email
Derive from RenderTarget - override Draw() method
« on: November 11, 2013, 04:04:40 pm »
Hi SFML-Community

I want to realize a BigRenderTexture class that overcomes the hardware dependent maximum texture size limit and behaves just like every other RenderTarget in SFML, in order to Draw all the SFML-Drawables.

I'm stuck at the point where the neat SFML "reverse" draw syntax is realized. Meaning the Interaction between Drawable and RenderTarget. My class derives from RenderTarget so that all Drawables accept it for drawing. But because Drawable and RenderTarget uses the Friend-Concept (not inheritable) AND the "Draw(vertices ...)"-method of RenderTarget is not overrideable I don't see a solution without changing the SFML implementation.

edit: I put this question in Help because I wasn't sure if it is a feature request or I'm just missing something
If I'm overseeing a simple solution, could someone point it out for me please? If not, then I'm suggesting to change the draw methods of RenderTarget to virtual. Or somehow get rid of the Friend-Concept solution - not sure how  ;)

Thanks,
Vinc
« Last Edit: November 11, 2013, 04:23:43 pm by Vincentus »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #1 on: November 11, 2013, 06:23:49 pm »
The two render-targets implemented in SFML implement drawing in a generic way -- there's nothing specific to them, only standard OpenGL code. I'm not going to put the draw functions virtual just because you have decided to create a new render-target that cannot use the standard drawing code ;)

So yes you're right, you'll have to find a workaround. You can't do it directly with the sf::RenderTarget API.
« Last Edit: November 11, 2013, 06:28:35 pm by Laurent »
Laurent Gomila - SFML developer

Vincentus

  • Newbie
  • *
  • Posts: 5
    • View Profile
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #2 on: November 12, 2013, 01:13:08 pm »
As it seems that I'm the first and probably the only one who would like to extend SFML in that way, you are right to spare the virtual overhead.  Draw is after all a very often called method, that could make the small performance loss through indirection countable.
I'm going to find some workaround that serves my needs, and stay with it then.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #3 on: November 12, 2013, 01:29:32 pm »
Quote
As it seems that I'm the first and probably the only one who would like to extend SFML in that way, you are right to spare the virtual overhead.  Draw is after all a very often called method, that could make the small performance loss through indirection countable.
To be honest, I don't care at all about performances. I doubt this would make a significant difference. My main concern here is rather about the design ;)
Laurent Gomila - SFML developer

Vincentus

  • Newbie
  • *
  • Posts: 5
    • View Profile
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #4 on: November 12, 2013, 02:19:54 pm »
To be honest, I don't care at all about performances. I doubt this would make a significant difference. My main concern here is rather about the design ;)

I can't see why it would be a bad design to allow for user defined RenderTarget specializations, that are fully interface compatible with the rest of SFML - if you cut out the performance aspect. But I'm not that experienced, so I have to ask you why :) Because from my point of view it would be a good design if I could implement a BigRenderTexture that behaves just like a RenderTexture from the outside.

Or consider another question if you have some spare time and interest ;) : What do you consider is the best way of realizing such a BigRenderTexture if you want it to be able to draw all SFML Drawables in the current SFML state? Without touching the SFML implementation, if even possible.

My approach was to simply derive from RenderTarget and use an Array of RenderTextures to redirect the draw call to, corresponding to the draw position of the Drawables. The draw position is however not known until the specific draw call. (The one that is called from the Drawable to the RenderTarget)


zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #5 on: November 12, 2013, 02:28:29 pm »
I have implemented a LargeRenderTexture in NetEXT using C#. You can find my drawing code here.

The way I handled drawing was that I created an array of RenderTextures and then in the draw code I simply translated the current render state's transform according to the offset of each RenderTexture before drawing.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Vincentus

  • Newbie
  • *
  • Posts: 5
    • View Profile
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #6 on: November 12, 2013, 02:59:54 pm »
aah ok, I didn't come to this solution because my brain wanted to prevent drawing to all RenderTextures :). In my code I previously evaluate on which RenderTextures the Drawable could be visible on and only draw it to those. But if you just draw it to all RenderTextures of the BigRenderTexture your approach works nicely. Considering that the maxTextureSize most likely won't be very small for most machines, it is also obvious that there won't be much overhead from simply drawing to all RenderTextures.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #7 on: November 12, 2013, 03:07:14 pm »
Drawing to all sub-render-texures just removes the complexity of calculating where the entity is drawn, it doesn't solve the design problem. Note that SFML.Net is a special case, all functions are virtual (RenderTarget is an interface) because of implementation constraints -- it is based on the C binding.
Laurent Gomila - SFML developer

Vincentus

  • Newbie
  • *
  • Posts: 5
    • View Profile
    • Email
Re: Derive from RenderTarget - override Draw() method
« Reply #8 on: November 15, 2013, 01:44:48 pm »
Drawing to all sub-render-texures just removes the complexity of calculating where the entity is drawn, it doesn't solve the design problem. Note that SFML.Net is a special case, all functions are virtual (RenderTarget is an interface) because of implementation constraints -- it is based on the C binding.

You are right, the design Problem is still there, but it is a functional workaround that doesn't require to change anything on the SFML side. Additionally you want to reuse the draw-capabilities of RenderTexture and not reimplement the whole thing on OpenGL-Level. But even if you wanted to do that the SFML implementation and the current coupling of RenderTarget and Drawable won't allow you that. But maybe I misunderstood what you meant.  :)

The solution now is to Derive the BigRenderTexture from the RenderTarget-Interface. Implement the pure virtual methods and hide the original Draw(drawable...) implementation of RenderTarget. It then behaves just like the RenderTexture from the outside. Note that it is not possible to do the same with the Draw(vertices...) method.

The draw methods looks as follows:
void BigRenderTexture::draw(const sf::Drawable& drawable, const sf::RenderStates& states)
{
        sf::RenderStates statesTmp = states;
        sf::Transform transform = statesTmp.transform;
        for (unsigned int i = 0; i < mRenderTextures.size(); i++)
        {
                //                                                                               Xindex                                                                   Yindex
                statesTmp.transform.translate( -1 * float(((i % mTableSize.x)) * mTextureMaxSize) , -1 * float(((i / mTableSize.x)) * mTextureMaxSize));
                mRenderTextures[i]->draw(drawable, statesTmp);
        }
}