Anfang mit 3D-Grafik.Programmierung

Cody86

Grünschnabel
Hallo alle zusammen!

Ich hab mir vor einiger Zeit das Buch "3d-Grafik-Programmierung" von Marius Apetri gekauft. Dieses Buch fängt wirklich beim Urschleim an (also so, wie es sein soll), d.h. das erste kleine Programm soll nichts weiter tun, als in einem kleinen Fenster spaltenweise die Pixel entsprechend der Farbpalette bunt zu färben und nach Tastendruck durch den Benutzer das Fenster wieder zu schließen.
Doch es kam, wie es kommen musste: es geht natürlich nicht!

Alles was passiert, ist, dass der Bildschirm kurz schwarz wird und dann schließt sich das Fenster auch schon wieder.

Hier ist das Programm:

Code:
#include <windows.h>
#include "s2_1.h"

uchar handle_input( MSG *msg );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow )
{
  surface.open_window( hInstance, 320, 200, 8 );
  
  uchar *screen = (uchar *) surface.get_screen_pointer();

  for( long x=0 ; x<256 ; x++ )
     for( long y=0 ; y<200 ; y++ )
        screen[ y * 320 + x ] = x;
    
  surface.release_screen_pointer();
    
  MSG message;
  while( !handle_input( &message ) );

  return message.wParam;
}

uchar handle_input( MSG *msg )
{
  if( PeekMessage( msg, NULL, 0, 0, PM_REMOVE ) )
  {
    if( msg->message == WM_QUIT || msg->message == WM_KEYDOWN ) return 1;
   
    TranslateMessage( msg );
    DispatchMessage( msg );    
  }
  return 0;
}

Ich weiß schon so viel, dass es an der Zeile 14 "screen[ y * 320 + x ] = x;" liegt, also quasi an der Manipulation des Videospeichers, denn wenn ich diese Zeile auskommentiere, dann wird der Bildschirm schwarz (das wird wohl das Fenster sein, welches erzeugt wird) und das Programm wartet drauf, dass ich eine Taste drücke.

Das Rahmenprogramm funktioniert also, aber warum geht das mit dem Einfärben nicht?

Doof ist auch, sämtliche Beispiel-Programme sind ja auch als fertige .exe-Dateien mit auf der Buch-CD, nur passiert dort dasselbe!

Hier sind noch die beiden Header-Dateien:

Code:
#ifndef SURFACE_H
#define SURFACE_H

#include <windows.h>
#include <stdlib.h>    // exit()
#include <string.h>    // memset(), memmove()
#include <ddraw.h>

#include "st2_1.h"     // pixel_8

#define WIN32_LEAN_AND_MEAN

#define x_res surface.get_x_resolution()
#define y_res surface.get_y_resolution()

void exit( char *message );

LRESULT CALLBACK main_window_procedure( HWND main_window_handle, UINT message, WPARAM wparam, LPARAM lparam )
{
  switch( message )
  {	
    case WM_CLOSE : PostQuitMessage( 0 );
    		    return 0;
  }
  
  return DefWindowProc( main_window_handle, message, wparam, lparam );
}

class directx_surface
{
  private:
    long x_resolution, y_resolution;

    LPDIRECTDRAW main_dd_object;
    LPDIRECTDRAWSURFACE primary_surface;
    DDSURFACEDESC surface_description;
    HWND main_window_handle;
    
    void initialise_direct_draw( long x, long y, long bit_depth );

  public:
    long get_x_resolution( void ) {  return x_resolution;  }
    long get_y_resolution( void ) {  return y_resolution;  }

    void open_window( HINSTANCE hInstance, long x, long y, long bit_depth );
    void close_window( void );

    void set_palette( pixel_8 *colors );

    void *get_screen_pointer( void );
    void release_screen_pointer( void ) {  primary_surface->Unlock( surface_description.lpSurface );  }

    directx_surface( void ) : main_dd_object( NULL ), primary_surface( NULL ), main_window_handle( NULL ),
                              x_resolution( 0 ), y_resolution( 0 ) { }
   ~directx_surface( void ) {  close_window();  }
} surface;

void directx_surface::initialise_direct_draw( long x, long y, long bit_depth )
{
  if( DirectDrawCreate( NULL, &main_dd_object, NULL ) != DD_OK )
    exit( "Fehler während der Ausführung von DirectDrawCreate().\n" );

  if( main_dd_object->SetCooperativeLevel( main_window_handle, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN |
                                           DDSCL_ALLOWMODEX ) != DD_OK )
    exit( "Fehler während der Ausführung von SetCooperativeLevel().\n" );

  if( main_dd_object->SetDisplayMode( x, y, bit_depth ) != DD_OK )
    exit( "Fehler während der Ausführung von SetDisplayMode().\n" );

  memset( &surface_description, 0, sizeof( surface_description ) );
  surface_description.dwSize = sizeof( surface_description );
  surface_description.dwFlags = DDSD_CAPS;
  surface_description.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

  if( main_dd_object->CreateSurface( &surface_description, &primary_surface, NULL ) != DD_OK )
    exit( "Fehler während der Ausführung von CreateSurface().\n" );
}

