#170460 - DiscoStew - Mon Sep 28, 2009 8:16 am
My first question was answered, which is below, but now I have a 2nd question, which I will post again at what is currently the end of the thread, since people have already checked this thread, and skim to the end.
With the capture mode, does it completely write over what was previously in the VRAM slot used? What I am wanting to do is render a couple of different frame with the 3D engine, and have them layered over each other, so that the top-most layer doesn't block the ones behind them, kinda like how the 2D engine works, except the frame rate will be based on how many layers I want to render per go. I believe that if I were to use 2 vram banks, I'd swap between the two, having one in LCD mode for the capture, and the other in BG mode using it as a bitmap which gets added into the capture if it is layered underneath it, but I'm hoping there is a way to do it with just 1 bank.
From what I can tell, when using both source A and B, it will only do an additive mix, and not be able to just write over what's already there, even with an alpha value. Perhaps someone out there may know a way?
------------------------------------------------
Original post:
{SOLVED}
When using glFlush(), it doesn't swap the buffers until the next VBlank. The code below shows the correct way to do it.
Code: |
lcdMainOnTop();
videoSetMode( MODE_FB3 );
vramSetBankD( VRAM_D_LCD );
glInit();
glEnable( GL_ANTIALIAS );
glClearColor( 0, 0, 0, 31 );
glClearPolyID( 63 );
glClearDepth( 0x7FFF );
glViewport( 0, 0, 255, 191 );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 70, 256.0 / 192.0, 0.1, 100 );
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
glMatrixMode(GL_MODELVIEW);
render_Poly( 0 );
glFlush( 0 );
swiWaitForVBlank();
REG_DISPCAPCNT = DCAP_ENABLE | DCAP_MODE( 0 ) | DCAP_BANK( 3 ) | DCAP_OFFSET( 0 ) | DCAP_SIZE( 3 ) | DCAP_SRC( 1 );
while(1)
swiWaitForVBlank(); |
_________________
DS - It's all about DiscoStew
Last edited by DiscoStew on Tue Sep 29, 2009 12:39 am; edited 1 time in total
#170462 - Min - Mon Sep 28, 2009 11:31 am
Try doing the capture after glFlush().
#170463 - DiscoStew - Mon Sep 28, 2009 4:22 pm
Ok, I understand it now. Moving it to after glFlush() didn't change it, but adding another swiWaitForVBlank() in between those two made it work. I forgot that when glFlush() is used, the buffers aren't swapped until the "next" VBlank.
thx
_________________
DS - It's all about DiscoStew
#170472 - DiscoStew - Tue Sep 29, 2009 12:39 am
This is my 2nd question.
With the capture mode, does it completely write over what was previously in the VRAM slot used? What I am wanting to do is render a couple of different frame with the 3D engine, and have them layered over each other, so that the top-most layer doesn't block the ones behind them, kinda like how the 2D engine works, except the frame rate will be based on how many layers I want to render per go. I believe that if I were to use 2 vram banks, I'd swap between the two, having one in LCD mode for the capture, and the other in BG mode using it as a bitmap which gets added into the capture if it is layered underneath it, but I'm hoping there is a way to do it with just 1 bank.
From what I can tell, when using both source A and B, it will only do an additive mix, and not be able to just write over what's already there, even with an alpha value. Perhaps someone out there may know a way?
_________________
DS - It's all about DiscoStew
#170482 - Min - Tue Sep 29, 2009 10:45 am
I haven't tried this so please correct any mistakes.
Using two bg layers on the main screen, one for display capture and one for the 3D. Only one VRAM bank is used for the capture/bg layer.
1. Render 3D and flush
2. Wait for Vblank
3. Set the capture/bg bank to LCD
4. Do display capture
5. Set the capture/bg bank to BG
Both the previous captured frame and the new 3D on top will be captured, adding another layer to the captured image each time the list is repeated ( but that you already know. :P ) Step 3-5 should complete before the screen needs to redraw, and therefore having the capture/bg bank in LCD mode during the capture shouldn't affect the display.
Oh, and make sure the clear color is transparent. Code: |
glClearColor( 0,0,0,0 ); |
You can even transparent polygons blend with the bg if you add this little line to your code: Code: |
REG_BLDCNT = BLEND_ALPHA | BLEND_SRC_BG0 | BLEND_DST_BG3 | BLEND_DST_BACKDROP; |
#170495 - DiscoStew - Tue Sep 29, 2009 6:16 pm
Min wrote: |
Both the previous captured frame and the new 3D on top will be captured, adding another layer to the captured image each time the list is repeated ( but that you already know. :P ) Step 3-5 should complete before the screen needs to redraw, and therefore having the capture/bg bank in LCD mode during the capture shouldn't affect the display. |
Not quite sure about that, because the capture is done while the screen is refreshing.
Anyways, this is what I have currently
Code: |
glClearColor( 0, 0, 0, 0 );
videoSetMode( MODE_FB2 | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE | ENABLE_3D );
bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 24, 0);
swiWaitForVBlank();
render_Poly( 0 );
glFlush( 0 );
swiWaitForVBlank();
vramSetBankD( VRAM_D_LCD );
REG_DISPCAPCNT = DCAP_ENABLE | DCAP_MODE( 0 ) | DCAP_BANK( 3 ) | DCAP_SIZE( 3 ) | DCAP_SRC( 0 );
render_Poly( 1 );
glFlush( 0 );
swiWaitForVBlank();
vramSetBankC( VRAM_C_LCD );
vramSetBankD( VRAM_D_MAIN_BG );
REG_DISPCAPCNT = DCAP_ENABLE | DCAP_MODE( 0 ) | DCAP_BANK( 2 ) | DCAP_SIZE( 3 ) | DCAP_SRC( 0 );
swiWaitForVBlank();
iprintf( "\n%02X\n", VRAM_C[ 50 + ( 256 * 96 )] );
videoSetMode( MODE_FB2 );
while(1)
{
swiWaitForVBlank();
} |
What this does is renders the first polygon (of a set size and distance away) and flushes it, then in the next VBlank, sets the capture hardware while sending in the next polygon (which is smaller, a different color, and closer than the last one, so both should be seen if done right), and then the 2nd capture is done in the next frame into VRAM_C, and then it is displayed.
As it is right now, it will only show the most recent polygon. If I comment out the 2nd polygon, the first one shows up instead. So, setting the 2nd polygon back in, I went and examined the data outside the polygon. The value was 0x8000, meaning that it was solid black, which might explain why the polygon in the back isn't showing, because it is being overwritten.
_________________
DS - It's all about DiscoStew
#170499 - Min - Tue Sep 29, 2009 7:07 pm
Ah, you are right. I had a feeling I was mistaken about something vital, please ignore my previous post.
#170509 - Cydrak - Tue Sep 29, 2009 11:15 pm
Hmm.. so you're trying to composite frames by capturing the 2D engine. Neat. I don't know a way to do it in one bank, sorry.
I think your bitmap needs modes 3-5 though, and that's why it's not capturing. I ran into a related issue myself. To get it working, you'll have to define your own constants (see below).
Basically there are two things to care about: the BG mode and the display source, which are bits 0-3 and 16-20 of REG_DISPCNT, respectively. (And as far as I could tell, despite living in the same register, the display source has no relation to the 2D engine, besides allowing you to actually see it! Completely bonkers, I know.)
The trouble with libnds "video modes" is that they implicitly assign both these settings. This means they'll conflict if you try to set MODE_FB2 | MODE_3_3D for example, even though it makes sense. So, have a look at GBATek:DISPCNT. You're probably interested in display source = 2+8 and BG mode = 3+8... nicely defined, it'd look something like DISPLAY_SRC_FB2 + BG_MODE_3 + BG_ENABLE_3D.
#170518 - DiscoStew - Wed Sep 30, 2009 4:16 am
I think that did it. The background (when not setting it) was kept at 4 Text BGs, so when I added 0x0003 to the videoSetMode function (which sets the mode to BG0-BG2 as Text, and BG3 as Extended), it was then showing both, one in front of the other. Exactly what I wanted.
I was excited until I tested translucent polygons. It wasn't working, but then I referred back to Min's post about it, so I added in that line in teh appropriate spot, and added another poly to get rendered for the 2nd pass. One was at 50%, and the other at 100%, both next to each other,and both covering part of the poly in back. Result?
Exactly how you'd imagine it would look. I got quite giddy when seeing it work on both emulator and hardware. Thank you all for helping me with this.
_________________
DS - It's all about DiscoStew