kategoria: ANSI C
[#241] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #240

Dla mnie to dziwne, bo na mój chłopski rozum, że jak generuje 100fps to i cztery, jest wzięty od czapy. Co to ma za znaczenie że są cztery bufory, i tak gracz widzi jeden, a drugi jest generowany, i jak skończony to jest robiona zamiana buforów.
[#242] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@asman, post #241

Zrobiłem test i faktycznie, dwa bufory to było za mało byl jeszcze tearing, jak dostawiłem trzeci to przestało szarpać..

Chyba udało się jednak zrobić synchro ! OK

Miałem kupe problemów po drodze np. z alokacją ScreenBuffora - jakby nie chciał zaalokować bitmapy 32bit, musialem recznie ja podpiąć. No i z uzyciem ChangeScreenBuffer czyli funkcji systemowych udalo mi sie uzyskac w tym momecie brak tearingu.

np.: musialem zrobić tak narazie, nie wiem dlaczego AllocScreenBuffer sam tego nie zrobił
struct Bitmap* bm1 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);
struct ScreenBuffer* sb1 = AllocScreenBuffer(APP_screen, 0, SB_COPY_BITMAP );
sb1->sb_BitMap = bm1;

Podziękowania dla @Arcziego, który pokazał mi przykład pod Wampira, dzięki czemu
miałem w końcu punkt odniesienia i widziałem że działa. Pod Wampirami można
samemu na chama zmieniać wskaźnik i jest OK.
Mi zależało na rozwiązaniu uniwersalnym Systemowym.

Kod jeszcze musze wyczyścić bo to taki na brudno jeszcze gorący..

nie ma tu zadanego żadnego czekania, po prostu za koleją bufory sa wypelniane,
nie wiem czy brak jakiegos czekania nie stworzy znowu tearingu np. na Emu68 gdzie raycaster zapieprza 180 fps

// init
struct MsgPort* disp  = CreateMsgPort();
struct MsgPort* safe  = CreateMsgPort();

struct Bitmap* bm1 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);
struct Bitmap* bm2 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);
struct Bitmap* bm3 = AllocBitMap(320,200,32, BMF_CLEAR | BMF_DISPLAYABLE , &APP_screen->BitMap);

struct ScreenBuffer* sb1 = AllocScreenBuffer(APP_screen, 0, SB_COPY_BITMAP  );
struct ScreenBuffer* sb2 = AllocScreenBuffer(APP_screen, 0,SB_COPY_BITMAP );
struct ScreenBuffer* sb3 = AllocScreenBuffer(APP_screen, 0,SB_COPY_BITMAP  );

sb1->sb_BitMap = bm1;
sb2->sb_BitMap = bm2;
sb3->sb_BitMap = bm3;

sb1->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safe;
sb1->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = disp;
sb2->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safe;
sb2->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = disp;
sb3->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safe;
sb3->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = disp;

// loop
int frame = 0;
LOOP
{
    switch (frame)
    {
        case 0:
        {
             ChangeScreenBuffer(APP_screen, sb1);
             APTR handle = LockBitMapTags(sb2->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&x_FBAddr2, TAG_DONE);
             UnLockBitMap(handle);
             // engine output buffer and render
             EM_prefs.output_buffer_32 = x_FBAddr2;
             EM_Update_And_Render();
         }
         break;
         case 1:
         {
            ChangeScreenBuffer(APP_screen, sb2);
            APTR handle = LockBitMapTags(sb3->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&x_FBAddr3, TAG_DONE);
             UnLockBitMap(handle);
             // engine output buffer and render
             EM_prefs.output_buffer_32 = x_FBAddr3;
             EM_Update_And_Render(&APP_main_loop);
           }
           break;
           case 2:
          {
              ChangeScreenBuffer(APP_screen, sb3);
              APTR handle = LockBitMapTags(sb1->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&x_FBAddr1, TAG_DONE);
               UnLockBitMap(handle);
             // engine output buffer and render
             EM_prefs.output_buffer_32 = x_FBAddr1;
              EM_Update_And_Render(&APP_main_loop);
            }
            break;
}
frame++;
if (frame> 2)
frame= 0;
}