void directx_surface::open_window( HINSTANCE hInstance, long x, long y, long bit_depth )
{
  x_resolution = x;  y_resolution = y;

  char *class_name = "Main Window";
  WNDCLASS m_window;

  m_window.style = CS_OWNDC;
  m_window.lpfnWndProc = main_window_procedure;
  m_window.cbClsExtra = 0;
  m_window.cbWndExtra = 0;
  m_window.hInstance = hInstance;
  m_window.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  m_window.hCursor = LoadCursor( NULL, IDC_ARROW );
  m_window.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
  m_window.lpszMenuName = NULL;
  m_window.lpszClassName = class_name;
  
  if( RegisterClass( &m_window ) == 0 )
    exit( "Fehler bei der Registrierung des Programmfensters.\n" );

    if( !(main_window_handle = CreateWindowEx( WS_EX_TOPMOST, class_name, "Application", WS_VISIBLE | WS_POPUP, 0,0,
                                               GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ),
                                               NULL, NULL, hInstance, NULL )) )
    exit( "Fehler beim Öffnen des Applikationsfensters.\n" );
 
  ShowCursor( 0 );

  initialise_direct_draw( x_resolution, y_resolution, bit_depth );
}

void directx_surface::close_window( void )
{   
  if( primary_surface )
  {    
    primary_surface->Release();
    primary_surface = NULL;
  }
  	
  if( main_dd_object )
  {
    main_dd_object->Release();
    main_dd_object = NULL;
  }
  
  DestroyWindow( main_window_handle );
}    

void directx_surface::set_palette( pixel_8 *colors )
{
  PALETTEENTRY palette_definition[ 256 ];
  memset( palette_definition, 0, 256*sizeof( PALETTEENTRY ) );

  for( ushort x=0 ; x<256 ; x++ )
  {
    palette_definition[ x ].peRed   = colors[ x ].red;
    palette_definition[ x ].peGreen = colors[ x ].green;
    palette_definition[ x ].peBlue  = colors[ x ].blue;
    palette_definition[ x ].peFlags = PC_NOCOLLAPSE;
  }

  LPDIRECTDRAWPALETTE primary_palette_object = NULL;  
  if( main_dd_object->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_definition, &primary_palette_object,
                                     NULL ) != DD_OK )
    exit( "Fehler während der Ausführung von CreatePalette().\n" );

  if( primary_surface->SetPalette( primary_palette_object ) != DD_OK )
    exit( "Fehler bei der Veränderung der DirectX Palette.\n" );
}

void *directx_surface::get_screen_pointer( void )
{
  primary_surface->Lock( NULL, &surface_description, DDLOCK_SURFACEMEMORYPTR, NULL );

  return surface_description.lpSurface;
}
 
void exit( char *message )
{
  surface.close_window();
  
  ShowCursor( 1 );
  MessageBox( NULL, message, "Fehler:", MB_OK );
  
  exit( 1 );
}

#endif

Code:
#ifndef SIMPLE_TYPES
#define SIMPLE_TYPES

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;

struct pixel_8
{
  uchar red, green, blue;
  
  pixel_8( void ) : red( 0 ), green( 0 ), blue( 0 ) { }
  pixel_8( uchar r, uchar g, uchar b ) : red( r ), green( g ), blue( b ) { }
};

#endif

Ich hoffe wirklich, jemand kann mir sagen, warum das nicht geht, weil ich würd das Buch schon gern durcharbeiten (bzw. erstmal anfangen zu arbeiten).
 
Also ich habe das Programm mal kompiliert und ausgeführt, ohne Probleme, das Manipulieren des Videospeicher hat aber leider keine Auswirkungen gezeigt. Sichtbare Änderungen konnten aber mit "surface.set_palette(...);" erreicht werden. Die Direkte Videospeicher manipulation wurde aber weiterhin ausgeführt.

Vieleicht solltest du einfach mal die neuste DirectX Version (9.25?) + neuste Treiber deiner Grafikkarte installieren. Da die Beigelegten Testprogramme auch nicht funktionieren muss das Problem auch an einer anderen Stelle liegen. Hastdu es schon mal auf einem anderen PC getestet?

mfg
SGSSGene
 
Zurück