Files
fs2open.github.com/code/graphics/GrD3DParticle.cpp
T
2004-07-26 20:47:56 +00:00

138 lines
3.4 KiB
C++

/*
* Code created by Thomas Whittaker (RT) for a Freespace 2 source code project
*
* You may not sell or otherwise commercially exploit the source or things you
* created based on the source.
*
*/
#include <d3d8.h>
#include "graphics/GrD3DInternal.h"
#include "graphics/GrD3DLight.h"
#include "particle/particle.h"
#include "cmdline/cmdline.h"
#include "GrD3DParticle.h"
D3DPOINTVERTEX Particle_list[MAX_PARTICLES];
int Current_index = 0;
float rt_pointsize = 3.0f;
float rt_pointsize_A = 1.0f;
float rt_pointsize_B = 0.9f;
float rt_pointsize_C = 0.8f;
bool d3d_particle_init()
{
return true;
}
void d3d_particle_deinit()
{
}
// If this function returns false the particle will not be rendered and steps should be
// taken to render it by another method
bool gr_d3d_particle_set(vertex *pos, int bitmap_id, float size)
{
if(Cmdline_d3d_particle == 0) return false;
if(pos == NULL) return false;
if(Current_index >= MAX_PARTICLES) return false;
// Better cap the particle size just incase
if(size >= GlobalD3DVars::d3d_caps.MaxPointSize) {
return false;
}
Particle_list[Current_index].x = pos->x;
Particle_list[Current_index].y = pos->y;
Particle_list[Current_index].z = pos->z;
Particle_list[Current_index].size = size;
Particle_list[Current_index].custom = bitmap_id;
Current_index++;
return true;
}
void gr_d3d_particle_reset_list()
{
Current_index = 0;
}
int qsort_texture_compare_func(const void *elem1, const void *elem2 )
{
D3DPOINTVERTEX *p1 = (D3DPOINTVERTEX *) elem1;
D3DPOINTVERTEX *p2 = (D3DPOINTVERTEX *) elem2;
if(p1->custom > p2->custom)
return 1;
else
return 0;
}
inline DWORD FtoDW( float f ) { return *((DWORD*)&f); }
bool gr_d3d_particle_render_list()
{
if(Current_index == 0) return true;
// Set the render states for using point sprites
d3d_SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
d3d_SetRenderState( D3DRS_POINTSCALEENABLE, TRUE );
d3d_SetRenderState( D3DRS_POINTSIZE_MIN, FtoDW(0.0f) );
d3d_SetRenderState( D3DRS_POINTSIZE, FtoDW(rt_pointsize) );
d3d_SetRenderState( D3DRS_POINTSCALE_A, FtoDW(rt_pointsize_A) );
d3d_SetRenderState( D3DRS_POINTSCALE_B, FtoDW(rt_pointsize_B) );
d3d_SetRenderState( D3DRS_POINTSCALE_C, FtoDW(rt_pointsize_C) );
// Sort by texture (only if its worth doing)
if(Current_index > 10)
qsort( Particle_list, Current_index, sizeof(D3DPOINTVERTEX), qsort_texture_compare_func);
// Set engine requirements
// Render particles in batches
int render_from = 0;
int i = 0;
DWORD current_texture = Particle_list[0].custom;
HRESULT hr = 0;
while(i < Current_index) {
if(current_texture != Particle_list[i].custom)
{
// Render that batch
gr_set_bitmap(current_texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f);
float u, v;
gr_tcache_set(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u, &v);
gr_d3d_set_state(TEXTURE_SOURCE_DECAL, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_READ );
hr += d3d_DrawPrimitive(
D3DVT_PVERTEX,
D3DPT_POINTLIST,
&Particle_list[render_from],
i - render_from);
// if((i - render_from) > 5)
// mprintf(("Particle render: %d\n",i - render_from));
// Get the next texture and mark the start of the next batch
current_texture = Particle_list[i].custom;
render_from = i;
}
i++;
}
d3d_SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
d3d_SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );
return (hr == 0);
}