[Solved] D3D output in a Qt widget?
-
Hi all,
I am developing a real-time 3d editing system. For some reason, I have to use D3D as the 3D api, and I would like to use Qt as the UI. I would like to know if there is any tutorial on how to set up Qt and Direct3D such that D3D will put its rendering output into a Qt widget as soon as it finishes rendering one frame. Note that I am not asking about getting the QPainter support of D3D back. Details of the solution would be highly appreciated as I am a newbie to Qt. I googled a bit and found some older posts which are quite frustrating for me. Many thanks for your help in advance!
-
I don't know anything about D3D so it is just an idea... Since Qt supports native window on Windows, wouldn't it be possible to create a new window with D3D, and reparent it to a Qt Widget?
The VLC player do some interesting things similar to that. The surface where the movie is rendered is not rendered by Qt (obviously :)), but a Qt widgets is parented to that surface.
-
AFAIK there are some tutorials around where the paintEvent() is null-implemented and a custom paint action is defined by the new widget. That way you should be able to create widgets that have d3d rendering. Maybe "this qt-interest mailing":http://lists.trolltech.com/qt-interest/2006-05/thread00316-0.html or "this forum thread":http://stackoverflow.com/questions/1641286/using-qt-with-directx will help you there if Benjamin's suggestion doesn't work out for you.
-
Thanks for your suggestion, Franzk. I ended up the following solution without going too deep into Qt mechanism.
Basically, I have set up a background thread to do the D3D rendering to render the scene into a texture, whenever a change is made to the scene. Then I derived a custom widget from QFrame to display the resultant texture. Using a timer, the main thread checks frequently whether the background rendering is done. If the rendering is done and the result has not been updated, the main thread read in the texture and display it in the customized QFrame widget. This is definitely not the optimal solution for a, say, real-time FPS game, due to the latency between finishing the rendering in the background, and displaying the final result in the widget (I have not tested the actual latency, though I guess it should not be too big). Nevertheless, it suffices in my case of interactive material editing. Hope this solution would be helpful to anyone doing a similar job.
-
@gpgpu: I am trying to do the same thing, I've been using Qt+GL for a long time and due to some constraints I am trying to do D3D rendering inside a Qt window. A couple of quick questions:
-> When you say you rendered a D3D scene into a texture, did you mean you rendered into D3D scene into an OpenGL texture?
-> And, for rendering the texture did you have to turn on any special flags or anything specific?
Any references or code samples are appreciated.
Thank you. -
Hi blueskin,
I just set the render target of the graphics pipeline in D3D to a D3D texture (so-called render-to-texture). I don't think I changed any flags. Below please see the code of my custom widget, which takes in a QImage (converted from the D3D texture), and display it on the screen.
@ class QImgBox : public QFrame
{
Q_OBJECTpublic:
QImgBox(QWidget *parent = 0, const int w = QIMGBOX_DEFAULT_W, const int h = QIMGBOX_DEFAULT_H);
void set_pixmap(const QImage &img);public slots:
protected:
void paintEvent(QPaintEvent *event);private:
void refreshPixmap();
QPixmap pixmap;
};@@QImgBox::QImgBox(QWidget *parent, const int w, const int h)
: QFrame(parent), pball(NULL), b_dragging(false), b_zooming(false)
{
setBackgroundRole(QPalette::Dark);
setAutoFillBackground(false);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setMinimumSize(w, h);
setMaximumSize(w, h);
setFocusPolicy(Qt::StrongFocus);pixmap = QPixmap(size());
pixmap.fill(this, 0, 0);
}void QImgBox::paintEvent(QPaintEvent *event)
{
QStylePainter painter(this);
painter.drawPixmap(0, 0, pixmap);QFrame::paintEvent(event);
}void QImgBox::refreshPixmap()
{
QPainter painter(&pixmap);
painter.initFrom(this);
update();
}void QImgBox::set_pixmap(const QImage &img)
{
pixmap = QPixmap::fromImage(img);
refreshPixmap();
}
@[quote author="blueskin" date="1302205650"]@gpgpu: I am trying to do the same thing, I've been using Qt+GL for a long time and due to some constraints I am trying to do D3D rendering inside a Qt window. A couple of quick questions:
-> When you say you rendered a D3D scene into a texture, did you mean you rendered into D3D scene into an OpenGL texture?
-> And, for rendering the texture did you have to turn on any special flags or anything specific?
Any references or code samples are appreciated.
Thank you.[/quote] -
Hey gpgpu, Thanks for your prompt reply. But I am actually looking for something different and I figured it out.
@
-> Create a QWidget
-> Override paintEngine() method, does nothing, just returns NULL
-> Assign HWND to widget->winId()#ifdef USE_QTGUI QApplication a(argc, argv); CD3DWidget wndw; wndw.show(); wndw.resize(1280,960); hWnd = wndw.winId(); #else hWnd = CreateAppWindow(name,300,300); #endif //CD3DWidget class contains only the following definitions CD3DWidget::CD3DWidget(QWidget * parent):QWidget(parent){ } QPaintEngine *CD3DWidget::paintEngine (){ return NULL; }
@
I also posted here
http://stackoverflow.com/questions/1641286/using-qt-with-directx/5595356#5595356