Ostatnia aktualizacja: 16.12.2021 22:34:16 przez mateusz_s
1
[#243] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #242

Jak zapieprza 180 FPS-ow to zalacz jakas tabele z osiagami dla roznych konfigow. Na razie wyglada, ze Pi v3 jest wydajnosciowo okolo 3 razy szybsze niz AC68080 To by sie tak mniej/wiecej zgadzalo z wynikow jakie widzialem dla V4SA i Pi v3 (z Aranym jako JIT). Gdzie Pi v3 bylo szybsze, oprocz osiagow w 3D.
[#244] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #242

Podrzucam jeszcez poprawiony kod.
Myślę, że AllocScreenBuffer coś źle alokuje bitmapy na siebie gdy parametr jest 0. Gdy parametr jest SB_SCREEN_BITMAP to bierze on sobie bitmape ze screenu wtedy, ale to robimy tylko dla pierwszego bufora.

oto obecny kod na triple buffering, sprawdziłem raycastera przy 170-180 na V1200 (jak wylaczylem podłogę)
także nie było tearingu, więc chyba ten kod jest ok...

// INICJALIZACJA
// create two message ports
	struct MsgPort* APP_port_disp = CreateMsgPort();
	struct MsgPort* APP_port_safe = CreateMsgPort();
	
	// declare Screen Buffer structure
	struct ScreenBuffer* APP_screen_buffer[3];

	// first buffer - the bitmap won't be allocated - it will use screens bitmap
	APP_screen_buffer[0] = AllocScreenBuffer(APP_screen, NULL, SB_SCREEN_BITMAP);

	// second and third buffer - the bitmaps will be allocated
	APP_screen_buffer[1] = AllocScreenBuffer(APP_screen, NULL, 0);
	APP_screen_buffer[2] = AllocScreenBuffer(APP_screen, NULL, 0);

	// for some reason AllocScreenBuffer() doesn't want to correct allocate BitMap for it - so we doing this manually for Screen Buffers 1 and 2.
	struct BitMap* bitmap_1 = AllocBitMap(320,200,32,BMF_DISPLAYABLE , &APP_screen->BitMap );
	FreeBitMap(APP_screen_buffer[1]->sb_BitMap);
	APP_screen_buffer[1]->sb_BitMap = bitmap_1;

	struct BitMap* bitmap_2 = AllocBitMap(320,200,32,BMF_DISPLAYABLE , &APP_screen->BitMap );
	FreeBitMap(APP_screen_buffer[2]->sb_BitMap);
	APP_screen_buffer[2]->sb_BitMap = bitmap_2;


	// link with message ports
	for (int i = 0; i < 3; i++)
	{
		APP_screen_buffer[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = APP_port_disp;
       	APP_screen_buffer[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = APP_port_safe;
	}
	
	// init buffer switcher
	int APP_current_frame_buffer = 1;
	int APP_next_frame_buffer = 2;

// PETLA


    while (APP_main_loop)
    {
		
      	if (ChangeScreenBuffer(APP_screen, APP_screen_buffer[APP_current_frame_buffer]))
		{
			// increment APP_current_frame_buffer
			APP_current_frame_buffer++;
			if (APP_current_frame_buffer > 2) APP_current_frame_buffer = 0;
		}

  		APTR handle = LockBitMapTags(APP_screen_buffer[APP_next_frame_buffer]->sb_BitMap, LBMI_BASEADDRESS, (ULONG)&EM_prefs.output_buffer_32, TAG_DONE);
		if (handle)			
		{	        
			EM_Update_And_Render(&APP_main_loop);
			
			// increment APP_next_frame_buffer
			APP_next_frame_buffer++;
			if (APP_next_frame_buffer > 2) APP_next_frame_buffer = 0;
		}
    	UnLockBitMap(handle);
}
2
[wyróżniony] [#245] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@asman, post #241

Potrójne buforowanie stosujesz żeby wyeliminować przestój związany z czekaniem na vblank żeby podmienić bufory. W podwójnym buforowaniu:

- pierwszy wyświetlasz
- drugi rysujesz
- jak skończyłeś drugi przed vblankiem to czekasz na niego i wtedy podmieniasz
- jak w powyższym kroku nie poczekasz to masz własnie tearing

Triple buffering z kolei:

- pierwszy wyświetlasz
- drugi rysujesz
- jak skończyłeś drugi przed vblankiem to rysujesz kolejną klatkę na trzecim
- jak skończyłeś trzeci przed vblankiem to rysujesz kolejną klatkę na drugim
- jak następuje vblank to podmieniasz pierwszy z drugim lub trzecim, w zależności gdzie znajduje się najświeższa kompletna klatka

wszystko to następuje bez jakiegokolwiek czekania - możesz swap buforów zrobić na przerwaniu vblankowym. Za to nie widzę żadnych dodatkowych zalet poczwórnego buforowania. ;)
[#246] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@teh_KaiN, post #245

Ja tam sie nie znam za bardzo na grafice, ale przy bardzo szybkich sprzetach jak te co osiagaja 170 FPS to beda chyba bledy w wyswietlaniu przy potrojnym buforze, bo albo procesor bedzie musial czekac na rysowanie, albo bedzie rysowal na buforze, ktory nie jest jeszcze wyswietlony, ale czeka zeby go wyswietlic. Wiec moze poczworne buforowanie ma jednak sens przy bardzo szybkich sprzetach?
[#247] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@teh_KaiN, post #245

Dzięki wielkie za wyjaśnienie, rozjaśniłeś mi z tym triple buffering.
[#248] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@Don_Adan, post #246

@teh_KaiN

jednak jakiś problem jest jeszcze z tym kodem, np. na V1200 jest niby ok ,
ale na emu w filmiku Michała Schulza widać było tearing, wiec jakiś WAIT musi byc jeszcze, np.w demku Kioea pod emu
było pięknie płynnie ale w moim raycasterze na emu w 320x200 bardzo brzydki tearing.. trzeba jeszcze
coś dodac do tego kodu jednak

tu na emu widać tearing w 320x200
(w ponad 2k jest 5-8 fps ale to i tak niezle w wersji PC jest zaledwie 30fps)


tu płynnie:


Ostatnia aktualizacja: 18.12.2021 15:03:34 przez mateusz_s

Ostatnia aktualizacja: 18.12.2021 15:03:58 przez mateusz_s
1
[#249] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@asman, post #247

Dostałem taki przykład od Thomasa Richtera, troche tam namotane jest.. również uzycie ChangeSCreenBuffer
trzeba uzyc klawiszy R - animacja,S-klatka po klatkce,Q - wyjscie..

poniżej kod cały, dorzucam też skompilowaną binarkę jakby ktoś chciał zobaczyć:
https://mstanisz.website.pl/tmp/amiga/DBuffer.exe.zip


/* :ts=8
 * doublebuffer.c - shows double-buffering, attached screens, menu lending
 *
 * (c) Copyright 1992 Commodore-Amiga, Inc.  All rights reserved.
 *
 * This software is provided as-is and is subject to change; no warranties
 * are made.  All use is at your own risk.  No liability or responsibility
 * is assumed.
 *
 * Example shows use of V39 double-buffering functions to achieve
 * 60 frame-per-second animation.  Also shows use of menus in
 * double-buffered screens, and the use of attached screens with
 * menu-lending to achieve the appearance of slider gadgets in
 * double-buffered screens.
 * 
 */

/*----------------------------------------------------------------------*/

#include <exec/types.h>
#include <graphics/displayinfo.h>
#include <intuition/intuition.h>

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/Picasso96.h>

#include	<stdio.h>
#include	<stdlib.h>

/*----------------------------------------------------------------------*/

STRPTR init_all( void  );
void error_exit( STRPTR errorstring );
BOOL handleIntuiMessage( struct IntuiMessage *imsg );
void handleDBufMessage( struct Message *dbmsg );
ULONG handleBufferSwap( void );
struct BitMap *makeImageBM( void );
void CloseWindowSafely( struct Window *win );

int CXBRK( void ) {return( 0 );}

/*----------------------------------------------------------------------*/

/* Some constants to handle the rendering of the animated face */
#define BM_WIDTH	80
#define BM_HEIGHT	80
#define BM_DEPTH	2

/* Odd numbers to give a non-repeating bounce */
ULONG		SC_ID = INVALID_ID;

/*----------------------------------------------------------------------*/

UWORD pens[] =
{
    0, /* DETAILPEN */
    1, /* BLOCKPEN	*/
    1, /* TEXTPEN	*/
    2, /* SHINEPEN	*/
    1, /* SHADOWPEN	*/
    3, /* FILLPEN	*/
    1, /* FILLTEXTPEN	*/
    0, /* BACKGROUNDPEN	*/
    2, /* HIGHLIGHTTEXTPEN	*/

    1, /* BARDETAILPEN	*/
    2, /* BARBLOCKPEN	*/
    1, /* BARTRIMPEN	*/

    (UWORD)~0, 
};

struct Screen *canvassc = NULL;
struct Window *canvaswin = NULL;

/*----------------------------------------------------------------------*/

#define	OK_REDRAW	1	/* Buffer fully detached, ready for redraw */
#define OK_SWAPIN	2	/* Buffer redrawn, ready for swap-in */

struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;

struct MsgPort *dbufport = NULL;
struct MsgPort *userport = NULL;

struct ScreenBuffer *scbuf[] = { NULL, NULL };
struct RastPort rport[2];

ULONG status[2];

LONG prevx[2] = { 50, 50 };
LONG prevy[2] = { 50, 50 };

ULONG buf_current, buf_nextdraw, buf_nextswap;
ULONG count;
struct BitMap *face = NULL;
LONG x, y, xstep, xdir, ystep, ydir;

/*----------------------------------------------------------------------*/

main()
{
	STRPTR errorstring;
	ULONG sigs;
	BOOL terminated = FALSE;

	SC_ID = p96RequestModeIDTags(TAG_DONE);

	/* Let's get everything initialized */

	if ( errorstring = init_all()){
		error_exit( errorstring );
	}

    count = 0;
    buf_current = 0;
    buf_nextdraw = 1;
    buf_nextswap = 1;
    sigs = 0;

    while ( !terminated )
    {

	/* Check for and handle any IntuiMessages */
	if(sigs & (1 << userport->mp_SigBit)){
		struct Message *imsg;

		while(imsg = GetMsg(userport)){
			terminated |= handleIntuiMessage((struct IntuiMessage *)imsg);
			ReplyMsg(imsg);
		}
	}

	/* Check for and handle any double-buffering messages.
	 * Note that double-buffering messages are "replied" to
	 * us, so we don't want to reply them to anyone.
	 */
	if(sigs & (1 << dbufport->mp_SigBit)){
		struct Message *dbmsg;
		while(dbmsg = GetMsg(dbufport)){
			handleDBufMessage(dbmsg);
		}
	}


	if ( !terminated )
	{
	    ULONG held_off = 0;
	    /* Only handle swapping buffers if count is non-zero */
	    if ( count )
	    {
		held_off = handleBufferSwap();
	    }
	    if ( held_off )
	    {
		/* If were held-off at ChangeScreenBuffer() time, then we
		 * need to try ChangeScreenBuffer() again, without awaiting
		 * a signal.  We WaitTOF() to avoid busy-looping.
		 */
		 WaitTOF();
	    }
	    else
	    {
		/* If we were not held-off, then we're all done
		 * with what we have to do.  We'll have no work to do
		 * until some kind of signal arrives.  This will normally
		 * be the arrival of the dbi_SafeMessage from the ROM
		 * double-buffering routines, but it might also be an
		 * IntuiMessage.
		 */
		sigs = Wait( ( 1 << dbufport->mp_SigBit ) | ( 1 << userport->mp_SigBit ) );
	    }
	}
    }

    error_exit( NULL );
}


/*----------------------------------------------------------------------*/

/* Handle the rendering and swapping of the buffers */

ULONG handleBufferSwap( void )
{
    ULONG held_off = 0;
    /* 'buf_nextdraw' is the next buffer to draw into.
     * The buffer is ready for drawing when we've received the
     * dbi_SafeMessage for that buffer.  Our routine to handle
     * messaging from the double-buffering functions sets the
     * OK_REDRAW flag when this message has appeared.
     *
     * Here, we set the OK_SWAPIN flag after we've redrawn
     * the imagery, since the buffer is ready to be swapped in.
     * We clear the OK_REDRAW flag, since we're done with redrawing
     */
    if ( status[ buf_nextdraw ] == OK_REDRAW )
    {
	x += xstep*xdir;
	if ( x < 0 )
	{
	    x = 0;
	    xdir = 1;
	}
	else if ( x > canvassc->Width - BM_WIDTH )
	{
	    x = canvassc->Width - BM_WIDTH - 1;
	    xdir = -1;
	}

	y += ystep*ydir;
	if ( y < canvassc->BarLayer->Height )
	{
	    y = canvassc->BarLayer->Height;
	    ydir = 1;
	}
	else if ( y >= canvassc->Height - BM_HEIGHT )
	{
	    y = canvassc->Height - BM_HEIGHT - 1;
	    ydir = -1;
	}

/*
	SetAPen( &rport[ buf_nextdraw ], 0 );
	RectFill( &rport[ buf_nextdraw ], 
	    prevx[ buf_nextdraw ], prevy[ buf_nextdraw ], 
	    prevx[ buf_nextdraw ] + BM_WIDTH - 1, prevy[ buf_nextdraw ] + BM_HEIGHT - 1 );
*/
	prevx[ buf_nextdraw ] = x;
	prevy[ buf_nextdraw ] = y;

	BltBitMapRastPort(face, 0, 0, &rport[buf_nextdraw], x, y, BM_WIDTH, BM_HEIGHT, 0xc0);

//	WaitBlit(); /* Gots to let the BBMRP finish */

	status[ buf_nextdraw ] = OK_SWAPIN;

	/* Toggle which the next buffer to draw is.
	 * If you're using multiple ( >2 ) buffering, you
	 * would use
	 *
	 *    buf_nextdraw = ( buf_nextdraw+1 ) % NUMBUFFERS;
	 *
	 */
	buf_nextdraw ^= 1;
    }

    /* Let's make sure that the next frame is rendered before we swap...
     */
    if ( status[ buf_nextswap ] == OK_SWAPIN )
    {
	scbuf[ buf_nextswap ]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = dbufport;

	if ( ChangeScreenBuffer( canvassc, scbuf[ buf_nextswap ] ) )
	{
	    status[ buf_nextswap ] = 0;

	    buf_current = buf_nextswap;
	    /* Toggle which the next buffer to swap in is.
	     * If you're using multiple ( >2 ) buffering, you
	     * would use
	     *
	     *    buf_nextswap = ( buf_nextswap+1 ) % NUMBUFFERS;
	     *
	     */
	    buf_nextswap ^= 1;

	    count--;
	}
	else
	{
	    held_off = 1;
	}
    }
    return( held_off );
}

/*----------------------------------------------------------------------*/

/* Handle Intuition messages */

BOOL handleIntuiMessage( struct IntuiMessage *imsg )
{
    UWORD code = imsg->Code;
    BOOL terminated = FALSE;

    switch ( imsg->Class )
    {
	case IDCMP_VANILLAKEY:
	    switch ( code )
	    {
		case 'S':
		case 's':
		    count = 1;
		    break;

		case 'R':
		case 'r':
		    count = ~0;
		    break;

		case 'Q':
		case 'q':
		    count = 0;
		    terminated = TRUE;
		    break;
	    }
	    break;
    }
    return( terminated );
}

/*----------------------------------------------------------------------*/

void handleDBufMessage( struct Message *dbmsg )
{
	ULONG buffer;

	/* dbi_SafeMessage is followed by an APTR dbi_UserData1, which
	* contains the buffer number.  This is an easy way to extract
	* it.
	* The dbi_SafeMessage tells us that it's OK to redraw the
	* in the previous buffer.
	*/

	buffer = ( ULONG ) *( ( APTR ** ) ( dbmsg+1 ) );

	/* Mark the previous buffer as OK to redraw into.
	* If you're using multiple ( >2 ) buffering, you
	* would use
	*
	*    ( buffer + NUMBUFFERS - 1 ) % NUMBUFFERS
	*
	*/

	status[ buffer^1 ] = OK_REDRAW;
}

/*----------------------------------------------------------------------*/

/* Get the resources and objects we need */

STRPTR init_all( void )
{
    if ( !( GfxBase = ( struct GfxBase * )
	OpenLibrary( "graphics.library", 39L ) ) )
    {
	return( "Couldn't open Gfx V39\n" );
    }

    if ( !( IntuitionBase = ( struct IntuitionBase * )
	OpenLibrary( "intuition.library", 39L ) ) )
    {
	return( "Couldn't open Intuition V39\n" );
    }

    if ( !( dbufport = CreateMsgPort() ) )
    {
	return( "Failed to create port\n" );
    }

    if ( !( userport = CreateMsgPort() ) )
    {
	return( "Failed to create port\n" );
    }

    if ( !( canvassc = OpenScreenTags( NULL, 
	SA_DisplayID, SC_ID, 
	SA_Overscan, OSCAN_TEXT, 
	SA_Depth, 2, 
	SA_AutoScroll, 1, 
	SA_Pens, pens, 
	SA_ShowTitle, TRUE, 
	SA_Title, "Intuition double-buffering example", 
	SA_SysFont, 1, 
	TAG_DONE ) ) )
    {
	return( "Couldn't open screen\n" );
    }

    if ( !( canvaswin = OpenWindowTags( NULL, 
	WA_NoCareRefresh, TRUE, 
	WA_Activate, TRUE, 
	WA_Borderless, TRUE, 
	WA_Backdrop, TRUE, 
	WA_CustomScreen, canvassc, 
	WA_NewLookMenus, TRUE, 
	TAG_DONE ) ) )
    {
	return( "Couldn't open window\n" );
    }
    canvaswin->UserPort = userport;

    ModifyIDCMP( canvaswin, IDCMP_MENUPICK | IDCMP_VANILLAKEY );


    if ( !( scbuf[ 0 ] = AllocScreenBuffer( canvassc, NULL, SB_SCREEN_BITMAP ) ) )
    {
	return( "Couldn't allocate ScreenBuffer 1\n" );
    }

    if ( !( scbuf[ 1 ] = AllocScreenBuffer( canvassc, NULL, SB_COPY_BITMAP ) ) )
    {
	return( "Couldn't allocate ScreenBuffer 2\n" );
    }

    /* Let's use the UserData to store the buffer number, for
     * easy identification when the message comes back.
     */
    scbuf[ 0 ]->sb_DBufInfo->dbi_UserData1 = ( APTR ) ( 0 );
    scbuf[ 1 ]->sb_DBufInfo->dbi_UserData1 = ( APTR ) ( 1 );
    status[ 0 ] = OK_REDRAW;
    status[ 1 ] = OK_REDRAW;

    if ( !( face = makeImageBM() ) )
    {
	return( "Couldn't allocate image bitmap\n" );
    }
    InitRastPort( &rport[ 0 ] );
    InitRastPort( &rport[ 1 ] );
    rport[ 0 ].BitMap = scbuf[ 0 ]->sb_BitMap;
    rport[ 1 ].BitMap = scbuf[ 1 ]->sb_BitMap;

	Move(&rport[0], canvassc->Width - 50, 9);
	Text(&rport[0], "1", 1);
	Move(&rport[1], canvassc->Width - 40, 9);
	Text(&rport[1], "2", 1);

    x = 50;
    y = 70;
    xstep = 1;
    xdir = 1;
    ystep = 1;
    ydir = -1;

    /* All is OK */
    return( 0 );
}

/*----------------------------------------------------------------------*/

/* Draw a crude "face" for animation */

#define MAXVECTORS	10

struct BitMap *makeImageBM( void )
{
	struct BitMap *bm;
	struct RastPort rport;
	struct AreaInfo area;
	struct TmpRas tmpRas;
	PLANEPTR planePtr;

	BYTE areabuffer[ MAXVECTORS*5 ];

	if(bm = (struct BitMap *)AllocBitMap(BM_WIDTH, BM_HEIGHT, BM_DEPTH, BMF_CLEAR, scbuf[ 0 ]->sb_BitMap)){
		if(planePtr = AllocRaster(BM_WIDTH, BM_HEIGHT)){
			InitRastPort(&rport);
			rport.BitMap = bm;

			InitArea(&area, areabuffer, MAXVECTORS);
			rport.AreaInfo = &area;

			InitTmpRas(&tmpRas, planePtr, RASSIZE(BM_WIDTH, BM_HEIGHT));
			rport.TmpRas = &tmpRas;

			SetABPenDrMd(&rport, 3, 0, JAM1);
			AreaEllipse(&rport, BM_WIDTH/2, BM_HEIGHT/2, BM_WIDTH/2-4, BM_HEIGHT/2-4);
			AreaEnd(&rport);

			SetAPen(&rport, 2);
			AreaEllipse(&rport, 5*BM_WIDTH/16, BM_HEIGHT/4, BM_WIDTH/9, BM_HEIGHT/9);
			AreaEllipse(&rport, 11*BM_WIDTH/16, BM_HEIGHT/4, BM_WIDTH/9, BM_HEIGHT/9);
			AreaEnd(&rport);

			SetAPen(&rport, 1);
			AreaEllipse(&rport, BM_WIDTH/2, 3*BM_HEIGHT/4, BM_WIDTH/3, BM_HEIGHT/9);
			AreaEnd(&rport);

			FreeRaster(planePtr, BM_WIDTH, BM_HEIGHT);
		}else{
			FreeBitMap(bm);
			bm = NULL;
		}
		return(bm);
	}
}

/*----------------------------------------------------------------------*/

/* Clean up everything and exit, printing the errorstring if any */
void error_exit(STRPTR errorstring)
{
	if(canvaswin){
		ClearMenuStrip(canvaswin);
		CloseWindowSafely(canvaswin);
	}

	if(canvassc){
		FreeScreenBuffer(canvassc, scbuf[1]);
		FreeScreenBuffer(canvassc, scbuf[0]);
		CloseScreen(canvassc);
	}

	if(dbufport) DeleteMsgPort(dbufport);

	if(userport) DeleteMsgPort(userport);

	if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);

	if(face)	FreeBitMap(face);

	if(GfxBase) CloseLibrary((struct Library *)GfxBase);

	if(errorstring){
		printf(errorstring);
		exit(20);
	}

	exit(0);
}


/*----------------------------------------------------------------------*/

void StripIntuiMessages( struct MsgPort *mp, struct Window *win );

/* these functions close an Intuition window
 * that shares a port with other Intuition
 * windows or IPC customers.
 *
 * We are careful to set the UserPort to
 * null before closing, and to free
 * any messages that it might have been
 * sent.
 */
#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/ports.h"
#include "intuition/intuition.h"

void
CloseWindowSafely( struct Window *win )
{
    /* we forbid here to keep out of race conditions with Intuition */
    Forbid();

    /* send back any messages for this window 
     * that have not yet been processed
     */
    StripIntuiMessages( win->UserPort, win );

    /* clear UserPort so Intuition will not free it */
    win->UserPort = NULL;

    /* tell Intuition to stop sending more messages */
    ModifyIDCMP( win, 0L );

    /* turn multitasking back on */
    Permit();

    /* and really close the window */
    CloseWindow( win );
}

/* remove and reply all IntuiMessages on a port that
 * have been sent to a particular window
 * ( note that we don't rely on the ln_Succ pointer
 *  of a message after we have replied it )
 */
void
StripIntuiMessages( mp, win )
struct MsgPort *mp;
struct Window *win;
{
    struct IntuiMessage *msg;
    struct Node *succ;

    msg = ( struct IntuiMessage * ) mp->mp_MsgList.lh_Head;

    while( succ =  msg->ExecMessage.mn_Node.ln_Succ )
    {

	if( msg->IDCMPWindow ==  win )
	{

	    /* Intuition is about to free this message.
	     * Make sure that we have politely sent it back.
	     */
	    Remove( ( struct Node * )msg );

	    ReplyMsg( ( struct Message * )msg );
	}
	    
	msg = ( struct IntuiMessage * ) succ;
    }
}

/*----------------------------------------------------------------------*/
[#250] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #249

Klatka zrobiona telefonem z powyzszego,
Ale na żywca tez było widać delikatny tearing moim zdaniem, jakby to dorzucić ten 3 bufor to by było ok


[#251] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #250

-- mały update --

Udało mi się przebić magiczna barierę 50 - 51 fps OK

(*wg sceny referencyjnej na V1200 320x200x32 - zaczynałem od ok. 20-22 fps)

Ostatnie dodatkowe FPS-y uzyskałem podczas czyszczenia kodu (nie wiem nawet w którym momencie)
oraz poprzez ręczne rozwinięcie kilku najbardziej wewnętrznych pętli - tu użyłem szablonu Duff-a (Duff Device)..

Myślę, że jest jeszcze trochę miejsca na optymalizacje przy algorytmie podłogowo/sufitowym ale to potem jakoś może. Ostatnio się dowiedziałem i sam sprawdzałem, że kompilacja na GCC 6.5.0 od Bebbo pomiedzy 040 a 060 nie daje żadnej różnicy, wiec może zostać przy buildzie 040 tylko? przy kompilacji na 080 też nie ma jakiś różnic.

Poprawiła się wydajność na Warpie 1260, jest już praktycznie grywalne, chyba cos ok. 20-22 fps o ile dobrze pamietam, teraz moze troche wiecej.

Na Emu68 to prędkości są kosmiczne nawet w wysokich rozdziałkach.

Dlatego też ide na razię w stronę Benchmarku dodając możliwość lepszych textur 256x256.. Ich rozmiar nie specjalnie wpływa na wydajność, dłużej się wczytuje.

Chciałbym zrobić jeden prosty, ale ładny level do testów właśnie.

Przepisałem też Starter. Jeśli w systemie jest ReAction to GUI bedzie właśnie pod ReAction a jak nie to standardowe.



Dorzuciłem też małą konsolkę, żeby było widać co i jak podczas inicjalizacji:








Ostatnia aktualizacja: 04.01.2022 15:19:23 przez mateusz_s

Ostatnia aktualizacja: 04.01.2022 15:20:03 przez mateusz_s
3
[#252] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #251

Yyy.... zapomniałeś o archiwum co by inni się pocieszyli z Tobą :)
1
[#253] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@waldiamiga, post #252

tak, jeszcze kończę :) nie za bardzo chce wrzucać bo ten level jest cały czas brzydki taki na szybko
ale postaram się wieczorkiem jeszcze wrzucić to co mam, tylko drobne poprawki jeszcze robie..
więc zapraszam wieczorkiem :) do ewentulanych testów
[#254] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #253

ps. sory jeszcze jakiś błąd znalazłem.. musze to poprawić.. potem podesle binarkę..
[#255] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #251

Mateusz ty jakieś demo na tym zrób.... a nie grę. Patrz KK rozwinął swoją grę właśnie z dema... A wiadomo są ludzie co wolą dema 😀😆. Pozdrawiam.
[#256] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@jimiche, post #255

No na razie chce takie demko/benchmark zrobić.
Ale z prostym małym levelem ale ładnie zrobionym.
Nie dodaje praktycznie żadnych nowych właściwości
Bo staram się zoptymalizowac te najważniejsze podstawy które mam, I tak mi schodzi. Można to w nieskończoność robic ale też co chwilę znajduje coś co można poprawić a im więcej funkcji będzie potem tym trudniej będzie optymalizować.
[#257] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #256

Kucze jakiś problem jednak znalazłem chyba w kompilatorze Bebo gcc 6.5.0,
wczenisje uzywalem wersji pod windows a ostantio przesiadłem się na linuxowego.

Napisałem już do Beboo na Git, tutaj szczegóły:
https://github.com/bebbo/amiga-gcc/issues/264
[#258] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #257

Niestety doswiadczylem tez tego problemu pod Win i niestety to mnie zniechecilo do kontynuowania swojego projektu 3d. Na wstepie rozwiazaniem bylo zrobienie arraya z sinusami co na 68k dawalo nawet dobry rezultat. Co do floata to upierdliwe. Dopoki nie znajde sposobu na pewny crosscompiler to temat do poczekalni
[#259] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@arturB, post #258

Tzn. Wersja pod windows jako setup.exe z 22 marca 2021 była Ok cały czas nie miałem problemów. Dopiero jak zainstalowałem najnowsza pod win/Ubuntu.

Teraz mi odpisał, że:
what I noticed so far: I changed the order of initializing the fpu and loading the libraries.
Please try using the libnix folder from your windows version and check if it behaves ok again.
[#260] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #259

Pracuje nad demo levelem, trochę schodzi.. wczoraj mi zeszło 3h nad jednym pomieszczeniem ;)
ale przy okazji "na szybko" udało mi się dorobić super efekt moim zdaniem.. tj. jasne pixele nie są
podatne ściemnianie z związku z odległościa. Mam wyliczone 256 tabel kolorów z odcienieniami do czerni
więc jest to bezkosztowa operacja która robie na poczatku przy wgrywaniu textury..

poniżej dwa ujecia.. staram się różnicować textury / per kafelek żeby nie było za bardzo powtarzalności






a tu przykłąd z "podświetleniem".. bałem się że w 320x200 bedzie kiepsko to wyglądać, ale nie miga aż tak bardzo i chyba robi się spoko klimacik.. wyobraźcie sobie oczy potworca w ciemnosći :D




a tu mnie poniosło i wkleiłem gun-a :PP




9
[#261] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #260

************************************************************
** KONIEC ETAPU ** PODSUMOWANIE, WYNIKI, PROŚBA O TESTY ITP ***
************************************************************


Cześć,
Podrzucam kilka materiałów na zakończenie etapu.

obecnie zaimplementowane rzeczy:
- textury ścian (na 4 osobne ściany)
- textury podłóg, sufitów (per kafelek)
- mouse lookaround
- cieniowanie distant + side
- "świecące textury" - jaskrawe kolory nie ulegają ściemnianiu, "świecą" w ciemności
- wybór rozmiaru textur 128x128 i 256x256
- systemowy triple buffering żeby pozbyć się screen tearingu
- Starter aplikacji zrobiony za pomocą standardowego gadtools oraz ReAction
(jeśli w systemie jest ReAction to bedzie w ReAction.)
- konsolka startowa

użyte metody/pomysły:
- oparto na liczbach zmiennoprzecinkowych, liczby fixed point tylko w najbardziej wewnętrznych pętlach.
- ściany mają swój osoby zestaw textur, a podłogi i sufity osobny (w 256 kolorach).
- każdy zestaw ma również wygenerowaną paletę 256 kolorów w 256 odcieniach od oryginału do czerni.
która służy do szybkiego cieniowania i "świecenia" w ciemności.
- każdy zestaw jest wczytywany jako całość do pamięci a dostęp do początku danej tekstury jest tylko przez offset
- zestaw dla ścian jest dodatkowo obrócony o 90 stopni przy wczytywaniu
- do renderowania podłóg i sufitów opracowałem algorytm o którym pisałem wcześniej
a który okazał się bardzo szybki. Jest trochę podobny do algorytmu z Dooma, tj. podczas obliczania i rysowania ścian zapisywana są dodatkowe informacje, a promień musi również pobrać dane z każdego grida na który na trafi (nie tylko z tego który ma w sobie ścianę jak dotychczas), te informacje pozwalają potem renderować podłogę i sufit z podziałem na poszczególne "kafelki".
- dużo optymalizacji, np. kolejne współrzędne textury ścian są pobierane z tablicy wcześniej przygotowanej. spora optymalizacja
algorytmu podłogowo/sufitowego (od pierwszej wersji), drobne mikro optymalizacje
- tylko język C, kompilacja pod 060 (działa na 040 i 080), wymaga FPU.


TESTY:
Kiedy wrzucałem jakiś czas temu referencyjny Ray-20 miałem takie wyniki na V1200:
- 320x200x32 (17 fps)
- 640x400x32 (5 fps)

Obecnie na V1200 mam:
- 320x200x32 - średnio 50 fps, blisko ścian dochodzi do 70-80, nieraz spada do 35 w zależnosći od ujecia,
ogólnie bardzo płynnie i szybko
- 640x400x32 - średnio 16-18 fps (grywalne)


Poniżej prezentacja DEMO LEVELU.. textury oparłem na jakimś zestawie z sieci. Robiłem kilka wersji żeby nie było powtarzalności za bardzo, najlepszy efekt jest wiadomo w 640x400 (i wyżej :) ) i z 256x256 tex. w 320x200 nie ma sensu za bardzo wybierać 256x256, rozmiar textur nie wpływa widocznie na wydajność.




Kilka zrzutów z V1200 w 640x400 z 256x256 tex:











zestaw textur 256x256 dla ścian i podłóg:







***************************************************************
*** LINK DO EXECA: *********************************************


https://mstanisz.website.pl/tmp/amiga/msRay_devpack_v0.31-exec.zip

*****************************************************************


Jeśli Ktoś ma ochotę POTESTOWAĆ - to będzie wdzięczny za jakiś FEEDBACK i parametry.
ps. NIE WŁAZIĆ W ŚCIANY :) bo nie ma kolizji, ale spoko nie zawiesi się :)
7
[#262] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #261

A tymczasem filmik z testami emu68 od Michała Schulza:

4
[#263] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #262

Bardzo smacznie to wygląda, a może jakaś kompilacja pod PPC, czyli pod WOS'a dla Blizzardów, CStormów PPC/ Ragnaroków itp.
Jest tu duży zapas mocy szczególnie pod Ragnarokiem i obowiązkowo jest GFX, więc jest na czym testować ok, racja
1
[#264] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #261

Nie wiem czy to już ktoś pisał ale przyda ci się mipmapping dla tekstur. Rozwiąże kilka problemów:
- efekt moire na podłogach
- migające tekstury w oddali

Dodatkowo potencjalnie poprawi wydajność. Przy samplowaniu tekstury która jest mocno zmniejszona masz tonę cachemissów. Nie bawiłbym się w liczenie który mip dla każdego piksela a po prostu robiłbym to dla każdego kafla/ściany. Banalnie proste.
3
[#265] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #261

Jak dla mnie rewelacja! Twój projekt zainspirował mnie i widzę ile jeszcze przede mną. Gratulacje!
1
[#266] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@BULI, post #263

@BULI
Taka kompilacja pod PPC jeszcze pewnie by dało rade, ale chyba bym musiał
framework przerobić na AmigaOS 4.1 dodatkowo.. Czy coś z Amiga4.1 pójdzie
pod też pod MorphOS?

@kiero
no z pixelozą w 320x200 by pewnie troche pomogło,
ale wydajnościowo nie wpływa to praktycznie, zrobiłem test z texturą chyba 16x16
i było bez róznicy
[#267] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #266

ja twoja starą wersję kompilowalem na morphosa i działało wzglednie normalnie. jak juz będziesz mieć coś "bardziej" to moge jeszcze raz przeportować.
[#268] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@michal_zukowski, post #267

Aha, ok.. to podeślę potem
[#269] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #268

-------------------------------------
------- ŹRÓDŁA - LINKI ----------
-------------------------------------

Cześć,
Dla zainteresowanych podsyłam źródła do samodzielnej kompilacji, testów itp.
Pomysły, wskazówki, komentarze, poprawki mile widziane:

Tutaj całe "dev pack" czyli żródła Amigowe i Windows + edytor, pięknie poukładane w katalogach.
https://mstanisz.website.pl/tmp/amiga/msRay_devpack_v0.31.zip

Tutaj wersja trochę uproszczona (tylko źródła Amigowe wszystko w jednym katalogu + info jak kompilować)
https://mstanisz.website.pl/tmp/amiga/msRay_devpack_v0.31--SIMPLE.zip

W przypadku problemów ze Starterem (używa alternatywnie ReAction) nie jest on konieczny,
albo można wywalić wszsytko co z ReaCtion zwiazane. Głowną Aplikację czyli Framework
można uruchomić z parametrem displayID danego trybu wyświetlania (tylko tryby 32 bit)



Ostatnia aktualizacja: 14.01.2022 10:49:08 przez mateusz_s
[#270] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@michal_zukowski, post #267

ja twoja starą wersję kompilowalem na morphosa i działało wzglednie normalnie. jak juz będziesz mieć coś "bardziej" to moge jeszcze raz przeportować.

Spróbuj kompilacji proszę pod WOS, zobaczymy czy poleci na Ragnaroku i Blizzardzie PPC?
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem