Files
fs2open.github.com/code/graphics/grd3d.cpp
T
portej05 719825f80d The big CVS comment removal. This chops approx. 3.5mb off a full checkout.
I've tested this through compiling and through hand checking. 
Normalises line endings in ALL files to \n.
2009-06-20 08:08:20 +00:00

2190 lines
64 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#ifndef NO_DIRECT3D
#include <math.h>
#include <d3d8.h>
#include <D3dx8tex.h>
#include <Dxerr8.h>
#include "graphics/2d.h"
#include "globalincs/systemvars.h"
#include "globalincs/alphacolors.h"
#include "graphics/grinternal.h"
#include "graphics/grd3d.h"
#include "graphics/grd3dinternal.h"
#include "graphics/grd3dlight.h"
#include "graphics/grd3dbmpman.h"
#include "osapi/osapi.h"
#include "bmpman/bmpman.h"
#include "io/key.h"
#include "math/floating.h"
#include "palman/palman.h"
#include "osapi/osregistry.h"
#include "graphics/line.h"
#include "graphics/font.h"
#include "io/mouse.h"
#include "cfile/cfile.h"
#include "cmdline/cmdline.h"
#include "debugconsole/timerbar.h"
#include "debugconsole/dbugfile.h"
#include "freespace2/freespaceresource.h"
#include "cmdline/cmdline.h"
#include <vector>
enum vertex_buffer_type{TRILIST_,LINELIST_,FLAT_};
// Structures and enums
struct Vertex_buffer {
Vertex_buffer() { memset(this, 0, sizeof(Vertex_buffer)); };
int n_prim;
int n_verts;
vertex_buffer_type type;
uint FVF;
int size;
IDirect3DVertexBuffer8 *buffer;
};
enum stage_state{
NONE = -1,
INITIAL = 0,
DEFUSE = 1,
GLOW_MAPPED_DEFUSE = 2,
NONMAPPED_SPECULAR = 3,
GLOWMAPPED_NONMAPPED_SPECULAR = 4,
MAPPED_SPECULAR = 5, CELL = 6,
GLOWMAPPED_CELL = 7,
ADDITIVE_GLOWMAPPING = 8,
SINGLE_PASS_SPECMAPPING = 9,
SINGLE_PASS_GLOW_SPEC_MAPPING = 10,
BACKGROUND_FOG = 11,
ENV = 12
};
//LPDIRECT3DCUBETEXTURE8 cube_map;
// External variables - booo!
extern bool env_enabled;
extern matrix View_matrix;
extern vec3d View_position;
extern matrix Eye_matrix;
extern vec3d Eye_position;
extern vec3d Object_position;
extern matrix Object_matrix;
extern float Canv_w2; // Canvas_width / 2
extern float Canv_h2; // Canvas_height / 2
extern float View_zoom;
extern int G3_user_clip;
extern vec3d G3_user_clip_normal;
extern vec3d G3_user_clip_point;
static int D3d_dump_frames = 0;
static ubyte *D3d_dump_buffer = NULL;
static int D3d_dump_frame_number = 0;
static int D3d_dump_frame_count = 0;
static int D3d_dump_frame_count_max = 0;
static int D3d_dump_frame_size = 0;
// Variables
stage_state current_render_state = NONE;
int In_frame = 0;
IDirect3DSurface8 *Gr_saved_surface = NULL;
std::vector<Vertex_buffer> D3D_vertex_buffers;
static int D3D_vertex_buffers_in_use = 0;
extern int n_active_lights;
D3DXPLANE d3d_user_clip_plane;
IDirect3DSurface8 *old_render_target = NULL;
//IDirect3DTexture8 *background_render_target = NULL;
// Function declarations
void shift_active_lights(int pos);
void pre_render_lights_init();
const char *d3d_error_string(HRESULT error);
void d3d_string_mem_use(int x, int y)
{
char mem_buffer[50];
sprintf(mem_buffer,"Texture mem free: %d Meg", GlobalD3DVars::lpD3DDevice->GetAvailableTextureMem()/1024/1024);
gr_string( x, y, mem_buffer);
}
void d3d_fill_pixel_format(PIXELFORMAT *pixelf, D3DFORMAT tformat);
// Whats all this then? Can we get rid of it? - RT
// LPVOID lpBufStart, lpPointer, lpInsStart;
// int Exb_size;
void gr_d3d_exb_flush(int end_of_frame)
{
/*
HRESULT ddrval;
D3DEXECUTEBUFFERDESC debDesc;
D3DEXECUTEDATA d3dExData;
if ( DrawPrim ) {
return;
}
if (!lpExBuf) return;
OP_EXIT( D3D_ex_ptr );
lpPointer = lpInsStart;
OP_PROCESS_VERTICES( 1, lpPointer );
PROCESSVERTICES_DATA( D3DPROCESSVERTICES_COPY, 0, D3D_num_verts, lpPointer );
ddrval = lpExBuf->Unlock();
if (ddrval != DD_OK ) {
mprintf(( "Failed to unlock the execute buffer!\n" ));
goto D3DError;
}
memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
d3dExData.dwVertexCount = D3D_num_verts;
d3dExData.dwInstructionOffset = (ULONG)((char*)lpInsStart - (char*)lpBufStart);
d3dExData.dwInstructionLength = (ULONG)((char*)D3D_ex_ptr - (char*)lpInsStart);
// if (end_of_frame==0) {
// mprintf(( "Flushing execute buffer in frame, %d verts, %d data size!\n", D3D_num_verts, d3dExData.dwInstructionLength ));
// } else if (end_of_frame==2) {
// mprintf(( "Flushing execute buffer in frame, because of VRAM flush!\n" ));
// }
ddrval = lpExBuf->SetExecuteData(&d3dExData);
if (ddrval != DD_OK ) {
mprintf(( "Failed to SetExecuteData!\n" ));
goto D3DError;
}
ddrval = lpD3DDeviceEB->Execute( lpExBuf, lpViewport, D3DEXECUTE_UNCLIPPED );
if (ddrval != DD_OK ) {
mprintf(( "Failed to Execute! nverts=%d\n", D3D_num_verts));
mprintf(( "(%s)\n", d3d_error_string(ddrval) ));
goto D3DError;
}
memset( &debDesc, 0, sizeof( debDesc ) );
debDesc.dwSize = sizeof( debDesc );
ddrval = lpExBuf->Lock( &debDesc );
if ( ddrval != DD_OK ) {
mprintf(( "Failed to lock the execute buffer!\n" ));
goto D3DError;
}
lpPointer = lpBufStart = lpInsStart = debDesc.lpData;
lpPointer = (void *)((uint)lpPointer+sizeof(D3DTLVERTEX)*D3D_MAX_VERTS);
lpInsStart = lpPointer;
OP_PROCESS_VERTICES( 1, lpPointer );
PROCESSVERTICES_DATA( D3DPROCESSVERTICES_COPY, 0, 1, lpPointer );
D3D_num_verts = 0;
D3D_ex_ptr = lpPointer;
D3D_ex_end = (void *)((uint)lpBufStart + Exb_size - 1024);
D3D_vertices = (D3DTLVERTEX *)lpBufStart;
return;
D3DError:
// Reset everything
if ( lpExBuf ) {
lpExBuf->Release();
lpExBuf = NULL;
}
// gr_d3d_cleanup();
// exit(1);
*/
}
// No objects should be rendered before this frame
void d3d_start_frame()
{
if(!GlobalD3DVars::D3D_activate) return;
HRESULT ddrval;
if (!GlobalD3DVars::D3D_inited) return;
if ( In_frame < 0 || In_frame > 1 ) {
mprintf(( "Start frame error! (%d)\n", In_frame ));
return;
}
if ( In_frame == 1 ) return;
In_frame++;
ddrval = GlobalD3DVars::lpD3DDevice->BeginScene();
if (ddrval != D3D_OK ) {
//mprintf(( "Failed to begin scene!\n%s\n", d3d_error_string(ddrval) ));
return;
}
}
// No objects should be rendered after this frame
void d3d_stop_frame()
{
if (!GlobalD3DVars::D3D_inited) return;
if(!GlobalD3DVars::D3D_activate) return;
if ( In_frame < 0 || In_frame > 1 ) {
mprintf(( "Stop frame error! (%d)\n", In_frame ));
return;
}
if ( In_frame == 0 ) return;
In_frame--;
if(GlobalD3DVars::D3D_activate)TIMERBAR_END_FRAME();
if(FAILED(GlobalD3DVars::lpD3DDevice->EndScene()))
{
return;
}
TIMERBAR_START_FRAME();
TIMERBAR_PUSH(1);
// Must cope with device being lost
if(GlobalD3DVars::lpD3DDevice->Present(NULL,NULL,NULL,NULL) == D3DERR_DEVICELOST)
{
d3d_lost_device();
}
TIMERBAR_POP();
}
// This function calls these render state one when the device is initialised and when the device is lost.
void d3d_set_initial_render_state(bool set)
{
if(current_render_state == INITIAL)return;
if(current_render_state == NONE){//this only needs to be done the first time-Bobboau
d3d_SetRenderState(D3DRS_DITHERENABLE, TRUE );
d3d_SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
d3d_SetRenderState(D3DRS_SPECULARENABLE, FALSE );
// Turn lighting off here, its on by default!
d3d_SetRenderState(D3DRS_LIGHTING , FALSE);
}
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE), set, set;
d3d_SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR , set, set);
d3d_SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR , set, set);
d3d_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR , set, set);
d3d_SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR , set, set);
d3d_SetTexture(1, NULL);
d3d_SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 4, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(initial_state_block);
current_render_state = INITIAL;
}
//BACKGROUND_FOG
void set_stage_for_background_fog(bool set){
if(current_render_state == BACKGROUND_FOG)return;
/*
if(!set){
//d3d_proj_fov
//d3d_proj_ratio;
float fov = (1.0/d3d_proj_fov) * 0.65; // I don't know whay this needs to be 0.65 ???
// int timestamp();
// float distort = sin(float(timestamp()) / 1000.0);
float distort = 0.0;
D3DXMATRIX world;
D3DXMATRIX cloak(
fov, 0, 0, 0,
0, -fov * d3d_proj_ratio, 0, 0,
0.5, 0.5, 1, 0,
0, 0, 0, 1);
D3DXMATRIX corection(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, -1, 1);
D3DXMatrixMultiply(&world, &corection, &cloak);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_TEXTURE0, &world);
}
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1, set, set);
d3d_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTexture(0, background_render_target);
*/ if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(background_fog_state_block);
current_render_state = BACKGROUND_FOG;
}
extern bool env_enabled;
void set_stage_for_cell_shaded(bool set){
if(current_render_state == CELL)return;
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT , set, set);
d3d_SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT , set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(cell_state_block);
current_render_state = CELL;
}
void set_stage_for_cell_glowmapped_shaded(bool set){
if(current_render_state == GLOWMAPPED_CELL)return;
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT, set, set );
d3d_SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT, set, set );
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_ADD, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(glow_mapped_cell_state_block);
current_render_state = GLOWMAPPED_CELL;
}
void set_stage_for_additive_glowmapped(bool set){
if(current_render_state == ADDITIVE_GLOWMAPPING)return;
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(additive_glow_mapping_state_block);
current_render_state = ADDITIVE_GLOWMAPPING;
}
void set_stage_for_defuse(bool set){
if(current_render_state == DEFUSE)return;
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTexture(1, NULL);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(defuse_state_block);
current_render_state = DEFUSE;
}
void set_stage_for_glow_mapped_defuse(bool set){
if(current_render_state == GLOW_MAPPED_DEFUSE)return;
if(!set && GLOWMAP < 0){
set_stage_for_defuse();
return;
}
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADD, set, set);
// d3d_SetTexture(1, GLOWMAP);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(glow_mapped_defuse_state_block);
current_render_state = GLOW_MAPPED_DEFUSE;
}
void set_stage_for_defuse_and_non_mapped_spec(bool set){
if(current_render_state == NONMAPPED_SPECULAR)return;
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_SPECULAR, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADD, set, set);
d3d_SetTexture(1, NULL);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(nonmapped_specular_state_block);
current_render_state = NONMAPPED_SPECULAR;
}
void set_stage_for_glow_mapped_defuse_and_non_mapped_spec(bool set){
if(current_render_state == GLOWMAPPED_NONMAPPED_SPECULAR)return;
if(!set && GLOWMAP < 0){
set_stage_for_defuse_and_non_mapped_spec();
return;
}
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADD, set, set);
// d3d_SetTexture(1, GLOWMAP);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_SPECULAR, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_ADD, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(glow_mapped_nonmapped_specular_state_block);
current_render_state = GLOWMAPPED_NONMAPPED_SPECULAR;
}
bool set_stage_for_spec_mapped(bool set){
if(current_render_state == MAPPED_SPECULAR)return true;
if(!set && SPECMAP < 0){
// Error(LOCATION, "trying to set stage when there is no specmap");
return false;
}
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_SPECULAR, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE4X, set, set);
// d3d_SetTexture(0, SPECMAP);
d3d_SetTexture(1, NULL);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
current_render_state = MAPPED_SPECULAR;
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(mapped_specular_state_block);
return true;
}
extern bool texture_has_alpha(int t_idx);
bool set_stage_for_env_mapped(bool set){
if(current_render_state == ENV)return true;
if(!set && SPECMAP < 0){
// Error(LOCATION, "trying to set stage when there is no specmap");
return false;
}
// D3DXMATRIX world;
if(!set){
D3DXMATRIX world(
Eye_matrix.vec.rvec.xyz.x, Eye_matrix.vec.rvec.xyz.y, Eye_matrix.vec.rvec.xyz.z, 0,
Eye_matrix.vec.uvec.xyz.x, Eye_matrix.vec.uvec.xyz.y, Eye_matrix.vec.uvec.xyz.z, 0,
Eye_matrix.vec.fvec.xyz.x, Eye_matrix.vec.fvec.xyz.y, Eye_matrix.vec.fvec.xyz.z, 0,
0, 0, 0, 1);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_TEXTURE1, &world);
}
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 0, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
// d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
// if(texture_has_alpha(SPECMAP))
if(Cmdline_alpha_env)
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE, set, set);
else
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1, set, set);
// d3d_SetTexture(0, SPECMAP);
// if(!set)d3d_SetTexture(1, cube_map);
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE, set, set);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE, set, set);
// d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_PREMODULATE, set, set);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE, set, set);
//D3DTOP_BLENDTEXTUREALPHA
current_render_state = ENV;
if(!set)GlobalD3DVars::lpD3DDevice->ApplyStateBlock(env_state_block);
return true;
}
//glow texture stage 3
void set_stage_for_single_pass_glow_specmapping(int SAME){
//D3DPMISCCAPS_TSSARGTEMP
static int same = -1;
// if((current_render_state == SINGLE_PASS_GLOW_SPEC_MAPPING) && (same == SAME))return;
if(SPECMAP < 0)return;
if(GLOWMAP < 0){
// set_stage_for_single_pass_specmapping(SAME);
return;
}
float u_scale = 1.0f, v_scale = 1.0f;
if(!SAME){
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADD);
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_CURRENT);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_SPECULAR);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_TEXTURE);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_MODULATE4X);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_TEMP );
d3d_SetTextureStageState( 3, D3DTSS_COLORARG1, D3DTA_CURRENT);
d3d_SetTextureStageState( 3, D3DTSS_COLORARG2, D3DTA_TEMP);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_ADD);
d3d_SetTextureStageState( 3, D3DTSS_RESULTARG, D3DTA_CURRENT);
same = SAME;
}else{
gr_screen.gf_set_bitmap(SPECMAP, gr_screen.current_alphablend_mode, gr_screen.current_bitblt_mode, 0.0);
d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 1);
gr_screen.gf_set_bitmap(GLOWMAP, gr_screen.current_alphablend_mode, gr_screen.current_bitblt_mode, 0.0);
d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 5);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_SPECULAR);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
d3d_SetTextureStageState( 1, D3DTSS_RESULTARG, D3DTA_TEMP);
d3d_SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
d3d_SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
d3d_SetTextureStageState( 2, D3DTSS_RESULTARG, D3DTA_CURRENT);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEMP);
d3d_SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT);
d3d_SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_MODULATE4X);
d3d_SetTextureStageState( 3, D3DTSS_RESULTARG, D3DTA_TEMP);
d3d_SetTextureStageState( 3, D3DTSS_COLORARG1, D3DTA_TEMP);
d3d_SetTextureStageState( 3, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
d3d_SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_MODULATE);
d3d_SetTextureStageState( 4, D3DTSS_RESULTARG, D3DTA_CURRENT);
d3d_SetTextureStageState( 4, D3DTSS_COLORARG1, D3DTA_TEMP);
d3d_SetTextureStageState( 4, D3DTSS_COLORARG2, D3DTA_CURRENT);
d3d_SetTextureStageState( 4, D3DTSS_COLOROP, D3DTOP_ADD);
d3d_SetTextureStageState( 5, D3DTSS_RESULTARG, D3DTA_CURRENT);
d3d_SetTextureStageState( 5, D3DTSS_COLORARG1, D3DTA_CURRENT);
d3d_SetTextureStageState( 5, D3DTSS_COLORARG2, D3DTA_TEXTURE);
d3d_SetTextureStageState( 5, D3DTSS_COLOROP, D3DTOP_ADD);
same = SAME;
}
current_render_state = SINGLE_PASS_GLOW_SPEC_MAPPING;
}
void set_stage_for_mapped_environment_mapping(){
/* if(ENVMAP > 0 && env_enabled){
d3d_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 1);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_CURRENT);
d3d_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_ADD);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
}else{
d3d_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
d3d_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
}
state = INITIAL;*/
}
extern bool d3d_init_device();
void gr_d3d_flip()
{
if(!GlobalD3DVars::D3D_activate) return;
int mx, my;
// Attempt to allow D3D8 to recover from task switching
// this can't work if it's NULL, check reversed - taylor
if ( GlobalD3DVars::lpD3DDevice == NULL ) {
// we really lost the device, try a reinit
if ( !d3d_init_device() )
Assert( 0 );
}
// if the device is not going to be available then just loop around until we get it back
// Returns:
// TRUE = the device is lost and cannot be recovered yet
// FALSE = the device is fine or has been successfully reset
if ( d3d_lost_device() )
return;
gr_reset_clip();
mouse_eval_deltas();
if ( mouse_is_visible() ) {
gr_reset_clip();
mouse_get_pos( &mx, &my );
if ( Gr_cursor != -1 ) {
gr_set_bitmap(Gr_cursor);
gr_bitmap( mx, my, false);
}
}
d3d_stop_frame();
d3d_tcache_frame();
d3d_start_frame();
}
void gr_d3d_flip_cleanup()
{
d3d_stop_frame();
}
void gr_d3d_flip_window(uint _hdc, int x, int y, int w, int h )
{
}
void gr_d3d_fade_in(int instantaneous)
{
}
void gr_d3d_fade_out(int instantaneous)
{
}
void d3d_setup_format_components(PIXELFORMAT *surface, color_gun *r_gun, color_gun *g_gun, color_gun *b_gun, color_gun *a_gun);
int gr_d3d_save_screen()
{
int rect_size_x;
int rect_size_y;
if(!GlobalD3DVars::D3D_activate) return -1;
gr_reset_clip();
if (GlobalD3DVars::lpD3D == NULL)
return -1;
if ( Gr_saved_surface ) {
mprintf(( "Screen alread saved!\n" ));
return -1;
}
IDirect3DSurface8 *front_buffer_a8r8g8b8 = NULL;
D3DDISPLAYMODE mode;
mode.Width = mode.Height = 0;
// although this doesn't really matter in fullscreen mode it doesn't hurt either
if (FAILED(GlobalD3DVars::lpD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode)))
{
DBUGFILE_OUTPUT_0("Could not get adapter display mode");
return -1;
}
// we get the full mode size which for windowed mode is the entire screen and not just the window
// Problem that we can only get front buffer in A8R8G8B8
mprintf(("Creating surface for front buffer of size: %d %d", mode.Width, mode.Height));
if(FAILED(GlobalD3DVars::lpD3DDevice->CreateImageSurface(
mode.Width, mode.Height, D3DFMT_A8R8G8B8, &front_buffer_a8r8g8b8))) {
DBUGFILE_OUTPUT_0("Failed to create image surface");
return -1;
}
if(FAILED(GlobalD3DVars::lpD3DDevice->GetFrontBuffer(front_buffer_a8r8g8b8))) {
DBUGFILE_OUTPUT_0("Failed to get front buffer");
goto Failed;
}
// Get the back buffer format
PIXELFORMAT dest_format;
color_gun r_gun, g_gun, b_gun, a_gun;
d3d_fill_pixel_format( &dest_format, GlobalD3DVars::d3dpp.BackBufferFormat);
d3d_setup_format_components(&dest_format, &r_gun, &g_gun, &b_gun, &a_gun);
// Create a surface of a compatable type
if(FAILED(GlobalD3DVars::lpD3DDevice->CreateImageSurface(
gr_screen.max_w, gr_screen.max_h,
GlobalD3DVars::d3dpp.BackBufferFormat, &Gr_saved_surface))) {
DBUGFILE_OUTPUT_0("Failed to create image surface");
goto Failed;
}
// Make a copy of the thing
D3DLOCKED_RECT src_rect;
D3DLOCKED_RECT dst_rect;
if(FAILED(Gr_saved_surface->LockRect(&dst_rect, NULL, 0))) {
DBUGFILE_OUTPUT_0("Failed to lock save buffer");
goto Failed;
}
RECT rct;
if (GlobalD3DVars::D3D_window) {
POINT pnt;
pnt.x = pnt.y = 0;
HWND wnd = (HWND)os_get_window();
ClientToScreen(wnd, &pnt);
rct.left = pnt.x;
rct.top = pnt.y;
if(pnt.x < 0) {
rct.left = 0;
}
if(pnt.y < 0) {
rct.top = 0;
}
//We can't write to anything larger than the desktop resolution, so check against it
if((UINT)(pnt.x + gr_screen.max_w) > mode.Width) {
rct.right = mode.Width;
}
else {
rct.right = pnt.x + gr_screen.max_w;
}
//And again
if((UINT)(pnt.y + gr_screen.max_h) > mode.Height) {
rct.bottom = mode.Height;
}
else{
rct.bottom = pnt.y + gr_screen.max_h;
}
} else {
rct.left = rct.top = 0;
rct.right = gr_screen.max_w;
rct.bottom = gr_screen.max_h;
}
//Find the total size of our rectangle
rect_size_x = rct.right - rct.left;
rect_size_y = rct.bottom - rct.top;
if(FAILED(front_buffer_a8r8g8b8->LockRect(&src_rect, &rct, D3DLOCK_READONLY))) {
DBUGFILE_OUTPUT_0("Failed to lock front buffer");
goto Failed;
}
typedef struct { unsigned char b,g,r,a; } TmpC;
if(gr_screen.bits_per_pixel == 32) {
for(int j = 0; j < (rect_size_y); j++) {
TmpC *src = (TmpC *) (((char *) src_rect.pBits) + (src_rect.Pitch * j));
uint *dst = (uint *) (((char *) dst_rect.pBits) + (dst_rect.Pitch * j));
for(int i = 0; i < (rect_size_x); i++) {
dst[i] = 0;
dst[i] |= (uint)(( (int) src[i].r / r_gun.scale ) << r_gun.shift);
dst[i] |= (uint)(( (int) src[i].g / g_gun.scale ) << g_gun.shift);
dst[i] |= (uint)(( (int) src[i].b / b_gun.scale ) << b_gun.shift);
}
}
} else {
for(int j = 0; j < (rect_size_y); j++) {
TmpC *src = (TmpC *) (((char *) src_rect.pBits) + (src_rect.Pitch * j));
ushort *dst = (ushort *) (((char *) dst_rect.pBits) + (dst_rect.Pitch * j));
for(int i = 0; i < (rect_size_x); i++) {
dst[i] = 0;
dst[i] |= (ushort)(( (int) src[i].r / r_gun.scale ) << r_gun.shift);
dst[i] |= (ushort)(( (int) src[i].g / g_gun.scale ) << g_gun.shift);
dst[i] |= (ushort)(( (int) src[i].b / b_gun.scale ) << b_gun.shift);
}
}
}
front_buffer_a8r8g8b8->UnlockRect();
Gr_saved_surface->UnlockRect();
if(front_buffer_a8r8g8b8) {
front_buffer_a8r8g8b8->Release();
}
return 0;
Failed:
if(front_buffer_a8r8g8b8) {
front_buffer_a8r8g8b8->Release();
}
extern void gr_d3d_free_screen(int id);
gr_d3d_free_screen(0);
return -1;
}
void gr_d3d_restore_screen(int id)
{
gr_reset_clip();
if ( !Gr_saved_surface ) {
gr_clear();
return;
}
// attempt to replace DX5 code with DX8
IDirect3DSurface8 *dest_buffer = NULL;
if(FAILED(GlobalD3DVars::lpD3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &dest_buffer)))
{
DBUGFILE_OUTPUT_0("FAiled");
return;
}
if(FAILED(GlobalD3DVars::lpD3DDevice->CopyRects(Gr_saved_surface, NULL, 0, dest_buffer, NULL)))
{
DBUGFILE_OUTPUT_0("FAiled");
}
dest_buffer->Release();
}
void gr_d3d_free_screen(int id)
{
if ( Gr_saved_surface ) {
Gr_saved_surface->Release();
Gr_saved_surface = NULL;
}
}
void gr_d3d_dump_frame_start(int first_frame, int frames_between_dumps)
{
if ( D3d_dump_frames ) {
Int3(); // We're already dumping frames. See John.
return;
}
D3d_dump_frames = 1;
D3d_dump_frame_number = first_frame;
D3d_dump_frame_count = 0;
D3d_dump_frame_count_max = frames_between_dumps;
D3d_dump_frame_size = gr_screen.max_w * gr_screen.max_h * 2;
if ( !D3d_dump_buffer ) {
int size = D3d_dump_frame_count_max * D3d_dump_frame_size;
D3d_dump_buffer = (ubyte *)vm_malloc(size);
if ( !D3d_dump_buffer ) {
Error(LOCATION, "Unable to malloc %d bytes for dump buffer", size );
}
}
}
void gr_d3d_flush_frame_dump()
{
int i,j;
char filename[MAX_PATH_LEN], *movie_path = ".\\";
ubyte outrow[1024*3*4];
if ( gr_screen.max_w > 1024) {
mprintf(( "Screen too wide for frame_dump\n" ));
return;
}
for (i = 0; i < D3d_dump_frame_count; i++) {
int w = gr_screen.max_w;
int h = gr_screen.max_h;
sprintf(filename, NOX("%sfrm%04d.tga"), movie_path, D3d_dump_frame_number );
D3d_dump_frame_number++;
CFILE *f = cfopen(filename, "wb");
// Write the TGA header
cfwrite_ubyte( 0, f ); // IDLength;
cfwrite_ubyte( 0, f ); // ColorMapType;
cfwrite_ubyte( 10, f ); // ImageType; // 2 = 24bpp, uncompressed, 10=24bpp rle compressed
cfwrite_ushort( 0, f ); // CMapStart;
cfwrite_ushort( 0, f ); // CMapLength;
cfwrite_ubyte( 0, f ); // CMapDepth;
cfwrite_ushort( 0, f ); // XOffset;
cfwrite_ushort( 0, f ); // YOffset;
cfwrite_ushort( (ushort)w, f ); // Width;
cfwrite_ushort( (ushort)h, f ); // Height;
cfwrite_ubyte( 24, f ); //PixelDepth;
cfwrite_ubyte( 0, f ); //ImageDesc;
// Go through and write our pixels
for (j=0;j<h;j++) {
/*
ubyte *src_ptr = D3d_dump_buffer+(i*D3d_dump_frame_size)+(j*w*2);
int len = tga_compress( (char *)outrow, (char *)src_ptr, w*sizeof(short) );
*/
int len = 0;
cfwrite(outrow,len,1,f);
}
cfclose(f);
}
D3d_dump_frame_count = 0;
}
void gr_d3d_dump_frame_stop()
{
if ( !D3d_dump_frames ) {
Int3(); // We're not dumping frames. See John.
return;
}
// dump any remaining frames
gr_d3d_flush_frame_dump();
D3d_dump_frames = 0;
if ( D3d_dump_buffer ) {
vm_free(D3d_dump_buffer);
D3d_dump_buffer = NULL;
}
}
void gr_d3d_dump_frame()
{
D3d_dump_frame_count++;
if ( D3d_dump_frame_count == D3d_dump_frame_count_max ) {
gr_d3d_flush_frame_dump();
}
}
/**
* Empty function
*
* @return uint, always 1
*/
uint gr_d3d_lock()
{
return 1;
}
/**
* Empty function
*
* @return void
*/
void gr_d3d_unlock()
{
}
/**
* Set fog
*
* @param int fog_mode
* @param int r
* @param int g
* @param int b
* @param float fog_near
* @param float fog_far
* @return void
*/
void gr_d3d_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
{
D3DCOLOR color = 0;
Assert((r >= 0) && (r < 256));
Assert((g >= 0) && (g < 256));
Assert((b >= 0) && (b < 256));
// turning fog off
if(fog_mode == GR_FOGMODE_NONE){
// only change state if we need to
if(gr_screen.current_fog_mode != fog_mode){
d3d_SetRenderState(D3DRS_FOGENABLE, FALSE );
}
gr_screen.current_fog_mode = fog_mode;
// to prevent further state changes
return;
}
// maybe switch fogging on
if(gr_screen.current_fog_mode != fog_mode){
d3d_SetRenderState(D3DRS_FOGENABLE, TRUE);
// if we're using table fog, enable table fogging
if(!Cmdline_nohtl){
if(GlobalD3DVars::d3d_caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
{
d3d_SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_LINEAR );
}
else
{
d3d_SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
d3d_SetRenderState( D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
if(GlobalD3DVars::d3d_caps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)
d3d_SetRenderState(D3DRS_RANGEFOGENABLE, TRUE);
}
}
gr_screen.current_fog_mode = fog_mode;
}
// is color changing?
if( (gr_screen.current_fog_color.red != r) || (gr_screen.current_fog_color.green != g) || (gr_screen.current_fog_color.blue != b) ){
// store the values
gr_init_color( &gr_screen.current_fog_color, r, g, b );
color = D3DCOLOR_XRGB(r, g, b);
d3d_SetRenderState(D3DRS_FOGCOLOR, color);
}
// planes changing?
if( (fog_near >= 0.0f) && (fog_far >= 0.0f) && ((fog_near != gr_screen.fog_near) || (fog_far != gr_screen.fog_far)) ){
gr_screen.fog_near = fog_near;
gr_screen.fog_far = fog_far;
// only generate a new fog table if we have to (wfog/table fog mode)
if(!Cmdline_nohtl){
d3d_SetRenderState( D3DRS_FOGSTART, *((DWORD *)(&fog_near)));
d3d_SetRenderState( D3DRS_FOGEND, *((DWORD *)(&fog_far)));
}
}
}
/**
* Support function for gr_d3d_set_gamma
*
*/
inline ushort d3d_ramp_val(UINT i, float recip_gamma, int scale = 65535)
{
return static_cast<ushort>(scale*pow(i/255.f, 1.0f/recip_gamma));
}
/**
* Set the gamma, or brightness
*
* @param float gamma
* @return void
*/
void gr_d3d_set_gamma(float gamma)
{
if(Cmdline_no_set_gamma) return;
Gr_gamma = gamma;
D3DGAMMARAMP gramp;
// Create the Gamma lookup table
for (int i = 0; i < 256; i++ ) {
gramp.red[i] = gramp.green[i] = gramp.blue[i] = d3d_ramp_val(i, gamma);
}
GlobalD3DVars::lpD3DDevice->SetGammaRamp(D3DSGR_CALIBRATE, &gramp);
}
/**
* Toggle polygon culling mode Counter-clockwise or none
*
* @param int cull
* @return void
*/
void gr_d3d_set_cull(int cull)
{
d3d_SetRenderState( D3DRS_CULLMODE, cull ? D3DCULL_CCW : D3DCULL_NONE );
}
void gr_d3d_set_fill_mode(int mode)
{
if(mode == GR_FILL_MODE_SOLID){
d3d_SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
return;
}
if(mode == GR_FILL_MODE_WIRE){
d3d_SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
return;
}
//defalt value
d3d_SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
}
/**
* Cross fade, actually works now
*
* @param int bmap1
* @param int bmap2
* @param int x1
* @param int y1
* @param int x2
* @param int y2
* @param float pct - Fade value, between 0.0 - 1.0
* @return void
*/
void gr_d3d_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
{
gr_set_bitmap(bmap1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - pct );
gr_bitmap(x1, y1);
gr_set_bitmap(bmap2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, pct );
gr_bitmap(x2, y2);
}
/**
* Empty function
*
* @param int filter
* @return void
*/
void gr_d3d_filter_set(int filter)
{
}
/**
* Set clear color
*
* @param int r
* @param int g
* @param int b
* @return void
*/
void gr_d3d_set_clear_color(int r, int g, int b)
{
gr_init_color(&gr_screen.current_clear_color, r, g, b);
}
// Not sure if we need this any more
void gr_d3d_get_region(int front, int w, int h, ubyte *data)
{
HRESULT hr;
// No support for getting the front buffer
if(front) {
mprintf(("No support for front buffer"));
return;
}
IDirect3DSurface8 *back_buffer = NULL;
hr = GlobalD3DVars::lpD3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back_buffer);
if( FAILED(hr))
{
mprintf(("Unsuccessful GetBackBuffer",d3d_error_string(hr)));
return;
}
D3DLOCKED_RECT buffer_desc;
hr = back_buffer->LockRect(&buffer_desc, NULL, D3DLOCK_READONLY );
if( FAILED(hr))
{
mprintf(("Unsuccessful buffer lock",d3d_error_string(hr)));
return;
}
ubyte *dptr = data;
ubyte *rptr = (ubyte*) buffer_desc.pBits;
int pitch = buffer_desc.Pitch;// / gr_screen.bytes_per_pixel;
for (int i=0; i<h; i++ ) {
ubyte *sptr = (ubyte*)&rptr[ i * pitch ];
// don't think we need to swizzle here ...
for(int j=0; j<w; j++ ) {
memcpy(dptr, sptr, gr_screen.bytes_per_pixel);
dptr += gr_screen.bytes_per_pixel;
sptr += gr_screen.bytes_per_pixel;
}
}
back_buffer->UnlockRect();
back_buffer->Release();
}
//*******Vertex buffer stuff*******//
int vertex_size(uint flags){
int size = 0;
Assert(! ((flags & VERTEX_FLAG_RHW) && (flags & VERTEX_FLAG_NORMAL)));
if(flags & VERTEX_FLAG_UV1)Assert(! ((flags & VERTEX_FLAG_UV2) || (flags & VERTEX_FLAG_UV3) || (flags & VERTEX_FLAG_UV4)));
if(flags & VERTEX_FLAG_UV2)Assert(! ((flags & VERTEX_FLAG_UV1) || (flags & VERTEX_FLAG_UV3) || (flags & VERTEX_FLAG_UV4)));
if(flags & VERTEX_FLAG_UV3)Assert(! ((flags & VERTEX_FLAG_UV2) || (flags & VERTEX_FLAG_UV1) || (flags & VERTEX_FLAG_UV4)));
if(flags & VERTEX_FLAG_UV4)Assert(! ((flags & VERTEX_FLAG_UV2) || (flags & VERTEX_FLAG_UV3) || (flags & VERTEX_FLAG_UV1)));
if(flags & VERTEX_FLAG_POSITION)size += sizeof(vec3d);
if(flags & VERTEX_FLAG_RHW)size += sizeof(float);
if(flags & VERTEX_FLAG_NORMAL)size += sizeof(vec3d);
if(flags & VERTEX_FLAG_DIFUSE)size += sizeof(DWORD);
if(flags & VERTEX_FLAG_SPECULAR)size += sizeof(DWORD);
if(flags & VERTEX_FLAG_UV1)size += sizeof(float)*2;
else if(flags & VERTEX_FLAG_UV2)size += sizeof(float)*4;
else if(flags & VERTEX_FLAG_UV3)size += sizeof(float)*6;
else if(flags & VERTEX_FLAG_UV4)size += sizeof(float)*8;
return size;
}
//D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1
int convert_to_fvf(uint flags){
int fvf = 0;
Assert(! ((flags & VERTEX_FLAG_RHW) && (flags & VERTEX_FLAG_NORMAL)));
if(flags & VERTEX_FLAG_UV1)Assert(! ((flags & VERTEX_FLAG_UV2) || (flags & VERTEX_FLAG_UV3) || (flags & VERTEX_FLAG_UV4)));
if(flags & VERTEX_FLAG_UV2)Assert(! ((flags & VERTEX_FLAG_UV1) || (flags & VERTEX_FLAG_UV3) || (flags & VERTEX_FLAG_UV4)));
if(flags & VERTEX_FLAG_UV3)Assert(! ((flags & VERTEX_FLAG_UV2) || (flags & VERTEX_FLAG_UV1) || (flags & VERTEX_FLAG_UV4)));
if(flags & VERTEX_FLAG_UV4)Assert(! ((flags & VERTEX_FLAG_UV2) || (flags & VERTEX_FLAG_UV3) || (flags & VERTEX_FLAG_UV1)));
if(flags & VERTEX_FLAG_POSITION) fvf |= D3DFVF_XYZ;
if(flags & VERTEX_FLAG_RHW) fvf |= D3DFVF_XYZRHW;
if(flags & VERTEX_FLAG_NORMAL) fvf |= D3DFVF_NORMAL;
if(flags & VERTEX_FLAG_DIFUSE) fvf |= D3DFVF_DIFFUSE;
if(flags & VERTEX_FLAG_SPECULAR) fvf |= D3DFVF_SPECULAR;
if(flags & VERTEX_FLAG_UV1) fvf |= D3DFVF_TEX1;
else if(flags & VERTEX_FLAG_UV2) fvf |= D3DFVF_TEX2;
else if(flags & VERTEX_FLAG_UV3) fvf |= D3DFVF_TEX3;
else if(flags & VERTEX_FLAG_UV4) fvf |= D3DFVF_TEX4;
return fvf;
}
#define fill_v(V,v) {(*((float *) (V))) = v; V = ((byte*)(V)) + sizeof(float);}
vec3d *check_vec1, *check_vec2;
void fill_vert(void *V, vertex *L, vec3d* N, uint flags){
if(flags & VERTEX_FLAG_RHW){
fill_v(V, L->sx);
fill_v(V, L->sy);
fill_v(V, L->sw);
fill_v(V, L->sw);
}else
if(flags & VERTEX_FLAG_POSITION){
check_vec1 = (vec3d*)V;
fill_v(V, L->x);
fill_v(V, L->y);
fill_v(V, L->z);
}
if(flags & VERTEX_FLAG_NORMAL){
check_vec2 = (vec3d*)V;
fill_v(V, N->xyz.x);
fill_v(V, N->xyz.y);
fill_v(V, N->xyz.z);
}
if(flags & VERTEX_FLAG_DIFUSE){
*(byte*)(V = ((byte*)V)+1 ) = L->a;
*(byte*)(V = ((byte*)V)+1 ) = L->r;
*(byte*)(V = ((byte*)V)+1 ) = L->g;
*(byte*)(V = ((byte*)V)+1 ) = L->b;
}
if(flags & VERTEX_FLAG_SPECULAR){
*(byte*)(V = ((byte*)V)+1 ) = L->spec_a;
*(byte*)(V = ((byte*)V)+1 ) = L->spec_r;
*(byte*)(V = ((byte*)V)+1 ) = L->spec_g;
*(byte*)(V = ((byte*)V)+1 ) = L->spec_b;
}
if(flags & VERTEX_FLAG_UV1){
fill_v(V, L->u);
fill_v(V, L->v);
}else
if(flags & VERTEX_FLAG_UV2){
fill_v(V, L->u);
fill_v(V, L->v);
fill_v(V, L->u2);
fill_v(V, L->v2);
}else
if(flags & VERTEX_FLAG_UV3){
fill_v(V, L->u);
fill_v(V, L->v);
fill_v(V, L->u2);
fill_v(V, L->v2);
fill_v(V, L->u3);
fill_v(V, L->v3);
}else
if(flags & VERTEX_FLAG_UV4){
fill_v(V, L->u);
fill_v(V, L->v);
fill_v(V, L->u2);
fill_v(V, L->v2);
fill_v(V, L->u3);
fill_v(V, L->v3);
fill_v(V, L->u4);
fill_v(V, L->v4);
}
}
//makes the vertex buffer, returns an index to it
int gr_d3d_make_buffer(poly_list *list, uint flags)
{
int k;
byte *v;
Vertex_buffer new_buffer;
new_buffer.size = vertex_size(flags);
new_buffer.FVF = convert_to_fvf(flags);
// d3d_CreateVertexBuffer(D3DVT_VERTEX, (list->n_verts), NULL, (void**)buffer);
k = GlobalD3DVars::lpD3DDevice->CreateVertexBuffer(
new_buffer.size * (list->n_verts ? list->n_verts : 1),
D3DUSAGE_WRITEONLY,
new_buffer.FVF,
D3DPOOL_MANAGED,
&new_buffer.buffer);
switch (k)
{
case D3DERR_INVALIDCALL:
Error(LOCATION, "CreateVertexBuffer returned D3DERR_INVALIDCALL.");
break;
case D3DERR_OUTOFVIDEOMEMORY:
Error(LOCATION, "CreateVertexBuffer returned D3DERR_OUTOFVIDEOMEMORY");
break;
case E_OUTOFMEMORY:
Error(LOCATION, "CreateVertexBuffer returned E_OUTOFMEMORY");
break;
default:
break;
}
if (new_buffer.buffer == NULL)
return -1;
new_buffer.buffer->Lock(0, 0, &v, 0);
for(k = 0; k<list->n_verts; k++){
fill_vert(&v[k * new_buffer.size], &list->vert[k], &list->norm[k], flags);
new_buffer.n_verts++;
}
new_buffer.buffer->Unlock();
new_buffer.n_verts = list->n_verts;
new_buffer.n_prim = list->n_verts;
new_buffer.type = TRILIST_;
D3D_vertex_buffers.push_back( new_buffer );
D3D_vertex_buffers_in_use++;
return (int)(D3D_vertex_buffers.size() - 1);
}
//makes the vertex buffer, returns an index to it
int gr_d3d_make_flat_buffer(poly_list *list)
{
int k;
D3DLVERTEX *v, *V;
vertex *L;
// vec3d *N;
Vertex_buffer new_buffer;
IDirect3DVertexBuffer8 **buffer = &new_buffer.buffer;
d3d_CreateVertexBuffer(D3DVT_LVERTEX, (list->n_verts), NULL, (void**)buffer);
new_buffer.buffer->Lock(0, 0, (BYTE **)&v, NULL);
for (k = 0; k < list->n_verts; k++) {
V = &v[k];
L = &list->vert[k];
// N = &list->norm[k]; //these don't have normals :\
V->sx = L->x;
V->sy = L->y;
V->sz = L->z;
V->tu = L->u;
V->tv = L->v;
V->color = D3DCOLOR_ARGB(255,L->r,L->g,L->b);
}
new_buffer.buffer->Unlock();
new_buffer.n_prim = list->n_verts/3;
new_buffer.type = FLAT_;
D3D_vertex_buffers.push_back( new_buffer );
D3D_vertex_buffers_in_use++;
return (int)(D3D_vertex_buffers.size() - 1);
}
//makes line buffer, returns index
int gr_d3d_make_line_buffer(line_list *list){
/*
int idx = find_first_empty_buffer();
if(idx > -1){
IDirect3DVertexBuffer8 **buffer = &vertex_buffer[idx].buffer;
d3d_CreateVertexBuffer(D3DVT_LVERTEX, (list->n_line*2), NULL, (void**)buffer);
D3DLVERTEX *v, *V;
vertex *L;
// vec3d *N;
int c = 0;
vertex_buffer[idx].buffer->Lock(0, 0, (BYTE **)&v, NULL);
for(int k = 0; k<list->n_line; k++){
for(int j = 0; j < 2; j++){
V = &v[(k*2)+j];
L = &list->vert[k][j];
V->sx = L->x;
V->sy = L->y;
V->sz = L->z;
V->tu = L->u;
V->tv = L->v;
V->color = D3DCOLOR_ARGB(255,L->r,L->g,L->b);
c++;
}
}
vertex_buffer[idx].buffer->Unlock();
vertex_buffer[idx].ocupied = true;
vertex_buffer[idx].n_prim = list->n_line;
vertex_buffer[idx].type = LINELIST_;
}
// return-1;
return idx;
*/
return-1;
}
//kills buffers dead!
void gr_d3d_destroy_buffer(int idx)
{
if ( (idx < 0) || (idx >= (int)D3D_vertex_buffers.size()) )
return;
Vertex_buffer *vbp = &D3D_vertex_buffers[idx];
if (vbp->buffer != NULL)
vbp->buffer->Release();
memset( vbp, 0, sizeof(Vertex_buffer) );
// we try to take advantage of the fact that there shouldn't be a lot of buffer
// deletions/additions going on all of the time, so a model_unload_all() and/or
// game_level_close() should pretty much keep everything cleared out on a
// regular basis
if (--D3D_vertex_buffers_in_use <= 0)
D3D_vertex_buffers.clear();
}
//enum vertex_buffer_type{TRILIST_,LINELIST_,FLAT_};
void gr_d3d_render_line_buffer(int idx)
{
if ( (idx < 0) || (idx >= (int)D3D_vertex_buffers.size()) )
return;
if (D3D_vertex_buffers[idx].buffer == NULL)
return;
d3d_SetVertexShader(vertex_types[D3DVT_LVERTEX].fvf);
GlobalD3DVars::lpD3DDevice->SetStreamSource(0, D3D_vertex_buffers[idx].buffer, sizeof(D3DLVERTEX));
gr_d3d_fog_set(GR_FOGMODE_NONE, 0,0,0, gr_screen.fog_near, gr_screen.fog_far); //it's a HUD item, should never be fogged
gr_d3d_set_cull(0);
d3d_SetRenderState(D3DRS_LIGHTING , FALSE);
GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_LINELIST , 0, D3D_vertex_buffers[idx].n_prim);
d3d_SetRenderState(D3DRS_LIGHTING , TRUE);
gr_d3d_set_cull(1);
}
extern int GR_center_alpha;
bool the_lights_are_on;
extern bool lighting_enabled;
void gr_d3d_center_alpha_int(int type);
Vertex_buffer *set_buffer;
void gr_d3d_set_buffer(int idx)
{
set_buffer = NULL;
if ( (idx < 0) || (idx >= (int)D3D_vertex_buffers.size()) )
return;
set_buffer = &D3D_vertex_buffers[idx];
d3d_SetVertexShader(set_buffer->FVF);
GlobalD3DVars::lpD3DDevice->SetStreamSource(0, set_buffer->buffer, set_buffer->size);
}
IDirect3DIndexBuffer8 *global_index_buffer = NULL;
int index_buffer_size = 0;
IDirect3DIndexBuffer8 *global_index_buffer32 = NULL;
int index_buffer_size32 = 0;
void gr_d3d_render_buffer(int start, int n_prim, ushort* index_buffer, uint *ibuf32, int flags)
{
if(set_buffer == NULL)return;
if(index_buffer != NULL && ibuf32 !=NULL){
Error(LOCATION, "gr_d3d_render_buffer was given TWO indext buffers, that's not cool man!\n only useing the 16 bit one");
ibuf32=NULL;
}
if(index_buffer != NULL || ibuf32 !=NULL){
if(index_buffer){
if(index_buffer_size < n_prim * 3 || !global_index_buffer){
if(global_index_buffer)global_index_buffer->Release();
GlobalD3DVars::lpD3DDevice->CreateIndexBuffer(n_prim * 3 * sizeof(ushort), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, (IDirect3DIndexBuffer8**) &global_index_buffer);
index_buffer_size = n_prim * 3;
}
ushort* i_buffer;
global_index_buffer->Lock(0, 0, (BYTE **)&i_buffer, D3DLOCK_DISCARD);
memcpy(i_buffer, index_buffer, n_prim*3*sizeof(ushort));
global_index_buffer->Unlock();
GlobalD3DVars::lpD3DDevice->SetIndices(global_index_buffer, 0);
}
if(ibuf32) {
if(index_buffer_size32 < n_prim * 3 || !global_index_buffer32){
if(global_index_buffer32)global_index_buffer32->Release();
GlobalD3DVars::lpD3DDevice->CreateIndexBuffer(n_prim * 3 * sizeof(uint), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, (IDirect3DIndexBuffer8**) &global_index_buffer32);
index_buffer_size32 = n_prim * 3;
}
uint* i_buffer32;
global_index_buffer32->Lock(0, 0, (BYTE **)&i_buffer32, D3DLOCK_DISCARD);
memcpy(i_buffer32, ibuf32, n_prim*3*sizeof(uint));
global_index_buffer32->Unlock();
GlobalD3DVars::lpD3DDevice->SetIndices(global_index_buffer32, 0);
}
// global_index_buffer->Lock(start, n_prim * 3 * sizeof(short), (BYTE **)&index_buffer, D3DLOCK_DISCARD);
}
// GlobalD3DVars::d3d_caps.MaxActiveLights = 1;
// if(!the_lights_are_on){
// d3d_SetVertexShader(D3DVT_VERTEX);
// d3d_SetRenderState(D3DRS_LIGHTING , TRUE);
// the_lights_are_on = true;
// }
extern D3DMATERIAL8 material;
// Sets the current alpha of the object
if(gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER){
material.Ambient.a = gr_screen.current_alpha;
material.Diffuse.a = gr_screen.current_alpha;
material.Specular.a = gr_screen.current_alpha;
material.Emissive.a = gr_screen.current_alpha;
}else{
material.Ambient.a = 1.0;
material.Diffuse.a = 1.0;
material.Specular.a = 1.0;
material.Emissive.a = 1.0f;
}
if(!lighting_enabled){
int l = int(255.0f*gr_screen.current_alpha);
d3d_SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(l,l,l,l));
}else{
d3d_SetRenderState(D3DRS_AMBIENT, ambient_light);
}
GlobalD3DVars::lpD3DDevice->SetMaterial(&material);
color old_fog_color = gr_screen.current_fog_color;
if(gr_screen.current_fog_mode != GR_FOGMODE_NONE)//when fogging don't fog unlit things, but rather fade them in a fog like manner -Bobboau
if(!lighting_enabled){
gr_d3d_fog_set(gr_screen.current_fog_mode, 0,0,0, gr_screen.fog_near, gr_screen.fog_far);
}
if (set_buffer->buffer == NULL) {
return;
}
/* if(set_buffer->type == LINELIST_) {
gr_d3d_render_line_buffer(idx);
return;
}
*/
float u_scale = 1.0f, v_scale = 1.0f;
gr_alpha_blend ab = ALPHA_BLEND_NONE;
if(gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER)
ab = ALPHA_BLEND_ALPHA_ADDITIVE;
// int same = (gr_screen.current_bitmap != SPECMAP)?0:1;
// if(!same)d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 0);
d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 0);
// if(!gr_zbuffering_mode)
// gr_d3d_set_state(TEXTURE_SOURCE_DECAL, ab, ZBUFFER_TYPE_NONE);
if(gr_zbuffering_mode == GR_ZBUFF_NONE){
gr_d3d_set_state(TEXTURE_SOURCE_DECAL, ab, ZBUFFER_TYPE_NONE);
d3d_SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
}else if(gr_zbuffering_mode == GR_ZBUFF_READ){
gr_d3d_set_state(TEXTURE_SOURCE_DECAL, ab, ZBUFFER_TYPE_READ);
d3d_SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
}else{
gr_d3d_set_state(TEXTURE_SOURCE_DECAL, ab, ZBUFFER_TYPE_DEFAULT);
}
pre_render_lights_init();
if(lighting_enabled){
shift_active_lights(0);
}
// bool single_pass_spec = false;
if(GLOWMAP > -1 && !Cmdline_noglow){
//glowmapped
gr_screen.gf_set_bitmap(GLOWMAP, gr_screen.current_alphablend_mode, gr_screen.current_bitblt_mode, 0.0);
d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 1);
set_stage_for_glow_mapped_defuse();
}else{
//non glowmapped
set_stage_for_defuse();
}
int passes = (n_active_lights / GlobalD3DVars::d3d_caps.MaxActiveLights);
// d3d_SetVertexShader(D3DVT_VERTEX);
gr_d3d_center_alpha_int(GR_center_alpha);
// if(!lighting_enabled) d3d_SetRenderState(D3DRS_LIGHTING , FALSE);
if(index_buffer != NULL || ibuf32 != NULL)GlobalD3DVars::lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,set_buffer->n_verts, start, n_prim);
else GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST , start, n_prim);
// if(!lighting_enabled) d3d_SetRenderState(D3DRS_LIGHTING , TRUE);
if(!lighting_enabled)
{
return;
}
//single pass specmap rendering ends here
/* if(single_pass_spec){
return;
}*/
if (gr_zbuffering_mode)
{
gr_d3d_set_state( TEXTURE_SOURCE_DECAL, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_READ );
}
else
gr_d3d_set_state( TEXTURE_SOURCE_DECAL, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE );
if(gr_screen.current_fog_mode != GR_FOGMODE_NONE){
old_fog_color = gr_screen.current_fog_color;
gr_d3d_fog_set(gr_screen.current_fog_mode, 0,0,0, gr_screen.fog_near, gr_screen.fog_far);
}
// if(single_pass_spec)set_stage_for_single_pass_specmapping(same);
// else set_stage_for_defuse();
set_stage_for_defuse();
d3d_SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0,0,0,0));
for(int i = 1; i<passes; i++){
shift_active_lights(i);
TIMERBAR_PUSH(7);
if(index_buffer != NULL || ibuf32 != NULL)GlobalD3DVars::lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,set_buffer->n_verts, start, n_prim);
else GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST , start, n_prim);
TIMERBAR_POP();
}
if(!lighting_enabled){
int l = int(255.0f*gr_screen.current_alpha);
d3d_SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(l,l,l,l));
}else{
d3d_SetRenderState(D3DRS_AMBIENT, ambient_light);
}
pre_render_lights_init();
shift_active_lights(0);
//spec mapping
if(SPECMAP > -1){
gr_zbias(1);
gr_screen.gf_set_bitmap(SPECMAP, gr_screen.current_alphablend_mode, gr_screen.current_bitblt_mode, 0.0);
if ( !d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 0)) {
mprintf(( "Not rendering specmap texture because it didn't fit in VRAM!\n" ));
// Error(LOCATION, "Not rendering specmap texture because it didn't fit in VRAM!");
return;
}
if(set_stage_for_spec_mapped()){
gr_d3d_set_state( TEXTURE_SOURCE_DECAL, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_READ );
if(index_buffer != NULL || ibuf32 != NULL)GlobalD3DVars::lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,set_buffer->n_verts, start, n_prim);
else GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST , start, n_prim);
d3d_SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0,0,0,0));
for(int i = 1; i<passes; i++){
shift_active_lights(i);
if(index_buffer != NULL || ibuf32 != NULL)GlobalD3DVars::lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,set_buffer->n_verts, start, n_prim);
else GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST , start, n_prim);
}
gr_d3d_set_state( TEXTURE_SOURCE_DECAL, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL );
if(Cmdline_env){
gr_zbias(2);
extern int Game_subspace_effect;
gr_screen.gf_set_bitmap(ENVMAP, gr_screen.current_alphablend_mode, gr_screen.current_bitblt_mode, 0.0);
d3d_tcache_set_internal(gr_screen.current_bitmap, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 0, 0, 1);
gr_d3d_set_state( TEXTURE_SOURCE_DECAL, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_READ );
set_stage_for_env_mapped();
d3d_SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
if(index_buffer != NULL || ibuf32 != NULL)GlobalD3DVars::lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,set_buffer->n_verts, start, n_prim);
else GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST , start, n_prim);
d3d_SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
}
gr_zbias(0);
}
// Revert back to old fog state
if(gr_screen.current_fog_mode != GR_FOGMODE_NONE)
gr_d3d_fog_set(gr_screen.current_fog_mode, old_fog_color.red,old_fog_color.green,old_fog_color.blue, gr_screen.fog_near, gr_screen.fog_far);
}
//*******matrix stuff*******//
/*
//the projection matrix; fov, aspect ratio, near, far
void (*gf_set_proj_matrix)(float, float, float, float);
void (*gf_end_proj_matrix)();
//the view matrix
void (*gf_set_view_matrix)(vec3d *, matrix*);
void (*gf_end_view_matrix)();
//object scaleing
void (*gf_push_scale_matrix)(vec3d *);
void (*gf_pop_scale_matrix)();
//object position and orientation
void (*gf_start_instance_matrix)(vec3d *, matrix*);
void (*gf_start_angles_instance_matrix)(vec3d *, angles*);
void (*gf_end_instance_matrix)();
*/
//fov = (4.0/9.0)*(PI)*View_zoom
//ratio = screen.aspect
//near = 1.0
//far = 30000
float fov_corection = 1.0f;
//the projection matrix; fov, aspect ratio, near, far
void gr_d3d_set_proj_matrix(float fov, float ratio, float n, float f){
// proj_matrix_stack->Push();
fov *= fov_corection;
D3DXMATRIX mat;
D3DXMatrixPerspectiveFovLH(&mat, fov, ratio, n, f);
// D3DXMatrixPerspectiveFovLH(&mat, (4.0f/9.0f)*(D3DX_PI)*View_zoom, 1.0f/gr_screen.aspect, 0.2f, 30000);
// proj_matrix_stack->LoadMatrix(&mat);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_PROJECTION, &mat);
}
void gr_d3d_end_proj_matrix(){
// proj_matrix_stack->Pop();
}
//extern float global_scaleing_factor;
//the view matrix
void gr_d3d_set_view_matrix(vec3d* offset, matrix *orient){
// view_matrix_stack->Push();
D3DXMATRIX mat, scale_m;
D3DXMATRIX MAT(
orient->vec.rvec.xyz.x, orient->vec.rvec.xyz.y, orient->vec.rvec.xyz.z, 0,
orient->vec.uvec.xyz.x, orient->vec.uvec.xyz.y, orient->vec.uvec.xyz.z, 0,
orient->vec.fvec.xyz.x, orient->vec.fvec.xyz.y, orient->vec.fvec.xyz.z, 0,
offset->xyz.x, offset->xyz.y, offset->xyz.z, 1);
D3DXMatrixIdentity(&mat);
// D3DXMatrixScaling(&scale_m, 1/global_scaleing_factor, 1/global_scaleing_factor, 1/global_scaleing_factor);//global sacaleing
// D3DXMatrixMultiply(&MAT, &MAT, &scale_m);
D3DXMatrixInverse(&mat, NULL, &MAT);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_VIEW, &mat);
}
void gr_d3d_end_view_matrix(){
// view_matrix_stack->Pop();
// GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_VIEW, view_matrix_stack->GetTop());
}
int matr_depth = 0;
//object position and orientation
void gr_d3d_start_instance_matrix(vec3d* offset, matrix *orient){
D3DXMATRIX old_world = *world_matrix_stack->GetTop(), scale_m;
world_matrix_stack->Push();
D3DXMATRIX world(
orient->vec.rvec.xyz.x, orient->vec.rvec.xyz.y, orient->vec.rvec.xyz.z, 0,
orient->vec.uvec.xyz.x, orient->vec.uvec.xyz.y, orient->vec.uvec.xyz.z, 0,
orient->vec.fvec.xyz.x, orient->vec.fvec.xyz.y, orient->vec.fvec.xyz.z, 0,
offset->xyz.x, offset->xyz.y, offset->xyz.z, 1);
// D3DXMatrixScaling(&scale_m, global_scaleing_factor, global_scaleing_factor, global_scaleing_factor);//global sacaleing
// D3DXMatrixMultiply(&world, &scale_m, &world);
D3DXMatrixMultiply(&world, &world, &old_world);
world_matrix_stack->LoadMatrix(&world);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_WORLD, world_matrix_stack->GetTop());
matr_depth++;
}
void gr_d3d_start_angles_instance_matrix(vec3d* offset, angles *orient){
D3DXMATRIX current = *world_matrix_stack->GetTop(), scale_m;
world_matrix_stack->Push();
D3DXMATRIX mat;
D3DXMatrixRotationYawPitchRoll(&mat,orient->h,orient->p,orient->b);
D3DXMATRIX world(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
offset->xyz.x, offset->xyz.y, offset->xyz.z, 1);
/// D3DXMatrixScaling(&scale_m, global_scaleing_factor, global_scaleing_factor, global_scaleing_factor);;//global sacaleing
// D3DXMatrixMultiply(&world, &scale_m, &world);
D3DXMatrixMultiply(&mat, &mat, &world);
D3DXMatrixMultiply(&mat, &mat, &current);
world_matrix_stack->LoadMatrix(&mat);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_WORLD, world_matrix_stack->GetTop());
matr_depth++;
}
void gr_d3d_end_instance_matrix()
{
world_matrix_stack->Pop();
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_WORLD, world_matrix_stack->GetTop());
matr_depth--;
}
//object scaleing
void gr_d3d_set_scale_matrix(vec3d* scale){
D3DXMATRIX mat = *world_matrix_stack->GetTop(), scale_m;
world_matrix_stack->Push();
D3DXMatrixScaling(&scale_m, scale->xyz.x, scale->xyz.y, scale->xyz.z);
D3DXMatrixMultiply(&mat, &scale_m, &mat);
world_matrix_stack->LoadMatrix(&mat);
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_WORLD, &mat);
}
void gr_d3d_end_scale_matrix()
{
world_matrix_stack->Pop();
GlobalD3DVars::lpD3DDevice->SetTransform(D3DTS_WORLD, world_matrix_stack->GetTop());
}
/**
* Turns on clip plane clip plane
* Doenst seem to work at the moment
*
* @return void
*/
void gr_d3d_start_clip(){
D3DXVECTOR3 point(G3_user_clip_point.xyz.x,G3_user_clip_point.xyz.y,G3_user_clip_point.xyz.z);
D3DXVECTOR3 normal(G3_user_clip_normal.xyz.x,G3_user_clip_normal.xyz.y,G3_user_clip_normal.xyz.z);
D3DXPlaneFromPointNormal(&d3d_user_clip_plane, &point, &normal);
HRESULT hr = GlobalD3DVars::lpD3DDevice->SetClipPlane(0, d3d_user_clip_plane);
// Assert(SUCCEEDED(hr));
if(FAILED(hr))
{
mprintf(("Failed to set clip plane\n"));
}
hr = d3d_SetRenderState(D3DRS_CLIPPLANEENABLE , D3DCLIPPLANE0);
Assert(SUCCEEDED(hr));
}
/**
* Turns off clip plane
*
* @return void
*/
void gr_d3d_end_clip(){
d3d_SetRenderState(D3DRS_CLIPPLANEENABLE , FALSE);
}
/**
* Takes a D3D error and turns it into text, however for DX8 they have really reduced the
* number of error codes so the result may be quite general
*
* @param HRESULT error
* @return const char *
*/
const char *d3d_error_string(HRESULT error)
{
return DXGetErrorString8(error);
}
//this is an attempt to get something more like the old style fogging that used the lockable back buffer,
//it will render the model with the background texture then fog with black as the color
void gr_d3d_setup_background_fog(bool set){
return;
/* IDirect3DSurface8 *bg_surf;
if(!background_render_target){
GlobalD3DVars::lpD3DDevice->CreateTexture(
1024, 1024,
0,
D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &background_render_target);
}
background_render_target->GetSurfaceLevel(0,&bg_surf);
if(set){
GlobalD3DVars::lpD3DDevice->GetRenderTarget(&old_render_target);
GlobalD3DVars::lpD3DDevice->SetRenderTarget(bg_surf , 0);
gr_d3d_clear();
}else{
// GlobalD3DVars::lpD3DDevice->GetRenderTarget(&background_render_target);
GlobalD3DVars::lpD3DDevice->SetRenderTarget(old_render_target , 0);
}*/
}
IDirect3DSurface8 *old_render_sten = NULL;
/*
extern D3DFORMAT d3d8_format;
LPDIRECT3DSURFACE8 face;
void d3d_init_environment(){
if(!cube_map){
D3DFORMAT use_format;
use_format = D3DFMT_X8R8G8B8;
GlobalD3DVars::lpD3DDevice->CreateCubeTexture(512, 1, D3DUSAGE_RENDERTARGET , use_format, D3DPOOL_DEFAULT, &cube_map);
// Check if it succeeds in allocating the cube map - it fails on a card that doesn't support
// cubemaps, silly!
if (NULL == cube_map) {
mprintf(("Failed in creating a cube-map in d3d_init_environment!"));
return;
}
}
if(!old_render_target){
GlobalD3DVars::lpD3DDevice->GetRenderTarget(&old_render_target);
GlobalD3DVars::lpD3DDevice->GetDepthStencilSurface(&old_render_sten);
}
for(int i = 0; i<6; i++){
cube_map->GetCubeMapSurface(_D3DCUBEMAP_FACES(i), 0, &face);
GlobalD3DVars::lpD3DDevice->SetRenderTarget(face , NULL);
gr_d3d_clear();
int r = face->Release();
}
GlobalD3DVars::lpD3DDevice->SetRenderTarget(old_render_target, old_render_sten);
// old_render_target = NULL;
}
LPDIRECT3DSURFACE8 env_face = NULL;
void d3d_render_to_env(int FACE){
if(env_face){
env_face->Release();
env_face = NULL;
}
if(!cube_map){
D3DFORMAT use_format;
use_format = D3DFMT_X8R8G8B8;
GlobalD3DVars::lpD3DDevice->CreateCubeTexture(512, 1, D3DUSAGE_RENDERTARGET , use_format, D3DPOOL_DEFAULT, &cube_map);
// Check if it succeeds in allocating the cube map - it fails on a card that doesn't support
// cubemaps, silly!
if (NULL == cube_map) {
mprintf(("Failed in creating a cube-map in d3d_render_to_env!"));
return;
}
}
if(!old_render_target){
GlobalD3DVars::lpD3DDevice->GetRenderTarget(&old_render_target);
GlobalD3DVars::lpD3DDevice->GetDepthStencilSurface(&old_render_sten);
}
if(FACE > -1){
cube_map->GetCubeMapSurface(_D3DCUBEMAP_FACES(FACE), 0, &env_face);
GlobalD3DVars::lpD3DDevice->SetRenderTarget(env_face , NULL);
gr_d3d_clear();
}else{
GlobalD3DVars::lpD3DDevice->SetRenderTarget(old_render_target, old_render_sten);
}
// old_render_target = NULL;
}
*/
#endif // !NO_DIRECT3D