Quake 3 lightmaps - PVR Multi-Texture

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

So, I had started working on some code to parse and render Quake 3 bsp's.
viewtopic.php?f=29&t=102059&start=20#p1034000
I put a pause on that when I realized that for more reason than one, KGLX was not really well suited for such a task.
As I have since decided to build my own GL api, I have enough finished to start looking back at getting Quake 3 bsps running.

One thing that bothered me, was getting lightmaps to render on the DC.

Essentially, Q3 lightmaps are just textures stored in the .bsp file, that are rendered on top of the base texture.
More modern builds of GL support multitexture, so the solution is quite simple in that case.
However, using the DC's PVR, the only way I can imagine is by sending each vertex twice to the PVR, once with the base texture data, and then again with a translucent vertex with the lightmap texture data.
From what I can tell, that is the solution this guy concluded
http://yam.20to4.net/dreamcast/index_old.html

Any thoughts welcome :P
Ayla
DC Developer
DC Developer
Posts: 142
Joined: Thu Apr 03, 2008 7:01 am
Has thanked: 0
Been thanked: 4 times
Contact:

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Ayla »

Can't you aggregate the two textures in vram, and render only the final texture?
User avatar
Bouz
DCEmu Junior
DCEmu Junior
Posts: 46
Joined: Mon May 10, 2010 3:42 pm
Location: St. Bauzille de Putois (France)
Has thanked: 0
Been thanked: 0

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Bouz »

You would probably have some strange when trying to display 2 triangles with the same coordinates. My feeling is that it would produce flickering unexpected results.
Are there many possible combinations of textures? I imagine it is nt possible to pre-aggregate them?
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by BlackAura »

There's no multitexture on the PVR, so you'd have to do multiple rendering passes.

That's what Quake 3 did on cards that didn't support multitexture, and for surfaces that needed more than two passes (some of the surfaces can have two or three layers, plus the lightmap). It's also what Quake 1 and 2 did on cards that didn't support multitexture.

Ayla / Bouz - Yes, it's possible to combine the textures with the lightmaps. That's actually how the software renderer in Quake 1 and Quake 2 works. It combines the textures and lightmaps, stores them in a surface cache, and then just draws from the cache using normal texture mapping. GLQuake and Quake 2 in OpenGL mode don't do this, because if you have hardware with fast alpha blending (3Dfx Voodoo cards, for instance) it's actually slower than just doing two rendering passes.

Quake 3's surfaces are too complicated to combine like that, because they can be animated, and have way more than just texture + lightmap.

Bouz - The flickering is called Z fighting. Usually, if you use exactly the same geometry (same vertices, sent in the same order) and the right depth compare mode, it won't be a problem. If it is, you can offset the lightmaps slightly from the surface, but that's kind of tricky to get right. I've never needed to do that on a PC though, and I don't think Quake / Quake 2 / Quake 3 did either.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

BlackAura wrote:There's no multitexture on the PVR, so you'd have to do multiple rendering passes.

That's what Quake 3 did on cards that didn't support multitexture, and for surfaces that needed more than two passes (some of the surfaces can have two or three layers, plus the lightmap). It's also what Quake 1 and 2 did on cards that didn't support multitexture.
Thank you for the informative, and obviously experienced responce.
That confirms my findings. Forgive me if I ask you more questions in the future :lol:
Bouz wrote:You would probably have some strange when trying to display 2 triangles with the same coordinates. My feeling is that it would produce flickering unexpected results.
As BlackAura mentioned, as long as you submit the verices correctly, there should be no problems.
In fact, the results can look quite nice, notice the blood splatter blends with the floor texture underneath, using a two-pass approach with the PVR.
Image
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

Bump on old thread :oops:

Thank you again BlackAura for your insight.

I never posted my results, after working on getting Quake 3 BSP's to render with Light Maps, using my build of OpenGL.
After I posted this, I had stopped working on the code and focused on other things.
However, I have recently started again from the beginning.

Interesting thing about the Quake 3 BSP format, is that the Light Maps are stored in the BSP file itself, while the decal, or base
textures are stored externally.
The light maps are stored as 24bit RGB textures, so all I needed to do was convert the 24bit colors to 16bit for use with the
PVR's 16bit RGB565 texture color format, and then bind to OpenGL.

For now, I am making a 3-pass render approach using hardware blending to achieve a multi-texture effect:
Pass 1: Submit Opaque Geometry
Pass 2: Submit Transparent Geometry ( determined by texture flags )
Pass 3: Submit Light Map Geometry

First Attempt: blending modes are set wrong!
Image

Adjusted the blending mode to smooth things out...
Image

Image

Image

CDi Demo of Posted Screens:
q3bsp-dc-a01.rar
OpenGL DC Quake 3 BSP Render Alpha 01 (C) PH3NOM 2014
(698.07 KiB) Downloaded 177 times
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

Bigger maps.
Reduced the Vertex Buffer size of Open GL to better match the PVR's limit, and increase the PVR's available texture memory.

LightMaps Disabled:
Image

LightMaps Enabled ( still need to work out a few details )
Image
YZB
DCEmu Cool Newbie
DCEmu Cool Newbie
Posts: 15
Joined: Sun Jun 11, 2006 11:51 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by YZB »

greet job :mrgreen:
Jae686
Insane DCEmu
Insane DCEmu
Posts: 112
Joined: Sat Sep 22, 2007 9:43 pm
Location: Braga - Portugal
Has thanked: 0
Been thanked: 0

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Jae686 »

PH3NOM wrote:So, I had started working on some code to parse and render Quake 3 bsp's.
viewtopic.php?f=29&t=102059&start=20#p1034000
I put a pause on that when I realized that for more reason than one, KGLX was not really well suited for such a task.
As I have since decided to build my own GL api, I have enough finished to start looking back at getting Quake 3 bsps running.

One thing that bothered me, was getting lightmaps to render on the DC.

Essentially, Q3 lightmaps are just textures stored in the .bsp file, that are rendered on top of the base texture.
More modern builds of GL support multitexture, so the solution is quite simple in that case.
However, using the DC's PVR, the only way I can imagine is by sending each vertex twice to the PVR, once with the base texture data, and then again with a translucent vertex with the lightmap texture data.
From what I can tell, that is the solution this guy concluded
http://yam.20to4.net/dreamcast/index_old.html

