|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Grafica di base sotto windows
salve a tutti,
ho bisogno di un piccolo aiutino e spero che voi mi possiate aiutare. Ho del mio vecchio codice dos che si occupava di rasterizzare poligoni in 3d sullo schermo in modalità vesa in più risoluzioni, a 16 e 32 bpp. Ora avrei bisogno di un porting quanto più diretto in windows. Non mi serve la grafica accelerata in d3d o opengl, nè voglio usare librerie particolari o peggio di terzi tipo sdl e simili; solo ciò che le librerie windows di base (e sottolineo base) offrono per: -inizializzare una finestra windowed o fullscreen -accendere un pixel a 16 o 32 bit -ottenere informazioni sullo stato corrente della finestra (bpp, windowed/fullscreen, risoluzione corrente...) ad es. per aggiornare automaticamente in caso di resize della finestra -utilizzare gli eventuali strumenti messi a disposizione per questa finestra tipo double buffering (posso benissimo farlo io, ma se c'é già...) -quanto altro mi possa servire vi venga in mente per questo lavoro Prego chiunque possa darmi dei consigli o possa indirizzarmi verso qualche link di scrivere due righe, mi servono solo le cose di base perché non ho molto tempo. Perdonatemi nel caso qualcuno abbia già postato domande del genere, ma mi sembrava un po' complessa come domanda per una ricerca nel forum. Grazie in anticipo! |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
In Windows non hai l'accesso diretto alla memoria video. Se poi già dici che vuoi evitare direct-draw, direct-3d, opengl, e compagnia bella ... ti tranci via pure tutto quello che comunque ti avrebbe avvantaggiato e di molto! Tu chiedi come inizializzare una finestra windowed o fullscreen. Una finestra "classica" (con barra titolo, ecc...) ad aprirla non ci sono grossi problemi, il fatto è che non so cosa potresti ricavarci. In Windows la gestione dell'interfaccia grafica è fatta ad "eventi", non sei tu che decidi quando disegnare sulla finestra ma il sistema. Tu puoi solo rispondere agli eventi. In DOS invece si faceva quello che si voleva e quando si voleva, avevi il controllo completo di tutto. In più in una finestra normale, puoi certamente disegnarci sopra ma non a basso livello. Accederci pixel per pixel mi sembra che sia possibile ma credo che sarebbe una palla ... Dici anche una finestra fullscreen ... ma in modalità esclusiva o no??? Per avere la modalità esclusiva serve direct-draw, altrimenti fare una semplice finestra full-screen, torniamo al caso precedente. Insomma fare un porting di un programma di grafica dal DOS al Windows la vedo dura senza utilizzare qualcosa che ti semplifica e velocizza la gestione della grafica!!
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Perdona la mia ignoranza, ma non dovrebbe esserci comunque un sistema per
inizializzare e disegnare in una finestra senza utilizzare directdraw? io so di qualcosa tipo wingdi o windib ora non ricordo che si occupa della grafica di windows di base, nel senso ad es. che con visual studio non hai bisogno di richiamare headers directx o opengl o sdl ma semplicemente le librerie di default che escono con il compilatore fresco installato; qualcosa del genere dovrebbe essere anche disponibile con il dev-c++, che è la piattaforma che alla fine vorrei usare. |
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Se vuoi posso anche postarti del codice per creare una semplice finestra vuota. Ma devi comunque capire la gestione degli eventi in Windows (se non la conosci già ovviamente).
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#5 | |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Quote:
Ogni aiuto sarà molto apprezzato. |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Codice:
#define STRICT
#include <windows.h>
#define MAIN_WNDCLASS "MiaClasseFinestra"
LRESULT CALLBACK Main_WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
return 0;
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint (hWnd, &ps);
EndPaint (hWnd, &ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage (0);
return 0;
case WM_CLOSE:
DestroyWindow (hWnd);
return 0;
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
INT APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpszCmdLine, INT iCmdShow)
{
WNDCLASSEX wcx;
HWND hWnd;
MSG msg;
wcx.cbSize = sizeof (wcx);
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = (WNDPROC) Main_WndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = NULL;
wcx.hIconSm = NULL;
wcx.hCursor = LoadCursor (NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = MAIN_WNDCLASS;
if (!RegisterClassEx (&wcx))
{
MessageBox (NULL, "Errore nella registrazione della classe",
"ERRORE", MB_OK | MB_ICONEXCLAMATION);
return 1;
}
hWnd = CreateWindow (MAIN_WNDCLASS, "Titolo finestra", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 300, 300,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL)
{
MessageBox (NULL, "Errore nella creazione della finestra",
"ERRORE", MB_OK | MB_ICONEXCLAMATION);
return 1;
}
ShowWindow (hWnd, SW_SHOWNORMAL);
UpdateWindow (hWnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return 0;
}
I passi per creare una semplice finestra sono: - Creare una window-procedure, cioè la funzione che riceverà gli eventi relativi alla finestra (nel codice sopra è la funzione Main_WndProc). - Creare una nuova classe di finestra (con RegisterClassEx). - Creare una nuova finestra (con CreateWindow). - Gestire il loop dei messaggi (con while (GetMessage .....ecc...). Se c'è qualcosa che non ti è chiaro, chiedi pure.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#7 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Ti ringrazio per tutto l'aiuto fornito (e per la pazienza!)
Appena ho un po' di tempo vedo di studiarmi qualche manuale di programmazione in windows, credo proprio di averne bisogno. Comunque il codice è abbastanza chiaro e qualche piccola(issima) applicazione windows l'ho già fatta in passato quindi non dovrei avere grossi problemi a capire il codice che mi hai gentilmente fornito. Ciao e grazie ancora! |
|
|
|
|
|
#8 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Ciao,
perdonate l'insistenza, volevo chiedere ancora qualcosa. Premesso che non ho avuto problemi con in codice di cui sopra, avrei ora bisogno di far convergere gli strumenti a disposizione con le mie esigenze. Non mi è necessario imparare per ora tutta l'architettura software di windows, solo alcuni metodi per ottenere strettamente ciò che al momento mi occorre. A chiunque possa interessare, in pratica ho bisogno di mostrare un vecchio lavoro fatto anni fa per dos, su macchine moderne windows, che naturalmente non supportano più molte delle applicazioni grafiche dell'epoca. Mi è assolutamente indispensabile ridurre al minimo il numero di cambiamenti apportati al codice originale e utilizzare al minimo strumenti e librerie esterne. Dunque, poniamoci nel caso che il mio programma disegni in un buffer in memoria un'immagine frutto di una elaborazione, come faccio a dire a windows di riversare il tutto nella finestra sullo schermo? (in maniera sufficientemente performante dato che si tratta di aggiornare svariate frame al secondo)? Altra cosa: se ridimensiono al volo o massimizzo la finestra come ottengo la nuova risoluzione e come aggiorno con continuità l'output del programma su video? Ringrazio anticipatamente e mi scuso per la (relativa) banalità delle mie domande (anche per quelle nuove che probabilmente farò in futuro). |
|
|
|
|
|
#9 | |||||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Quote:
Quote:
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX Se invece ti va bene una finestra ridimensionabile, ad ogni ridimensionamento, la window-procedure riceve il messaggio WM_SIZE, che "informa" della nuova dimensione. Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|||||
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Innanzitutto grazie per la rapida risposta.
Cercherò sinteticamente di risolvere gli ultimi dettagli Uso dev-c++ e visual studio, dipende dalla macchina sulla quale mi trovo. Il mio programma è un semplice engine 3d; in sintesi carica un oggetto .3ds dal disco e lo renderizza sullo schermo in realtime ed io posso spostarlo e ruotarlo con la tastiera (anche con il mouse ma non è necessario per il momento...). Lavora in modalità vesa a 32 bit con le relative risoluzioni previste (640, 800...). Funziona sia in modalità double buffering (render in un buffer e riversamento nella mem video) che in page flipping (disegna in una zona della mem video mentre mostra l'altra, poi le scambia). A me basta il primo metodo, l'importante che vada abbastanza spedito...) A me serve che il rispettivo programma windows faccia più o meno lo stesso, non è affatto necessario che rispetti le risoluzioni originali, basta che funzioni correttamente. Grazie ancora per il tempo dedicatomi! |
|
|
|
|
|
#11 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Piccolo aggiornamento:
ho trovato questo codice (vedere in fondo alla pagina per i sorgenti), peraltro molto chiaro e che compila su miriadi di piattaforme che fa in opengl esattamente ciò che io voglio fare in software. In pratica è già tutto settato, solo che ad occuparsi del rendering è opengl. Non ne sono sicuro, ma forse se potessi accedere direttamente al buffer che poi viene swappato con SwapBuffers(hDC), dovrei semplicemente rimuovere ogni riferimento ad opengl e metterci poi il mio renderer. Sto trascurando qualcosa? |
|
|
|
|
|
#12 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
fidati, ti conviene usare OpenGL, se non addirittura Direct3D... |
|
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Ma da quello che ho capito, kekk0 non vuole usare librerie esterne.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#14 | |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Quote:
|
|
|
|
|
|
|
#15 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Tu dici che hai già un tuo software che renderizza gli oggetti 3D, se ho capito bene, e quindi non hai bisogno di OpenGL, Direct-3D e simili (perché farebbero in sostanza la stessa cosa che hai già fatto tu). Dal tuo software, sempre se ho capito bene, "esce" una mappa di pixel ed è quella che vorresti visualizzare direttamente in Windows. Bene, la libreria SDL ti permette di "disegnare" su una superficie in modo abbastanza semplice, veloce e performante. Ecco cosa dice l'introduzione della SDL per il Video: * Set a video mode at any depth (8-bpp or greater) with optional conversion, if the video mode is not supported by the hardware.Pensi che possa fare al caso tuo? Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#16 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
ad ogni modo credo che nella GDI quello che faccia di più al caso tuo siano le DIB Sections, ovvero bitmap di cui hai accesso diretto ai pixel di memoria (scordati SetPixel che è troppo lenta); trattandosi di bitmap ai quali hai accesso diretto però non possono essere selezionati in un DC associato ad una finestra (ottenuto cioè con GetDC): il DC deve essere per forza un Memory Device Context e lo puoi usare per realizzare il double buffering facendo periodicamente un BitBlt da questo Memory DC a quello della finestra. recapitolando: 1) ti salvi in una variabile un handle al DC della tua finestra (GetDC) 2) crei un Memory DC (CreateCompatibleDC, e lo fai compatibile al display) 3) crei una DIB Section (CreateDIBSection) 4) selezioni la DIB Section nel Memory DC (SelectObject) 5) costruisci il tuo frame accedendo direttamente alla memoria della DIB Section, in cui troverai i pixels nel formato secondo il quale hai creato la DIB Section 6) quando hai costruito un frame fai BitBlt col Memory DC come sorgente e il DC della finestra come destinazione inoltre ti consiglio di implementarlo con due thread in modo tale da sfruttare eventualmente le architetture multicore: il codice che costruisce i frames (cioè che fa il rendering vero e proprio) fallo in un thread a parte; tutto il resto nel thread primario. Ultima modifica di 71104 : 03-04-2006 alle 22:48. |
|
|
|
|
|
|
#17 | ||
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
Quote:
Quote:
Comunque ti ringrazio per le tue informazioni; cercherò di seguirle e di (finalmente) portare a termine questo progetto (tra l'altro lavorandoci 10 minuti al giorno causa lavoro...) |
||
|
|
|
|
|
#18 | |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
ciao a tutti!
Quote:
non è che mi faresti un piccolo esempio di codice come ha fatto andrea? non c'è fretta e se ti scocci non lo fare, non fa niente! grazie in ogni caso! non è |
|
|
|
|
|
|
#19 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
- CreateCompatibleDC per creare un Memory DC - GetDC per ottenere un handle a quello della tua finestra - CreateDIBSection per creare un bitmap di cui hai un puntatore ai dati, che puoi modificare direttamente (occhio al formato) - SelectObject per selezionare la DIB section nel Memory DC (quello creato con CreateCompatibleDC) - BitBlt per copiare velocemente il contenuto di un DC a un altro; usala per copiare il contenuto della DIB section nel DC della finestra - oppure in alternativa all'ultima, StretchBlt, che fa la stessa cosa ma con la possibilità di stretching dell'immagine (solo ortogonale però, niente deformazioni a trapezio) spero di esserti stato utile, ciao. Ultima modifica di 71104 : 16-04-2006 alle 13:44. |
|
|
|
|
|
|
#20 |
|
Member
Iscritto dal: Feb 2006
Messaggi: 163
|
grazie per la gentilezza, sei stato più che utile
ciao! |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 04:09.



















