#include "gl_local.h"
#include <GLFW/glfw3.h>
#include "../client/keys.h"
extern void GL_draw_model_not_found(void);
extern void GL_draw_beam(entity_t *e);
extern void GL_draw_sprite(entity_t *e, model_t *model);
extern void GL_draw_2d_quad(GLuint image, float x1, float y1, float x2, float y2, float s1, float t1, float s2,
float t2, float r, float g, float b, float a);
ALIAS_GL_IMPL_BLOCK(Frame, float32(time), float32x3(viewOrigin))
ALIAS_GL_IMPL_BLOCK(View, float32x3(origin))
static inline void prepare_model_view(void) {
alias_matrix_multiply(u_view_matrix.uniform.data.mat, u_model_matrix.uniform.data.mat,
u_model_view_matrix.uniform.data.mat);
}
static inline void prepare_view_projection(void) {
alias_matrix_multiply(u_projection_matrix.uniform.data.mat, u_view_matrix.uniform.data.mat,
u_view_projection_matrix.uniform.data.mat);
}
static inline void prepare_model_view_projection(void) {
alias_gl_ShaderResource_prepare(&u_view_projection_matrix);
alias_matrix_multiply(u_view_projection_matrix.uniform.data.mat, u_model_matrix.uniform.data.mat,
u_model_view_projection_matrix.uniform.data.mat);
}
struct alias_gl_ShaderResource u_time = {.type = alias_gl_Type_float, .name = "time"};
struct alias_gl_ShaderResource u_model_matrix = {.type = alias_gl_Type_float4x4, .name = "model_matrix"};
struct alias_gl_ShaderResource u_view_matrix = {.type = alias_gl_Type_float4x4, .name = "view_matrix"};
struct alias_gl_ShaderResource u_model_view_matrix = {
.type = alias_gl_Type_float4x4, .name = "model_view_matrix", .uniform.prepare = prepare_model_view};
struct alias_gl_ShaderResource u_projection_matrix = {.type = alias_gl_Type_float4x4, .name = "projection_matrix"};
struct alias_gl_ShaderResource u_view_projection_matrix = {
.type = alias_gl_Type_float4x4, .name = "view_projection_matrix", .uniform.prepare = prepare_view_projection};
struct alias_gl_ShaderResource u_model_view_projection_matrix = {
.type = alias_gl_Type_float4x4, .name = "model_view_projection_matrix", .uniform.prepare = prepare_model_view_projection};
struct alias_gl_Buffer u_frame_buffer = {.kind = alias_gl_Buffer_cpu, .size = sizeof(struct alias_gl_Frame)};
struct alias_gl_ShaderResource u_frame = {.type = alias_gl_Type_shaderStorageBuffer,
.name = "frame",
.block.buffer = &u_frame_buffer,
.block.snippet = &alias_gl_Frame_snippet};
struct alias_gl_ShaderResource u_view;
struct alias_gl_ShaderResource u_draw;
void R_Clear(void);
viddef_t vid;
refimport_t ri;
model_t *r_worldmodel[CMODEL_COUNT];
float gldepthmin, gldepthmax;
glconfig_t gl_config;
glstate_t gl_state;
image_t *r_notexture; image_t *r_nonormal;
image_t *r_whitepcx;
image_t *r_particletexture;
entity_t *currententity;
cplane_t frustum[4];
int r_visframecount; int r_framecount;
int c_brush_polys, c_alias_polys;
float v_blend[4];
void GL_Strings_f(void);
vec3_t vup;
vec3_t vpn;
vec3_t vright;
vec3_t r_origin;
float r_world_matrix[16];
float r_base_world_matrix[16];
refdef_t r_newrefdef;
int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
cvar_t *r_norefresh;
cvar_t *r_drawentities;
cvar_t *r_drawworld;
cvar_t *r_speeds;
cvar_t *r_fullbright;
cvar_t *r_novis;
cvar_t *r_nocull;
cvar_t *r_lerpmodels;
cvar_t *r_lefthand;
cvar_t *r_lightlevel;
cvar_t *gl_nosubimage;
cvar_t *gl_allow_software;
cvar_t *gl_vertex_arrays;
cvar_t *gl_particle_min_size;
cvar_t *gl_particle_max_size;
cvar_t *gl_particle_size;
cvar_t *gl_particle_att_a;
cvar_t *gl_particle_att_b;
cvar_t *gl_particle_att_c;
cvar_t *gl_ext_swapinterval;
cvar_t *gl_ext_palettedtexture;
cvar_t *gl_ext_multitexture;
cvar_t *gl_ext_pointparameters;
cvar_t *gl_ext_compiled_vertex_array;
cvar_t *gl_log;
cvar_t *gl_bitdepth;
cvar_t *gl_driver;
cvar_t *gl_lightmap;
cvar_t *gl_shadows;
cvar_t *gl_mode;
cvar_t *gl_dynamic;
cvar_t *gl_monolightmap;
cvar_t *gl_modulate;
cvar_t *gl_nobind;
cvar_t *gl_round_down;
cvar_t *gl_picmip;
cvar_t *gl_skymip;
cvar_t *gl_showtris;
cvar_t *gl_ztrick;
cvar_t *gl_finish;
cvar_t *gl_clear;
cvar_t *gl_cull;
cvar_t *gl_polyblend;
cvar_t *gl_flashblend;
cvar_t *gl_playermip;
cvar_t *gl_saturatelighting;
cvar_t *gl_swapinterval;
cvar_t *gl_texturemode;
cvar_t *gl_lockpvs;
cvar_t *gl_3dlabs_broken;
extern cvar_t *vid_fullscreen;
extern cvar_t *vid_gamma;
extern cvar_t *vid_ref;
bool R_CullBox(vec3_t mins, vec3_t maxs) {
int i;
if(r_nocull->value)
return false;
for(i = 0; i < 4; i++)
if(BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2)
return true;
return false;
}
void GL_TransformForEntity(entity_t *e) {
alias_translate(u_model_matrix.uniform.data.mat, e->origin[0], e->origin[1], e->origin[2]);
alias_rotate_z(u_model_matrix.uniform.data.mat, e->angles[1]);
alias_rotate_y(u_model_matrix.uniform.data.mat, -e->angles[0]);
alias_rotate_x(u_model_matrix.uniform.data.mat, -e->angles[2]);
}
void R_DrawEntitiesOnList(void) {
int i;
if(!r_drawentities->value)
return;
for(i = 0; i < r_newrefdef.num_entities; i++) {
currententity = &r_newrefdef.entities[i];
if(currententity->flags & RF_TRANSLUCENT)
continue;
if(currententity->flags & RF_BEAM) {
GL_draw_beam(currententity);
} else {
model_t *model = currententity->model;
if(!model) {
GL_draw_model_not_found();
continue;
}
switch(model->type) {
case mod_alias:
R_DrawAliasModel(currententity, model);
break;
case mod_brush:
R_DrawBrushModel(currententity, model);
break;
case mod_sprite:
GL_draw_sprite(currententity, model);
break;
default:
GL_draw_model_not_found();
break;
}
}
}
for(i = 0; i < r_newrefdef.num_entities; i++) {
currententity = &r_newrefdef.entities[i];
if(!(currententity->flags & RF_TRANSLUCENT))
continue;
if(currententity->flags & RF_BEAM) {
GL_draw_beam(currententity);
} else {
model_t *model = currententity->model;
if(!model) {
GL_draw_model_not_found();
continue;
}
switch(model->type) {
case mod_alias:
R_DrawAliasModel(currententity, model);
break;
case mod_brush:
R_DrawBrushModel(currententity, model);
break;
case mod_sprite:
GL_draw_sprite(currententity, model);
break;
default:
GL_draw_model_not_found();
break;
}
}
}
}
int SignbitsForPlane(cplane_t *out) {
int bits, j;
bits = 0;
for(j = 0; j < 3; j++) {
if(out->normal[j] < 0)
bits |= 1 << j;
}
return bits;
}
void R_SetFrustum(void) {
int i;
RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90 - r_newrefdef.fov_x / 2));
RotatePointAroundVector(frustum[1].normal, vup, vpn, 90 - r_newrefdef.fov_x / 2);
RotatePointAroundVector(frustum[2].normal, vright, vpn, 90 - r_newrefdef.fov_y / 2);
RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90 - r_newrefdef.fov_y / 2));
for(i = 0; i < 4; i++) {
frustum[i].type = PLANE_ANYZ;
frustum[i].dist = DotProduct(r_origin, frustum[i].normal);
frustum[i].signbits = SignbitsForPlane(&frustum[i]);
}
}
void R_SetupFrame(void) {
int i;
mleaf_t *leaf;
r_framecount++;
u_time.uniform.data._float = r_newrefdef.time;
VectorCopy(r_newrefdef.vieworg, r_origin);
AngleVectors(r_newrefdef.viewangles, vpn, vright, vup);
if(!(r_newrefdef.rdflags & RDF_NOWORLDMODEL) && r_worldmodel[r_newrefdef.cmodel_index]->type == mod_brush) {
r_oldviewcluster = r_viewcluster;
r_oldviewcluster2 = r_viewcluster2;
leaf = Mod_PointInLeaf(r_origin, r_worldmodel[r_newrefdef.cmodel_index]);
r_viewcluster = r_viewcluster2 = leaf->cluster;
if(!leaf->contents) { vec3_t temp;
VectorCopy(r_origin, temp);
temp[2] -= 16;
leaf = Mod_PointInLeaf(temp, r_worldmodel[r_newrefdef.cmodel_index]);
if(!(leaf->contents & CONTENTS_SOLID) && (leaf->cluster != r_viewcluster2))
r_viewcluster2 = leaf->cluster;
} else { vec3_t temp;
VectorCopy(r_origin, temp);
temp[2] += 16;
leaf = Mod_PointInLeaf(temp, r_worldmodel[r_newrefdef.cmodel_index]);
if(!(leaf->contents & CONTENTS_SOLID) && (leaf->cluster != r_viewcluster2))
r_viewcluster2 = leaf->cluster;
}
}
for(i = 0; i < 4; i++)
v_blend[i] = r_newrefdef.blend[i];
c_brush_polys = 0;
c_alias_polys = 0;
if(r_newrefdef.rdflags & RDF_NOWORLDMODEL) {
glEnable(GL_SCISSOR_TEST);
glClearColor(0.3, 0.3, 0.3, 1);
glScissor(r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1, 0, 0.5, 0.5);
glDisable(GL_SCISSOR_TEST);
}
}
void MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) {
GLdouble xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
xmin += -(2 * gl_state.camera_separation) / zNear;
xmax += -(2 * gl_state.camera_separation) / zNear;
alias_matrix_frustum(xmin, xmax, ymin, ymax, zNear, zFar, u_projection_matrix.uniform.data.mat);
}
void R_SetupGL(void) {
float screenaspect;
int x, x2, y2, y, w, h;
x = floor(r_newrefdef.x * vid.width / vid.width);
x2 = ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width);
y = floor(vid.height - r_newrefdef.y * vid.height / vid.height);
y2 = ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height);
w = x2 - x;
h = y - y2;
glViewport(x, y2, w, h);
screenaspect = (float)r_newrefdef.width / r_newrefdef.height;
MYgluPerspective(r_newrefdef.fov_y, screenaspect, 4, 4096);
glCullFace(GL_FRONT);
alias_matrix_identity(u_view_matrix.uniform.data.mat);
alias_rotate_x(u_view_matrix.uniform.data.mat, -90);
alias_rotate_z(u_view_matrix.uniform.data.mat, 90);
alias_rotate_x(u_view_matrix.uniform.data.mat, -r_newrefdef.viewangles[2]);
alias_rotate_y(u_view_matrix.uniform.data.mat, -r_newrefdef.viewangles[0]);
alias_rotate_z(u_view_matrix.uniform.data.mat, -r_newrefdef.viewangles[1]);
alias_translate(u_view_matrix.uniform.data.mat, -r_newrefdef.vieworg[0], -r_newrefdef.vieworg[1],
-r_newrefdef.vieworg[2]);
if(gl_cull->value)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
}
void R_Clear(void) {
GLboolean old_mask;
glGetBooleanv(GL_DEPTH_WRITEMASK, &old_mask);
glDepthMask(GL_TRUE);
if(gl_clear->value || true)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear(GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_LEQUAL);
glDepthMask(old_mask);
}
void R_Flash(void) {
GL_draw_2d_quad(r_whitepcx->texnum, 0, 0, vid.width, vid.height, 0, 0, 1, 1, r_newrefdef.blend[0],
r_newrefdef.blend[1], r_newrefdef.blend[2], r_newrefdef.blend[3]);
}
void R_RenderView(refdef_t *fd) {
if(r_norefresh->value)
return;
r_newrefdef = *fd;
if(!r_worldmodel[r_newrefdef.cmodel_index] && !(r_newrefdef.rdflags & RDF_NOWORLDMODEL))
ri.Sys_Error(ERR_DROP, "R_RenderView: NULL worldmodel");
model_t *model = r_worldmodel[r_newrefdef.cmodel_index];
if(r_speeds->value) {
c_brush_polys = 0;
c_alias_polys = 0;
}
R_PushDlights(model);
if(gl_finish->value)
glFinish();
R_SetupFrame();
R_SetFrustum();
R_SetupGL();
R_MarkLeaves(model);
R_DrawWorld(model);
R_DrawEntitiesOnList();
GL_draw_particles();
R_DrawAlphaSurfaces(model);
if(r_speeds->value) {
ri.Con_Printf(PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n", c_brush_polys, c_alias_polys, c_visible_textures,
c_visible_lightmaps);
}
}
void R_SetGL2D(void) {
alias_matrix_ortho(0, vid.width, vid.height, 0, -99999, 99999, u_projection_matrix.uniform.data.mat);
alias_matrix_identity(u_view_matrix.uniform.data.mat);
glDisable(GL_CULL_FACE);
}
void R_SetLightLevel(void) {
struct SH1 shadelight;
if(r_newrefdef.rdflags & RDF_NOWORLDMODEL)
return;
shadelight = R_LightPoint(r_worldmodel[r_newrefdef.cmodel_index], r_newrefdef.vieworg);
SH1_Normalize(shadelight, &r_lightlevel->value);
}
void R_RenderFrame(refdef_t *fd) {
static uint32_t frame_index = 0;
struct alias_gl_Frame *frame = (struct alias_gl_Frame *)alias_gl_updateBufferBegin(&u_frame_buffer, 0, sizeof(*frame));
frame->time = fd->time;
frame->index = frame_index++;
VectorCopy(fd->vieworg, frame->viewOrigin);
alias_gl_updateBufferEnd(&u_frame_buffer, 0, sizeof(*frame));
R_RenderView(fd);
R_SetLightLevel();
R_SetGL2D();
R_Flash();
}
void R_Register(void) {
r_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
r_norefresh = ri.Cvar_Get("r_norefresh", "0", 0);
r_fullbright = ri.Cvar_Get("r_fullbright", "0", 0);
r_drawentities = ri.Cvar_Get("r_drawentities", "1", 0);
r_drawworld = ri.Cvar_Get("r_drawworld", "1", 0);
r_novis = ri.Cvar_Get("r_novis", "0", 0);
r_nocull = ri.Cvar_Get("r_nocull", "0", 0);
r_lerpmodels = ri.Cvar_Get("r_lerpmodels", "1", 0);
r_speeds = ri.Cvar_Get("r_speeds", "0", 0);
r_lightlevel = ri.Cvar_Get("r_lightlevel", "0", 0);
gl_nosubimage = ri.Cvar_Get("gl_nosubimage", "0", 0);
gl_allow_software = ri.Cvar_Get("gl_allow_software", "0", 0);
gl_particle_min_size = ri.Cvar_Get("gl_particle_min_size", "2", CVAR_ARCHIVE);
gl_particle_max_size = ri.Cvar_Get("gl_particle_max_size", "40", CVAR_ARCHIVE);
gl_particle_size = ri.Cvar_Get("gl_particle_size", "40", CVAR_ARCHIVE);
gl_particle_att_a = ri.Cvar_Get("gl_particle_att_a", "0.01", CVAR_ARCHIVE);
gl_particle_att_b = ri.Cvar_Get("gl_particle_att_b", "0.0", CVAR_ARCHIVE);
gl_particle_att_c = ri.Cvar_Get("gl_particle_att_c", "0.01", CVAR_ARCHIVE);
gl_modulate = ri.Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
gl_log = ri.Cvar_Get("gl_log", "0", 0);
gl_bitdepth = ri.Cvar_Get("gl_bitdepth", "0", 0);
gl_mode = ri.Cvar_Get("gl_mode", "3", CVAR_ARCHIVE);
gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0);
gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
gl_dynamic = ri.Cvar_Get("gl_dynamic", "1", 0);
gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
gl_round_down = ri.Cvar_Get("gl_round_down", "1", 0);
gl_picmip = ri.Cvar_Get("gl_picmip", "0", 0);
gl_skymip = ri.Cvar_Get("gl_skymip", "0", 0);
gl_showtris = ri.Cvar_Get("gl_showtris", "0", 0);
gl_ztrick = ri.Cvar_Get("gl_ztrick", "0", 0);
gl_finish = ri.Cvar_Get("gl_finish", "0", CVAR_ARCHIVE);
gl_clear = ri.Cvar_Get("gl_clear", "0", 0);
gl_cull = ri.Cvar_Get("gl_cull", "1", 0);
gl_polyblend = ri.Cvar_Get("gl_polyblend", "1", 0);
gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0);
gl_playermip = ri.Cvar_Get("gl_playermip", "0", 0);
gl_monolightmap = ri.Cvar_Get("gl_monolightmap", "0", 0);
gl_driver = ri.Cvar_Get("gl_driver", "opengl32", CVAR_ARCHIVE);
gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0);
gl_vertex_arrays = ri.Cvar_Get("gl_vertex_arrays", "0", CVAR_ARCHIVE);
gl_ext_swapinterval = ri.Cvar_Get("gl_ext_swapinterval", "1", CVAR_ARCHIVE);
gl_ext_palettedtexture = ri.Cvar_Get("gl_ext_palettedtexture", "1", CVAR_ARCHIVE);
gl_ext_multitexture = ri.Cvar_Get("gl_ext_multitexture", "1", CVAR_ARCHIVE);
gl_ext_pointparameters = ri.Cvar_Get("gl_ext_pointparameters", "1", CVAR_ARCHIVE);
gl_ext_compiled_vertex_array = ri.Cvar_Get("gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE);
gl_swapinterval = ri.Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE);
gl_saturatelighting = ri.Cvar_Get("gl_saturatelighting", "0", 0);
gl_3dlabs_broken = ri.Cvar_Get("gl_3dlabs_broken", "1", CVAR_ARCHIVE);
vid_fullscreen = ri.Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
vid_gamma = ri.Cvar_Get("vid_gamma", "1.0", CVAR_ARCHIVE);
vid_ref = ri.Cvar_Get("vid_ref", "soft", CVAR_ARCHIVE);
ri.Cmd_AddCommand("imagelist", GL_ImageList_f);
ri.Cmd_AddCommand("screenshot", GL_ScreenShot_f);
ri.Cmd_AddCommand("modellist", Mod_Modellist_f);
ri.Cmd_AddCommand("gl_strings", GL_Strings_f);
}
bool R_SetMode(void) {
rserr_t err;
bool fullscreen;
if(vid_fullscreen->modified && !gl_config.allow_cds) {
ri.Con_Printf(PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n");
ri.Cvar_SetValue("vid_fullscreen", !vid_fullscreen->value);
vid_fullscreen->modified = false;
}
fullscreen = vid_fullscreen->value;
vid_fullscreen->modified = false;
gl_mode->modified = false;
if((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, fullscreen)) == rserr_ok) {
gl_state.prev_mode = gl_mode->value;
} else {
if(err == rserr_invalid_fullscreen) {
ri.Cvar_SetValue("vid_fullscreen", 0);
vid_fullscreen->modified = false;
ri.Con_Printf(PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n");
if((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, false)) == rserr_ok)
return true;
} else if(err == rserr_invalid_mode) {
ri.Cvar_SetValue("gl_mode", gl_state.prev_mode);
gl_mode->modified = false;
ri.Con_Printf(PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n");
}
if((err = GLimp_SetMode(&vid.width, &vid.height, gl_state.prev_mode, false)) != rserr_ok) {
ri.Con_Printf(PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n");
return false;
}
}
return true;
}
static inline void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
const GLchar *message, const void *userParam) {
if(type == GL_DEBUG_TYPE_ERROR || type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR ||
type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR || type == GL_DEBUG_TYPE_PORTABILITY) {
ri.Con_Printf(PRINT_ALL, "OPENGL debug error - %s\n",
message); }
if(type == GL_DEBUG_TYPE_PERFORMANCE) {
}
if(type == GL_DEBUG_TYPE_OTHER) {
}
if(type == GL_DEBUG_TYPE_MARKER) {
}
}
bool R_Init(void *hinstance, void *hWnd) {
int err;
ri.Con_Printf(PRINT_ALL, "ref_gl version: " REF_VERSION "\n");
Draw_GetPalette();
R_Register();
if(!GLimp_Init(hinstance, hWnd)) {
return -1;
}
gl_state.prev_mode = 3;
if(!R_SetMode()) {
ri.Con_Printf(PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n");
return -1;
}
if(!QGL_Init()) {
ri.Con_Printf(PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string);
return -1;
}
if(glDebugMessageCallback != NULL) {
glDebugMessageCallback(debug_callback, NULL);
}
ri.Vid_MenuInit();
gl_config.vendor_string = glGetString(GL_VENDOR);
ri.Con_Printf(PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string);
gl_config.renderer_string = glGetString(GL_RENDERER);
ri.Con_Printf(PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string);
gl_config.version_string = glGetString(GL_VERSION);
ri.Con_Printf(PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string);
ri.Con_Printf(PRINT_ALL, "GL_EXTENSIONS:");
GLint num_extensions;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for(GLint i = 0; i < num_extensions; i++) {
const GLubyte *name = glGetStringi(GL_EXTENSIONS, i);
ri.Con_Printf(PRINT_ALL, " %s", name);
}
GL_SetDefaultState();
GL_InitImages();
Mod_Init();
R_InitParticleTexture();
Draw_InitLocal();
err = glGetError();
if(err != GL_NO_ERROR)
ri.Con_Printf(PRINT_ALL, "glGetError() = 0x%x\n", err);
return 0;
}
void R_Shutdown(void) {
ri.Cmd_RemoveCommand("modellist");
ri.Cmd_RemoveCommand("screenshot");
ri.Cmd_RemoveCommand("imagelist");
ri.Cmd_RemoveCommand("gl_strings");
Mod_FreeAll();
GL_ShutdownImages();
GLimp_Shutdown();
QGL_Shutdown();
}
void R_BeginFrame(float camera_separation) {
gl_state.camera_separation = camera_separation;
if(gl_mode->modified || vid_fullscreen->modified) { cvar_t *ref;
ref = ri.Cvar_Get("vid_ref", "gl", 0);
ref->modified = true;
}
if(gl_log->modified) {
GLimp_EnableLogging(gl_log->value);
gl_log->modified = false;
}
if(gl_log->value) {
GLimp_LogNewFrame();
}
if(vid_gamma->modified) {
vid_gamma->modified = false;
if(gl_config.renderer & (GL_RENDERER_VOODOO)) {
char envbuffer[1024];
float g;
g = 2.00 * (0.8 - (vid_gamma->value - 0.5)) + 1.0F;
Com_sprintf(envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g);
putenv(envbuffer);
Com_sprintf(envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g);
putenv(envbuffer);
}
}
GLimp_BeginFrame(camera_separation);
glViewport(0, 0, vid.width, vid.height);
alias_matrix_ortho(0, vid.width, vid.height, 0, -99999, 99999, u_projection_matrix.uniform.data.mat);
alias_matrix_identity(u_view_matrix.uniform.data.mat);
glDisable(GL_CULL_FACE);
if(gl_texturemode->modified) {
GL_TextureMode(gl_texturemode->string);
gl_texturemode->modified = false;
}
R_Clear();
alias_gl_resetTemporaryBuffers();
}
unsigned r_rawpalette[256];
void R_SetPalette(const unsigned char *palette) {
int i;
byte *rp = (byte *)r_rawpalette;
if(palette) {
for(i = 0; i < 256; i++) {
rp[i * 4 + 0] = palette[i * 3 + 0];
rp[i * 4 + 1] = palette[i * 3 + 1];
rp[i * 4 + 2] = palette[i * 3 + 2];
rp[i * 4 + 3] = 0xff;
}
} else {
for(i = 0; i < 256; i++) {
rp[i * 4 + 0] = d_8to24table[i] & 0xff;
rp[i * 4 + 1] = (d_8to24table[i] >> 8) & 0xff;
rp[i * 4 + 2] = (d_8to24table[i] >> 16) & 0xff;
rp[i * 4 + 3] = 0xff;
}
}
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 0, 0.5, 0.5);
}
void R_BeginRegistration(const char *map);
struct model_s *R_RegisterModel(int cmodel_index, const char *name);
struct BaseImage *R_RegisterSkin(const char *name);
void R_SetSky(const char *name, float rotate, vec3_t axis);
void R_EndRegistration(void);
void R_RenderFrame(refdef_t *fd);
struct BaseImage *Draw_FindPic(const char *name);
void Draw_Pic(int x, int y, const char *name);
void Draw_Char(int x, int y, int c);
void Draw_TileClear(int x, int y, int w, int h, const char *name);
void Draw_Fill(int x, int y, int w, int h, int c);
void Draw_FadeScreen(void);
void Draw_Triangles(const struct BaseImage *image, const struct DrawVertex *vertexes, uint32_t num_vertexes,
const uint32_t *indexes, uint32_t num_indexes);
refexport_t GetRefAPI(refimport_t rimp) {
extern void GL_set_sky(uint32_t cmodel_index, const char *name, float rotate, vec3_t axis);
refexport_t re;
ri = rimp;
re.api_version = API_VERSION;
re.BeginRegistration = R_BeginRegistration;
re.RegisterModel = R_RegisterModel;
re.RegisterSkin = R_RegisterSkin;
re.RegisterPic = Draw_FindPic;
re.SetSky = GL_set_sky;
re.EndRegistration = R_EndRegistration;
re.RenderFrame = R_RenderFrame;
re.DrawGetPicSize = Draw_GetPicSize;
re.DrawPic = Draw_Pic;
re.DrawStretchPic = Draw_StretchPic;
re.DrawChar = Draw_Char;
re.DrawTileClear = Draw_TileClear;
re.DrawFill = Draw_Fill;
re.DrawFadeScreen = Draw_FadeScreen;
re.DrawStretchRaw = Draw_StretchRaw;
re.DrawTriangles = Draw_Triangles;
re.Init = R_Init;
re.Shutdown = R_Shutdown;
re.CinematicSetPalette = R_SetPalette;
re.BeginFrame = R_BeginFrame;
re.EndFrame = GLimp_EndFrame;
re.AppActivate = GLimp_AppActivate;
Swap_Init();
return re;
}
#ifndef REF_HARD_LINKED
void Sys_Error(char *error, ...) {
va_list argptr;
char text[1024];
va_start(argptr, error);
vsprintf(text, error, argptr);
va_end(argptr);
ri.Sys_Error(ERR_FATAL, "%s", text);
}
void Com_Printf(char *fmt, ...) {
va_list argptr;
char text[1024];
va_start(argptr, fmt);
vsprintf(text, fmt, argptr);
va_end(argptr);
ri.Con_Printf(PRINT_ALL, "%s", text);
}
#endif