Any thoughts welcome :P
I just wished I had his source code [http://yam.20to4.net/dreamcast/index_old.html]. I wonder how much I could learn from them.
cube_b3
Ex-Newsposter
Ex-Newsposter
Posts: 4037
Joined: Tue May 28, 2002 6:51 am
Location: pakistan,karachi
Has thanked: 13 times
Been thanked: 5 times
Contact:

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by cube_b3 »

Looks good.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

Forgot to mention about the Frame Rate: those screens are without using the BSP PVS system, and without any sort of Frustum Culling.
My most recent build has implemented the BSP PVS system ( using the SH4's fast Vector Math Instructions ), and z-frustum culling ( could be optimized to full frustum culling ), and then finally using the facets of my Open GL API ( Near-Z Clipping ).
Jae686 wrote:I just wished I had his source code [http://yam.20to4.net/dreamcast/index_old.html]. I wonder how much I could learn from them.
I agree; it is a shame he has never posted on these forums or his sources.

In recent time, I have just decided to add software mip-map generation for my build of Open GL:
(the left image is the 512x512 texture scaled down to 320x320 by the PVR hardware, the right image is my software-generated mip-map at 256x256 being scaled up to 320x320 by the PVR hardware.
Image

I have been thinking of a way to do multi-texture much faster than the way I am currently doing it using my build of Open GL.

Basically right now, making 2 passes, I am submitting the geometry twice for each vertex.
This means each vertex gets possibly ( clipped, light, transformed ) each time submitted.
My idea is I can simply allow the submission of two separate textures ( opaque + alpha ) with almost no extra cost on the CPU, by computing the output vertex ( light, clipped, transformed ), then copy into each list ( opaque, alpha ).
Jae686
Insane DCEmu
Insane DCEmu
Posts: 112
Joined: Sat Sep 22, 2007 9:43 pm
Location: Braga - Portugal
Has thanked: 0
Been thanked: 0

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Jae686 »

And how does he make the radial blur ? does he copy the whole framebuffer to main memory and perform the blur ? (And if so, how can I get a pointer to the frame buffer) ?
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by BlueCrab »

You can have the PVR render the screen to a texture, which you'd have a pointer to (by virtue of the fact that you have to supply the texture pointer to render to). That's the easiest way to do it, probably.

Otherwise, if you really wanted to hack away at low-level stuff, you could get the frame buffer pointer and go that route as well. Just remember that if you do that and want to use it as a texture later, you'll either have to set it up as a strided texture or you'll have to resize it (whereas the render-to-texture stuff in KOS requires a power-of-two-sized texture to start with, so you can easily use it later as a regular texture).
Jae686
Insane DCEmu
Insane DCEmu
Posts: 112
Joined: Sat Sep 22, 2007 9:43 pm
Location: Braga - Portugal
Has thanked: 0
Been thanked: 0

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Jae686 »

BlueCrab wrote:You can have the PVR render the screen to a texture, which you'd have a pointer to (by virtue of the fact that you have to supply the texture pointer to render to). That's the easiest way to do it, probably.

Otherwise, if you really wanted to hack away at low-level stuff, you could get the frame buffer pointer and go that route as well. Just remember that if you do that and want to use it as a texture later, you'll either have to set it up as a strided texture or you'll have to resize it (whereas the render-to-texture stuff in KOS requires a power-of-two-sized texture to start with, so you can easily use it later as a regular texture).
So If i understood correctly I would basically allocate a texture in video memory render to it -> copy it into main memory -> do any sort of post-processing and then copy it again to VRAM? (I assume that messing directly on the VRAM would be slow).
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

Even on modern hardware, reading pixels from the GPU back to the CPU is a very slow process!
I have done so using Windows GDI, DirectX, as well as OpenGL.
Out of those, Open GL was the fastest mode, but it only copied its own frame buffer data, not that of Windows, so it did not do what I needed it to.
The CPU I am using is an AMD FX 8320, and GPU is AMD HD 7870, and struggled to hit 30fps at 1920x1080p.
This is an area where the new game consoles 'unified memory' architecture really has an advantage...
I have considered compressing the Frame Buffer on the GPU before sending it back to the CPU, but that is a different story altogether 8-)

Any how, that is not how the 'cheap' radial blur effect is achieved.

First, this would be hard to do in KGLX due to lack of render-to-texture. In my build of Open GL this should be easy to implement.

Take a look here (Dave brought this to my attention):
http://nehe.gamedev.net/tutorial/radial ... ure/18004/

It is a pretty simple effect that looks interesting ( I have not tried it yet, but will soon ) :grin:
Basic overview ( If I understand correctly from taking a very quick look at that page, Dave feel free to correct me):
1.) Set viewport to a smaller region of the screen ( the size of your render-to-texture )
2.) Render your entire scene at the smaller viewport to a texture
3.) Set the viewport to the full screen
4.) Render your entire scene again
5.) With blending enabled, make a loop over the rendered texture, drawing as 2d vertices to be overlaid on top of the 3d scene.
Each loop gradually changes the u/v values to gradually zoom in on the texture, while decreasing the alpha to fade the texture out.

I now plan to have a go at this effect, If successful I will add it as an example for my Open GL API. :roll:
Jae686
Insane DCEmu
Insane DCEmu
Posts: 112
Joined: Sat Sep 22, 2007 9:43 pm
Location: Braga - Portugal
Has thanked: 0
Been thanked: 0

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Jae686 »

Are you planning on adding support to vertex arrays on your API :P ?

