Descent3/renderer/HardwareBaseGPU.cpp
2024-05-24 20:57:17 -04:00

757 lines
22 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Descent Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// TODO: This is missing a good way of overriding base behavior (like, you know, method overrides...)
#include "pserror.h"
#include "mono.h"
#include "3d.h"
#include "renderer.h"
#include "bitmap.h"
#include "grdefs.h"
#include <cstring>
#include "HardwareInternal.h"
#include "lightmap.h"
// FIXME: Unused
// The font characteristics
static float rend_FontRed[4], rend_FontBlue[4], rend_FontGreen[4], rend_FontAlpha[4];
char Renderer_error_message[256] = "Generic renderer error";
// The following values are referenced by the game code, but only
// UseMultitexture is actually referenced and used in this code - and
// even that can probably go away and we just assume there is more than
// one texture unit (which, since I believe OpenGL 1.2 is a requirement)
bool UseHardware = true;
bool NoLightmaps = false;
bool StateLimited = false;
bool UseMultitexture = false;
bool UseWBuffer = false;
// General renderer states
int gpu_Overlay_map = -1;
uint8_t gpu_Overlay_type = OT_NONE;
uint8_t Renderer_initted = 0;
// Generic GPU data
rendering_state gpu_state;
renderer_preferred_state gpu_preferred_state = {0, 1, 1.5};
int gpu_last_frame_polys_drawn = 0;
int gpu_last_frame_verts_processed = 0;
int gpu_last_uploaded = 0;
float gpu_Alpha_factor = 1.0f;
float gpu_Alpha_multiplier = 1.0f;
PosColorUVVertex vArray[100];
PosColorUV2Vertex vArray2[100];
// returns the alpha that we should use
float rend_GetAlphaMultiplier() {
switch (gpu_state.cur_alpha_type) {
case AT_ALWAYS:
case AT_TEXTURE:
case AT_VERTEX:
case AT_TEXTURE_VERTEX:
case AT_SATURATE_VERTEX:
case AT_SATURATE_TEXTURE_VERTEX:
case AT_SPECULAR:
return 1.0;
case AT_CONSTANT:
case AT_CONSTANT_TEXTURE:
case AT_CONSTANT_TEXTURE_VERTEX:
case AT_CONSTANT_VERTEX:
case AT_LIGHTMAP_BLEND:
case AT_LIGHTMAP_BLEND_SATURATE:
case AT_SATURATE_TEXTURE:
case AT_SATURATE_CONSTANT_VERTEX:
return gpu_state.cur_alpha / 255.0;
default:
// Int3(); // no type defined,get jason
return 0;
}
}
// Retrieves an error message
const char *rend_GetErrorMessage() { return Renderer_error_message; }
// Sets an error message
void rend_SetErrorMessage(const char *str) {
ASSERT(strlen(str) < 256);
strcpy(Renderer_error_message, str);
}
// FIXME: Unused
// Sets the argb characteristics of the font characters. color1 is the upper left and proceeds clockwise
void rend_SetCharacterParameters(ddgr_color color1, ddgr_color color2, ddgr_color color3, ddgr_color color4) {
rend_FontRed[0] = (float)(GR_COLOR_RED(color1) / 255.0f);
rend_FontRed[1] = (float)(GR_COLOR_RED(color2) / 255.0f);
rend_FontRed[2] = (float)(GR_COLOR_RED(color3) / 255.0f);
rend_FontRed[3] = (float)(GR_COLOR_RED(color4) / 255.0f);
rend_FontGreen[0] = (float)(GR_COLOR_GREEN(color1) / 255.0f);
rend_FontGreen[1] = (float)(GR_COLOR_GREEN(color2) / 255.0f);
rend_FontGreen[2] = (float)(GR_COLOR_GREEN(color3) / 255.0f);
rend_FontGreen[3] = (float)(GR_COLOR_GREEN(color4) / 255.0f);
rend_FontBlue[0] = (float)(GR_COLOR_BLUE(color1) / 255.0f);
rend_FontBlue[1] = (float)(GR_COLOR_BLUE(color2) / 255.0f);
rend_FontBlue[2] = (float)(GR_COLOR_BLUE(color3) / 255.0f);
rend_FontBlue[3] = (float)(GR_COLOR_BLUE(color4) / 255.0f);
rend_FontAlpha[0] = (color1 >> 24) / 255.0f;
rend_FontAlpha[1] = (color2 >> 24) / 255.0f;
rend_FontAlpha[2] = (color3 >> 24) / 255.0f;
rend_FontAlpha[3] = (color4 >> 24) / 255.0f;
}
// Sets where the software renderer should write to
void rend_SetSoftwareParameters(float aspect, int width, int height, int pitch, uint8_t *framebuffer) {}
// Sets the state of bilinear filtering for our textures
void rend_SetFiltering(int8_t state) {
gpu_state.cur_bilinear_state = state;
}
// Sets the near and far planes for z buffer
void rend_SetZValues(float nearz, float farz) {
gpu_state.cur_near_z = nearz;
gpu_state.cur_far_z = farz;
// mprintf(0,"OPENGL:Setting depth range to %f - %f\n",nearz,farz);
// JEFF: glDepthRange must take parameters [0,1]
// It is set in init
//@@dglDepthRange (0,farz);
}
// Sets a bitmap as a overlay map to rendered on top of the next texture map
// a -1 value indicates no overlay map
void rend_SetOverlayMap(int handle) { gpu_Overlay_map = handle; }
void rend_SetOverlayType(uint8_t type) { gpu_Overlay_type = type; }
void rend_FillCircle(ddgr_color col, int x, int y, int rad) {}
void rend_DrawCircle(int x, int y, int rad) {}
// Sets up a font character to draw. We draw our fonts as pieces of textures
void rend_DrawFontCharacter(int bm_handle, int x1, int y1, int x2, int y2, float u, float v, float w, float h) {
g3Point *ptr_pnts[4];
g3Point pnts[4];
for (int i = 0; i < 4; i++) {
pnts[i].p3_z = 1; // Make REALLY close!
pnts[i].p3_flags = PF_PROJECTED;
ptr_pnts[i] = &pnts[i];
}
pnts[0].p3_sx = x1;
pnts[0].p3_sy = y1;
pnts[0].p3_u = u;
pnts[0].p3_v = v;
pnts[1].p3_sx = x2;
pnts[1].p3_sy = y1;
pnts[1].p3_u = u + w;
pnts[1].p3_v = v;
pnts[2].p3_sx = x2;
pnts[2].p3_sy = y2;
pnts[2].p3_u = u + w;
pnts[2].p3_v = v + h;
pnts[3].p3_sx = x1;
pnts[3].p3_sy = y2;
pnts[3].p3_u = u;
pnts[3].p3_v = v + h;
rend_DrawPolygon2D(bm_handle, ptr_pnts, 4);
}
// Sets the alpha value for constant alpha
void rend_SetAlphaValue(uint8_t val) {
gpu_state.cur_alpha = val;
gpu_Alpha_multiplier = rend_GetAlphaMultiplier();
}
// Sets the texture wrapping type
void rend_SetWrapType(wrap_type val) { gpu_state.cur_wrap_type = val; }
void rend_SetZBias(float z_bias) {
if (Z_bias != z_bias) {
Z_bias = z_bias;
// Force refresh our transforms to take the Zbias into account
g3_GetModelViewMatrix(&View_position, &Unscaled_matrix, (float *)gTransformModelView);
g3_UpdateFullTransform();
g3_ForceTransformRefresh();
}
}
// Sets the overall alpha scale factor (all alpha values are scaled by this value)
// usefull for motion blur effect
void rend_SetAlphaFactor(float val) {
if (val < 0.0f)
val = 0.0f;
if (val > 1.0f)
val = 1.0f;
gpu_Alpha_factor = val;
}
// Returns the current Alpha factor
float rend_GetAlphaFactor(void) { return gpu_Alpha_factor; }
// Gets a pointer to a linear frame buffer
void rend_GetLFBLock(renderer_lfb *lfb) {}
// Releases an lfb lock
void rend_ReleaseLFBLock(renderer_lfb *lfb) {}
// Returns the aspect ratio of the physical screen
void rend_GetProjectionParameters(int *width, int *height) {
*width = gpu_state.clip_x2 - gpu_state.clip_x1;
*height = gpu_state.clip_y2 - gpu_state.clip_y1;
}
void rend_GetProjectionScreenParameters(int &screenLX, int &screenTY, int &screenW, int &screenH) {
screenLX = gpu_state.clip_x1;
screenTY = gpu_state.clip_y1;
screenW = gpu_state.clip_x2 - gpu_state.clip_x1 + 1;
screenH = gpu_state.clip_y2 - gpu_state.clip_y1 + 1;
}
// Returns the aspect ratio of the physical screen
float rend_GetAspectRatio(void) {
float aspect_ratio = (float)((3.0f * gpu_state.screen_width) / (4.0f * gpu_state.screen_height));
return aspect_ratio;
}
// Given a source x,y and width,height, draws any sized bitmap into the renderer lfb
void rend_DrawLFBBitmap(int sx, int sy, int w, int h, int dx, int dy, uint16_t *data, int rowsize) {}
// draws a scaled 2d bitmap to our buffer
void rend_DrawScaledBitmap(int x1, int y1, int x2, int y2, int bm, float u0, float v0, float u1, float v1, int color,
float *alphas) {
g3Point *ptr_pnts[4];
g3Point pnts[4];
float r, g, b;
if (color != -1) {
r = GR_COLOR_RED(color) / 255.0;
g = GR_COLOR_GREEN(color) / 255.0;
b = GR_COLOR_BLUE(color) / 255.0;
}
for (int i = 0; i < 4; i++) {
if (color == -1)
pnts[i].p3_l = 1.0;
else {
pnts[i].p3_r = r;
pnts[i].p3_g = g;
pnts[i].p3_b = b;
}
if (alphas) {
pnts[i].p3_a = alphas[i];
}
pnts[i].p3_z = 1.0f;
pnts[i].p3_flags = PF_PROJECTED;
}
pnts[0].p3_sx = x1;
pnts[0].p3_sy = y1;
pnts[0].p3_u = u0;
pnts[0].p3_v = v0;
pnts[1].p3_sx = x2;
pnts[1].p3_sy = y1;
pnts[1].p3_u = u1;
pnts[1].p3_v = v0;
pnts[2].p3_sx = x2;
pnts[2].p3_sy = y2;
pnts[2].p3_u = u1;
pnts[2].p3_v = v1;
pnts[3].p3_sx = x1;
pnts[3].p3_sy = y2;
pnts[3].p3_u = u0;
pnts[3].p3_v = v1;
ptr_pnts[0] = &pnts[0];
ptr_pnts[1] = &pnts[1];
ptr_pnts[2] = &pnts[2];
ptr_pnts[3] = &pnts[3];
rend_SetTextureType(TT_LINEAR);
rend_DrawPolygon2D(bm, ptr_pnts, 4);
}
// given a chunked bitmap, renders it.
void rend_DrawChunkedBitmap(chunked_bitmap *chunk, int x, int y, uint8_t alpha) {
int *bm_array = chunk->bm_array;
int w = chunk->w;
int h = chunk->h;
int piece_w = bm_w(bm_array[0], 0);
int piece_h = bm_h(bm_array[0], 0);
int screen_w, screen_h;
int i, t;
rend_SetZBufferState(0);
rend_GetProjectionParameters(&screen_w, &screen_h);
for (i = 0; i < h; i++) {
for (t = 0; t < w; t++) {
int dx = x + (piece_w * t);
int dy = y + (piece_h * i);
int dw, dh;
if ((dx + piece_w) > screen_w)
dw = piece_w - ((dx + piece_w) - screen_w);
else
dw = piece_w;
if ((dy + piece_h) > screen_h)
dh = piece_h - ((dy + piece_h) - screen_h);
else
dh = piece_h;
float u2 = (float)dw / (float)piece_w;
float v2 = (float)dh / (float)piece_h;
rend_DrawSimpleBitmap(bm_array[i * w + t], dx, dy);
}
}
rend_SetZBufferState(1);
}
// given a chunked bitmap, renders it.scaled
void rend_DrawScaledChunkedBitmap(chunked_bitmap *chunk, int x, int y, int neww, int newh, uint8_t alpha) {
int *bm_array = chunk->bm_array;
int w = chunk->w;
int h = chunk->h;
int piece_w;
int piece_h;
int screen_w, screen_h;
int i, t;
float scalew, scaleh;
scalew = ((float)neww) / ((float)chunk->pw);
scaleh = ((float)newh) / ((float)chunk->ph);
piece_w = scalew * ((float)bm_w(bm_array[0], 0));
piece_h = scaleh * ((float)bm_h(bm_array[0], 0));
rend_GetProjectionParameters(&screen_w, &screen_h);
rend_SetOverlayType(OT_NONE);
rend_SetLighting(LS_NONE);
rend_SetColorModel(CM_MONO);
rend_SetZBufferState(0);
rend_SetAlphaType(AT_CONSTANT_TEXTURE);
rend_SetAlphaValue(alpha);
rend_SetWrapType(WT_WRAP);
for (i = 0; i < h; i++) {
for (t = 0; t < w; t++) {
int dx = x + (piece_w * t);
int dy = y + (piece_h * i);
int dw, dh;
if ((dx + piece_w) > screen_w)
dw = piece_w - ((dx + piece_w) - screen_w);
else
dw = piece_w;
if ((dy + piece_h) > screen_h)
dh = piece_h - ((dy + piece_h) - screen_h);
else
dh = piece_h;
float u2 = (float)dw / (float)piece_w;
float v2 = (float)dh / (float)piece_h;
rend_DrawScaledBitmap(dx, dy, dx + dw, dy + dh, bm_array[i * w + t], 0, 0, u2, v2);
}
}
rend_SetZBufferState(1);
}
// Sets some global preferences for the renderer
int rend_SetPreferredState(renderer_preferred_state *pref_state) {
int retval = 1;
renderer_preferred_state old_state = gpu_preferred_state;
gpu_preferred_state = *pref_state;
if (gpu_state.initted) {
int reinit = 0;
mprintf(0, "Inside pref state!\n");
// Change gamma if needed
if (pref_state->width != gpu_state.screen_width || pref_state->height != gpu_state.screen_height ||
old_state.bit_depth != pref_state->bit_depth) {
reinit = 1;
}
if (reinit) {
retval = rend_ReInit();
} else {
if (old_state.gamma != pref_state->gamma) {
rend_SetGammaValue(pref_state->gamma);
}
}
} else {
gpu_preferred_state = *pref_state;
}
return retval;
}
// Draws a simple bitmap at the specified x,y location
void rend_DrawSimpleBitmap(int bm_handle, int x, int y) {
rend_SetAlphaType(AT_CONSTANT_TEXTURE);
rend_SetAlphaValue(255);
rend_SetLighting(LS_NONE);
rend_SetColorModel(CM_MONO);
rend_SetOverlayType(OT_NONE);
rend_SetFiltering(0);
rend_DrawScaledBitmap(x, y, x + bm_w(bm_handle, 0), y + bm_h(bm_handle, 0), bm_handle, 0, 0, 1, 1);
rend_SetFiltering(1);
}
// Fills in the passed in pointer with the current rendering state
void rend_GetRenderState(rendering_state *rstate) { memcpy(rstate, &gpu_state, sizeof(rendering_state)); }
// Preuploads a texture to the video card
void rend_PreUploadTextureToCard(int handle, int map_type) {}
// Frees an uploaded texture from the video card
void rend_FreePreUploadedTexture(int handle, int map_type) {}
// Returns 1 if there is mid video memory, 2 if there is low vid memory, or 0 if there is large vid memory
int rend_LowVidMem(void) { return 0; }
// Returns 1 if the renderer supports bumpmapping
int rend_SupportsBumpmapping(void) { return 0; }
// Sets a bumpmap to be rendered, or turns off bumpmapping altogether
void rend_SetBumpmapReadyState(int state, int map) {}
// returns rendering statistics for the frame
void rend_GetStatistics(tRendererStats *stats) {
if (Renderer_initted) {
stats->poly_count = gpu_last_frame_polys_drawn;
stats->vert_count = gpu_last_frame_verts_processed;
stats->texture_uploads = gpu_last_uploaded;
} else {
memset(stats, 0, sizeof(tRendererStats));
}
}
#ifdef DEDICATED_ONLY
void rend_DrawPolygon2D(int, g3Point **, int, int) {}
void rend_DrawPolygon3D(int, g3Point **, int, int) {}
#else
// Takes nv vertices and draws the 2D polygon defined by those vertices.
// Uses bitmap "handle" as a texture
void rend_DrawPolygon2D(int handle, g3Point **p, int nv) {
ASSERT(nv < 100);
ASSERT(gpu_Overlay_type == OT_NONE);
g3_RefreshTransforms(true);
if (UseMultitexture) {
gpu_SetMultitextureBlendMode(false);
}
int xAdd = gpu_state.clip_x1;
int yAdd = gpu_state.clip_y1;
float fr, fg, fb;
if (gpu_state.cur_light_state == LS_FLAT_GOURAUD || gpu_state.cur_texture_quality == 0) {
float scale = 1.0f / 255.0f;
fr = GR_COLOR_RED(gpu_state.cur_color) * scale;
fg = GR_COLOR_GREEN(gpu_state.cur_color) * scale;
fb = GR_COLOR_BLUE(gpu_state.cur_color) * scale;
}
// make sure our bitmap is ready to be drawn
gpu_BindTexture(handle, MAP_TYPE_BITMAP, 0);
float alpha = gpu_Alpha_multiplier * gpu_Alpha_factor;
PosColorUVVertex *vData = &vArray[0];
// Specify our coordinates
int i;
for (i = 0; i < nv; ++i, ++vData) {
g3Point *pnt = p[i];
if (gpu_state.cur_alpha_type & ATF_VERTEX) {
// the alpha should come from the vertex
alpha = pnt->p3_a * gpu_Alpha_multiplier * gpu_Alpha_factor;
}
// If we have a lighting model, apply the correct lighting!
if (gpu_state.cur_light_state == LS_FLAT_GOURAUD || gpu_state.cur_texture_quality == 0) {
// pull the color from the constant color data
vData->color.r = fr;
vData->color.g = fg;
vData->color.b = fb;
vData->color.a = alpha;
} else if (gpu_state.cur_light_state != LS_NONE) {
// Do lighting based on intensity (MONO) or colored (RGB)
if (gpu_state.cur_color_model == CM_MONO) {
vData->color.r = pnt->p3_l;
vData->color.g = pnt->p3_l;
vData->color.b = pnt->p3_l;
vData->color.a = alpha;
} else {
vData->color.r = pnt->p3_r;
vData->color.g = pnt->p3_g;
vData->color.b = pnt->p3_b;
vData->color.a = alpha;
}
} else {
// force white
vData->color.r = 1.0f;
vData->color.g = 1.0f;
vData->color.b = 1.0f;
vData->color.a = alpha;
}
vData->uv.s = pnt->p3_u;
vData->uv.t = pnt->p3_v;
vData->uv.r = 0.0f;
vData->uv.w = 1.0f;
// Finally, specify a vertex
vData->pos.x = pnt->p3_sx + xAdd;
vData->pos.y = pnt->p3_sy + yAdd;
vData->pos.z = 0.0f;
}
gpu_RenderPolygon(&vArray[0], nv);
}
// Takes nv vertices and draws the 3D polygon defined by those vertices.
// Uses bitmap "handle" as a texture
void rend_DrawPolygon3D(int handle, g3Point **p, int nv, int map_type) {
g3Point *pnt;
int i;
float fr, fg, fb;
float alpha;
ASSERT(nv < 100);
g3_RefreshTransforms(false);
if (gpu_state.cur_texture_quality == 0) {
gpu_DrawFlatPolygon3D(p, nv);
return;
}
if (gpu_Overlay_type != OT_NONE && UseMultitexture) {
rend_DrawMultitexturePolygon3D(handle, p, nv, map_type);
return;
}
if (gpu_state.cur_light_state == LS_FLAT_GOURAUD) {
fr = GR_COLOR_RED(gpu_state.cur_color) / 255.0;
fg = GR_COLOR_GREEN(gpu_state.cur_color) / 255.0;
fb = GR_COLOR_BLUE(gpu_state.cur_color) / 255.0;
}
if (UseMultitexture) {
gpu_SetMultitextureBlendMode(false);
}
gpu_BindTexture(handle, map_type, 0);
alpha = gpu_Alpha_multiplier * gpu_Alpha_factor;
PosColorUVVertex *vData = &vArray[0];
// Specify our coordinates
for (i = 0; i < nv; i++, vData++) {
pnt = p[i];
// all points should be original
ASSERT(pnt->p3_flags & PF_ORIGPOINT);
////////////////////////////////////////////
if (pnt->p3_flags & PF_ORIGPOINT) {
if (!(pnt->p3_flags & PF_PROJECTED)) {
g3_ProjectPoint(pnt);
}
// get the original point
float origPoint[4];
origPoint[0] = pnt->p3_vecPreRot.x;
origPoint[1] = pnt->p3_vecPreRot.y;
origPoint[2] = pnt->p3_vecPreRot.z;
origPoint[3] = 1.0f;
// transform by the full transform
float view[4];
g3_TransformVert(view, origPoint, gTransformFull);
vector tempv = pnt->p3_vecPreRot - View_position;
vector testPt = tempv * Unscaled_matrix;
float screenX = pnt->p3_sx + gpu_state.clip_x1;
float screenY = pnt->p3_sy + gpu_state.clip_y1;
// normalize
float oOW = 1.0f / view[3];
view[0] *= oOW;
view[1] *= oOW;
view[2] *= oOW;
oOW *= 1.0f;
}
////////////////////////////////////////////
if (gpu_state.cur_alpha_type & ATF_VERTEX) {
alpha = pnt->p3_a * gpu_Alpha_multiplier * gpu_Alpha_factor;
}
// If we have a lighting model, apply the correct lighting!
if (gpu_state.cur_light_state != LS_NONE) {
if (gpu_state.cur_light_state == LS_FLAT_GOURAUD) {
vData->color.r = fr;
vData->color.g = fg;
vData->color.b = fb;
vData->color.a = alpha;
} else {
// Do lighting based on intesity (MONO) or colored (RGB)
if (gpu_state.cur_color_model == CM_MONO) {
vData->color.r = pnt->p3_l;
vData->color.g = pnt->p3_l;
vData->color.b = pnt->p3_l;
vData->color.a = alpha;
} else {
vData->color.r = pnt->p3_r;
vData->color.g = pnt->p3_g;
vData->color.b = pnt->p3_b;
vData->color.a = alpha;
}
}
} else {
vData->color.r = 1;
vData->color.g = 1;
vData->color.b = 1;
vData->color.a = alpha;
}
vData->uv.s = pnt->p3_u;
vData->uv.t = pnt->p3_v;
vData->uv.r = 0.0f;
vData->uv.w = 1.0f;
// Finally, specify a vertex
vData->pos = pnt->p3_vecPreRot;
}
// And draw!
gpu_RenderPolygon(&vArray[0], nv);
// If there is a lightmap to draw, draw it as well
if (gpu_Overlay_type != OT_NONE) {
return; // Temp fix until I figure out whats going on
Int3(); // Shouldn't reach here
}
}
#endif // DEDICATED_ONLY
// Takes nv vertices and draws the polygon defined by those vertices. Uses bitmap "handle"
// as a texture
void rend_DrawMultitexturePolygon3D(int handle, g3Point **p, int nv, int map_type) {
g3Point *pnt;
int i, fr, fg, fb;
float alpha;
float one_over_square_res = 1.0 / GameLightmaps[gpu_Overlay_map].square_res;
float xscalar = (float)GameLightmaps[gpu_Overlay_map].width * one_over_square_res;
float yscalar = (float)GameLightmaps[gpu_Overlay_map].height * one_over_square_res;
ASSERT(nv < 100);
if (gpu_state.cur_light_state == LS_NONE) {
fr = GR_COLOR_RED(gpu_state.cur_color);
fg = GR_COLOR_GREEN(gpu_state.cur_color);
fb = GR_COLOR_BLUE(gpu_state.cur_color);
}
alpha = gpu_Alpha_multiplier * gpu_Alpha_factor;
PosColorUV2Vertex *vData = &vArray2[0];
// Specify our coordinates
for (i = 0; i < nv; i++, vData++) {
pnt = p[i];
ASSERT(pnt->p3_flags & PF_ORIGPOINT);
if (gpu_state.cur_alpha_type & ATF_VERTEX)
alpha = pnt->p3_a * gpu_Alpha_multiplier * gpu_Alpha_factor;
// If we have a lighting model, apply the correct lighting!
if (gpu_state.cur_light_state != LS_NONE) {
// Do lighting based on intesity (MONO) or colored (RGB)
if (gpu_state.cur_color_model == CM_MONO) {
vData->color.r = pnt->p3_l;
vData->color.g = pnt->p3_l;
vData->color.b = pnt->p3_l;
vData->color.a = alpha;
} else {
vData->color.r = pnt->p3_r;
vData->color.g = pnt->p3_g;
vData->color.b = pnt->p3_b;
vData->color.a = alpha;
}
} else {
vData->color.r = 1;
vData->color.g = 1;
vData->color.b = 1;
vData->color.a = alpha;
}
/*
// Texture this polygon!
float texw=1.0/(pnt->p3_z+Z_bias);
vData->uv0.s=pnt->p3_u*texw;
vData->uv0.t=pnt->p3_v*texw;
vData->uv0.r=0;
vData->uv0.w=texw;
vData->uv1.s=pnt->p3_u2*xscalar*texw;
vData->uv1.t=pnt->p3_v2*yscalar*texw;
vData->uv1.r=0;
vData->uv1.w=texw;
*/
vData->uv0.s = pnt->p3_u;
vData->uv0.t = pnt->p3_v;
vData->uv0.r = 0.0f;
vData->uv0.w = 1.0f;
vData->uv1.s = pnt->p3_u2 * xscalar;
vData->uv1.t = pnt->p3_v2 * yscalar;
vData->uv1.r = 0.0f;
vData->uv1.w = 1.0f;
// Finally, specify a vertex
/*
vData->pos.x=pnt->p3_sx+x_add;
vData->pos.y=pnt->p3_sy+y_add;
vData->pos.z = -std::max(0,std::min(1.0,1.0-(1.0/(pnt->p3_z+Z_bias))));
*/
vData->pos = pnt->p3_vecPreRot;
}
// make sure our bitmap is ready to be drawn
gpu_BindTexture(handle, map_type, 0);
// make sure our bitmap is ready to be drawn
gpu_BindTexture(gpu_Overlay_map, MAP_TYPE_LIGHTMAP, 1);
gpu_SetMultitextureBlendMode(true);
gpu_RenderPolygonUV2(&vArray2[0], nv);
}