When will we have a chance to give a try on your GL API (I'm getting quite curious :) ) ?
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

Yeah, I have implemented Vertex Arrays, in the form of glDrawArrays(...).
However, glDrawElements(...) not yet supported. If that is of interest to you, let me know, I will up that on my to-do list.

And things are working out nicely, as todays experiment has turned out successfully and allowed me to spot a few lingering bugs in the API, and fix them :lol:
Stay posted for an official release very soon.

Today in some short spare time I have successfully implemented the 'radial blur' effect on DC, using my Open GL API.

Radial Blur Disabled:
Image

Radial Blur Enabled:
Image

Looks pretty cool in motion, I have uploaded an elf here:
opengl-dc-radial-blur-01.rar
Open GL DC Radial Blur Demo (C) 2014 PH3NOM
(1.2 MiB) Downloaded 179 times
First off, we need to allocate some texture memory for the Render-To-Texture:
Spoiler!

Code: Select all

static pvr_ptr_t * RENDER_TEXTURE = NULL;
static GLuint      RENDER_TEXTURE_ID;
static long unsigned int RENDER_TEXTURE_W;
static long unsigned int RENDER_TEXTURE_H;

void InitRenderTexture(long unsigned int width, long unsigned int height)
{
    /* 1.) Allcoate PVR Texture Memory for Render-To-Texture */
	RENDER_TEXTURE_W = width;
	RENDER_TEXTURE_H = height;
	RENDER_TEXTURE = pvr_mem_malloc(RENDER_TEXTURE_W * RENDER_TEXTURE_H * 2); 
    
	/* 2.) Generate a texture for Open GL, and bind that texxture */
	glGenTextures(1, &RENDER_TEXTURE_ID);
    glBindTexture(GL_TEXTURE_2D, RENDER_TEXTURE_ID);
    
	/* 3.) Use glKosTexImage2D() to bind the texture address for the Render-To-Texture */
	glKosTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                    RENDER_TEXTURE_W, RENDER_TEXTURE_H, 0,
                    PVR_TXRFMT_NONTWIDDLED, PVR_TXRFMT_RGB565, RENDER_TEXTURE);

    /* 4.) Enable GL_LINEAR Texture Filter to enable the PVR's bilinear filtering */              
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FILTER, GL_LINEAR);
}
After that, rendering the scene is pretty much what I described earlier:
Spoiler!

Code: Select all

		if(enable_radial) /* Render scene with radial blur */
		{
            /* Set Screen Viewport to top left  of screen */
            glViewport(0, vid_mode->height - RENDER_TEXTURE_H, RENDER_TEXTURE_W, RENDER_TEXTURE_H);

			glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            /* Draw the GL "scene" */
            draw_gl();

		    /* Render the submitted vertex data to a Texture */
			glutSwapBuffersToTexture(RENDER_TEXTURE, &RENDER_TEXTURE_W, &RENDER_TEXTURE_H);

            /* Set Screen Viewport to top left  of screen with Scissor test window set to the Viewport */
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
		    glViewport(0, 0, vid_mode->width, vid_mode->height);

			/* Submit the Vertex Data for the scene ( just a qube, heh ) */
		    draw_gl();

			/* Now, Render the "Radial Blur" Post-Process Effect */
		    RenderBlurEffect(25, 0.02f);

		    /* Submit Vertex Data to GPU for Display */
		    glutSwapBuffers();
		}
		else /* Render scene with no radial blur */
		{
            /* Fullscreen glViewport - only effects the internal GL screenview matrix */
            glViewport(0, 0, vid_mode->width, vid_mode->height);

			glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            /* Draw the GL "scene" */
            draw_gl();

		    /* Submit Vertex Data to GPU for Display */
		    glutSwapBuffers();
		}
From that, the 'radial blur' is achieved by submitting the render-to-texture result as a 2D quad overlaid on top of the 3D scene:
Spoiler!
void RenderBlurEffect(int times, float inc)

{
float spost = 0.0f; // Starting Texture Coordinate Offset
float alphainc = 0.9f / times; // Fade Speed For Alpha Blending
float alpha = 0.2f; // Starting Alpha Value

#ifdef DEBUG_NULL_DC // Null DC does not accuratley handle render-to-texture u/v coords
float U = RENDER_TEXTURE_W / (float)vid_mode->width;
float V = RENDER_TEXTURE_H / (float)vid_mode->height;
#else
float U = 1.0f;
float V = 1.0f;
#endif
float W = (float)vid_mode->width;
float H = (float)vid_mode->height;

glDisable(GL_LIGHTING); // Disable GL Lighting
glDisable(GL_DEPTH_TEST); // Disable Depth Testing
glEnable(GL_TEXTURE_2D); // Enable 2D Texture Mapping
glEnable(GL_BLEND); // Enable Blending

glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Set Blending Mode

glBindTexture(GL_TEXTURE_2D, RENDER_TEXTURE_ID); // Bind The Rendered Texture

alphainc = alpha / times; // alphainc=0.2f / Times To Render Blur

glBegin(GL_QUADS);

while(times--) // Number Of Times To Render Blur
{
glColor4f(1.0f, 1.0f, 1.0f, alpha); // Set The Alpha Value (Starts At 0.2)

glTexCoord2f(0 + spost, 0 + spost);
glVertex2f(0, 0);

glTexCoord2f(U - spost, 0 + spost);
glVertex2f(W, 0);

glTexCoord2f(U - spost, V - spost);
glVertex2f(W, H);

glTexCoord2f(0 + spost, V - spost);
glVertex2f(0, H);

spost += inc; // Gradually Increase spost (Zooming Closer To Texture Center)

alpha = alpha - alphainc; // Gradually Decrease alpha (Gradually Fading Image Out)
}

glEnd();

glDisable(GL_TEXTURE_2D); // Disable 2D Texture Mapping
glDisable(GL_BLEND); // Disable Blending
glEnable(GL_DEPTH_TEST); // Enable Depth Testing
glEnable(GL_LIGHTING); // Enable Lighting
}
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by PH3NOM »

As it turns out, for radial blur, it is not necessary to render at a smaller viewport.
And I would actually advise against it. Just render to your texture at your normal viewport.

Why? Because I have just implemented a way to copy your submitted vertex data to the PVR for render-to-texture without having to wipe the buffers in main ram.
This means instead of having to compute and submit the final vertex twice( light, clipped, transformed ), it will only need to be calculated once.
But this only works right if you do not change the viewport.

The only drawback is that the PVR memory requires a 1024x512 texture to fit the 640x480 screen, as opposed to rendering to a smaller texture.

Image

Here is the updated code from above:

Code: Select all

		if(enable_radial) /* Render scene with radial blur */
		{
            /* Draw the GL "scene" */
            draw_gl();

		    /* Render the submitted vertex data to a Texture */
			glutCopyBufferToTexture(RENDER_TEXTURE, &RENDER_TEXTURE_W, &RENDER_TEXTURE_H);

			/* Now, Render the "Radial Blur" Post-Process Effect */
		    RenderBlurEffect(25, 0.02f);

		    /* Submit Vertex Data to GPU for Display */
		    glutSwapBuffers();
		}
		else /* Render scene with no radial blur */
		{
            /* Draw the GL "scene" */
            draw_gl();

		    /* Submit Vertex Data to GPU for Display */
		    glutSwapBuffers();
		}
User avatar
Christuserloeser
Moderator
Moderator
Posts: 5948
Joined: Thu Aug 28, 2003 12:16 am
Location: DCEvolution.net
Has thanked: 10 times
Been thanked: 0
Contact:

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Christuserloeser »

Image
Insane homebrew collector.
Jae686
Insane DCEmu
Insane DCEmu
Posts: 112
Joined: Sat Sep 22, 2007 9:43 pm
Location: Braga - Portugal
Has thanked: 0
Been thanked: 0

Re: Quake 3 lightmaps - PVR Multi-Texture

Post by Jae686 »

Looks excellent! I cant wait to try it out ! :)
Post Reply