/* * @brief */ static void R_DrawLines(void) { if (!r_draw.line_arrays.vert_index) return; R_EnableTexture(&texunit_diffuse, false); R_EnableColorArray(true); // alter the array pointers R_BindArray(GL_VERTEX_ARRAY, GL_SHORT, r_draw.line_arrays.verts); R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_draw.line_arrays.colors); glDrawArrays(GL_LINES, 0, r_draw.line_arrays.vert_index / 2); // and restore them R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_COLOR_ARRAY); R_EnableColorArray(false); R_EnableTexture(&texunit_diffuse, true); r_draw.line_arrays.vert_index = r_draw.line_arrays.color_index = 0; }
void R_DrawChars (void) { if (!r_char_arrays.vert_index) return; R_BindTexture(draw_chars->texnum); R_EnableColorArray(true); /* alter the array pointers */ R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_char_arrays.colors); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, r_char_arrays.texcoords); glVertexPointer(2, GL_SHORT, 0, r_char_arrays.verts); glDrawArrays(GL_QUADS, 0, r_char_arrays.vert_index / 2); refdef.batchCount++; r_char_arrays.color_index = 0; r_char_arrays.texcoord_index = 0; r_char_arrays.vert_index = 0; /* and restore them */ R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_COLOR_ARRAY); R_EnableColorArray(false); }
/** * @brief Draws a marker on the ground to indicate pathing CL_AddPathingBox * @sa CL_AddPathing * @sa RF_BOX */ static void R_DrawFloor (const entity_t * e) { image_t *cellIndicator = R_FindImage("pics/sfx/cell", it_pic); const float dx = PLAYER_WIDTH * 2; const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha}; const float size = 4.0; /** @todo use default_texcoords */ const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } }; const vec3_t points[] = { { e->origin[0] - size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx + size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx + size, e->origin[1] - size, e->origin[2] }, { e->origin[0] - size, e->origin[1] - size, e->origin[2] } }; glDisable(GL_DEPTH_TEST); R_Color(color); R_BindTexture(cellIndicator->texnum); /* circle points */ R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; glEnable(GL_DEPTH_TEST); R_Color(NULL); }
/* * @brief */ static void R_DrawChars(void) { uint16_t i; for (i = 0; i < r_draw.num_fonts; i++) { r_char_arrays_t *chars = &r_draw.char_arrays[i]; if (!chars->vert_index) continue; R_BindTexture(r_draw.fonts[i].image->texnum); R_EnableColorArray(true); // alter the array pointers R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, chars->colors); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, chars->texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_SHORT, chars->verts); glDrawArrays(GL_QUADS, 0, chars->vert_index / 2); chars->color_index = 0; chars->texcoord_index = 0; chars->vert_index = 0; } // restore array pointers R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_COLOR_ARRAY); R_EnableColorArray(false); // restore draw color R_Color(NULL); }
/** * @sa R_DrawParticles */ static void R_DrawSprite (const ptl_t * p) { const ptl_t *q; vec3_t up, right; vec3_t nup, nright; vec3_t pos; float texcoords[8]; /* load texture set up coordinates */ assert(p->pic); R_BindTexture(p->pic->art.image->texnum); /* calculate main position and normalised up and right vectors */ q = p->parent ? p->parent : p; R_GetSpriteVectors(q, right, up); /* Calculate normalised */ VectorCopy(up, nup); VectorCopy(right, nright); VectorNormalizeFast(nup); VectorNormalizeFast(nright); /* offset */ VectorCopy(q->s, pos); VectorMA(pos, q->offset[0], nup, pos); VectorMA(pos, q->offset[1], nright, pos); if (p->parent) { /* if this is a child then calculate our own up and right vectors and offsets */ R_GetSpriteVectors(p, right, up); /* but offset by our parent's nup and nright */ VectorMA(pos, p->offset[0], nup, pos); VectorMA(pos, p->offset[1], nright, pos); } /* center image */ VectorMA(pos, -0.5, up, pos); VectorMA(pos, -0.5, right, pos); R_SpriteTexcoords(p, texcoords); R_Color(p->color); { /* draw it */ const vec3_t points[] = { { pos[0], pos[1], pos[2] }, { pos[0] + up[0], pos[1] + up[1], pos[2] + up[2] }, { pos[0] + up[0] + right[0], pos[1] + up[1] + right[1], pos[2] + up[2] + right[2] }, { pos[0] + right[0], pos[1] + right[1], pos[2] + right[2] } }; R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); refdef.batchCount++; } }
/** * @brief Static model render function * @sa R_DrawAliasFrameLerp */ static void R_DrawAliasStatic (const mAliasMesh_t *mesh, const vec4_t shellColor) { R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, mesh->verts); R_BindArray(GL_NORMAL_ARRAY, GL_FLOAT, mesh->normals); if (r_state.active_normalmap || r_state.dynamic_lighting_enabled) R_BindArray(GL_TANGENT_ARRAY, GL_FLOAT, mesh->tangents); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, mesh->texcoords); glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3); refdef.batchCount++; R_DrawMeshModelShell(mesh, shellColor); }
void R_DrawFills (void) { if (!r_fill_arrays.vert_index) return; R_EnableTexture(&texunit_diffuse, false); R_EnableColorArray(true); /* alter the array pointers */ R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_fill_arrays.colors); glVertexPointer(2, GL_SHORT, 0, r_fill_arrays.verts); glDrawArrays(GL_QUADS, 0, r_fill_arrays.vert_index / 2); refdef.batchCount++; /* and restore them */ R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_COLOR_ARRAY); R_EnableColorArray(false); R_EnableTexture(&texunit_diffuse, true); r_fill_arrays.vert_index = r_fill_arrays.color_index = 0; R_Color(NULL); }
/** * @brief Draws an arrow between two points * @sa CL_AddArrow * @sa RF_BOX */ static void R_DrawArrow (const entity_t* e) { const vec3_t upper = { e->origin[0] + 2, e->origin[1], e->origin[2] }; const vec3_t mid = { e->origin[0], e->origin[1] + 2, e->origin[2] }; const vec3_t lower = { e->origin[0], e->origin[1], e->origin[2] + 2 }; const vec4_t color = { e->color[0], e->color[1], e->color[2], e->alpha }; const vec3_t points[] = { { e->oldorigin[0], e->oldorigin[1], e->oldorigin[2] }, { upper[0], upper[1], upper[2] }, { mid[0], mid[1], mid[2] }, { lower[0], lower[1], lower[2] } }; R_Color(color); glDisable(GL_TEXTURE_2D); glEnable(GL_LINE_SMOOTH); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; glDisable(GL_LINE_SMOOTH); glEnable(GL_TEXTURE_2D); R_Color(nullptr); }
void R_DrawBoundingBoxes (void) { int i; const int step = 3 * 8; const int bboxes = r_bbox_array.bboxes_index / step; const glIndex indexes[] = { 2, 1, 0, 1, 4, 5, 1, 7, 3, 2, 7, 6, 2, 4, 0 }; const glIndex indexes2[] = { 4, 6, 7 }; if (!r_bbox_array.bboxes_index) return; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); R_Color(NULL); for (i = 0; i < bboxes; i++) { const float *bbox = &r_bbox_array.bboxes[i * step]; R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, bbox); /* Draw top and sides */ glDrawElements(GL_TRIANGLE_FAN, 15, GLINDEX, indexes); /* Draw bottom */ glDrawElements(GL_TRIANGLE_FAN, 3, GLINDEX, indexes2); } R_BindDefaultArray(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); r_bbox_array.bboxes_index = 0; }
/** * @brief "Clean up" the depth buffer into a rect * @note we use a big value (but not too big) to set the depth buffer, then it is not really a clean up * @todo can we fix bigZ with a value come from glGet? */ void R_CleanupDepthBuffer (int x, int y, int width, int height) { const int nx = x * viddef.rx; const int ny = y * viddef.ry; const int nwidth = width * viddef.rx; const int nheight = height * viddef.ry; const GLboolean hasDepthTest = glIsEnabled(GL_DEPTH_TEST); const GLdouble bigZ = 2000; const vec3_t points [] = { { nx, ny, bigZ }, { nx + nwidth, ny, bigZ }, { nx + nwidth, ny + nheight, bigZ }, { nx, ny + nheight, bigZ } }; GLint depthFunc; glGetIntegerv(GL_DEPTH_FUNC, &depthFunc); /* we want to overwrite depth buffer not to have his constraints */ glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (!hasDepthTest) glDisable(GL_DEPTH_TEST); glDepthFunc(depthFunc); }
void R_DrawCircle (float radius, const vec4_t color, float thickness, const vec3_t shift) { vec3_t points[16]; const size_t steps = lengthof(points); unsigned int i; glEnable(GL_LINE_SMOOTH); glLineWidth(thickness); R_Color(color); for (i = 0; i < steps; i++) { const float a = 2.0f * M_PI * (float) i / (float) steps; VectorSet(points[i], shift[0] + radius * cos(a), shift[1] + radius * sin(a), shift[2]); } R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_LINE_LOOP, 0, steps); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; R_Color(NULL); glLineWidth(1.0f); glDisable(GL_LINE_SMOOTH); }
/* * @brief Draws all particles for the current frame. */ void R_DrawParticles(const r_element_t *e, const size_t count) { size_t i, j; R_EnableColorArray(true); R_ResetArrayState(); // alter the array pointers R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, r_particle_state.verts); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, r_particle_state.texcoords); R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_particle_state.colors); const GLuint base = (uintptr_t) e->data; for (i = j = 0; i < count; i++, e++) { const r_particle_t *p = (const r_particle_t *) e->element; // bind the particle's texture if (p->image->texnum != texunit_diffuse.texnum) { if (i > j) { // draw pending particles glDrawArrays(GL_QUADS, (base + j) * 4, (i - j) * 4); j = i; } R_BindTexture(p->image->texnum); R_BlendFunc(GL_SRC_ALPHA, p->blend); } } if (i > j) { // draw any remaining particles glDrawArrays(GL_QUADS, (base + j) * 4, (i - j) * 4); } // restore array pointers R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_COLOR_ARRAY); R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_EnableColorArray(false); R_Color(NULL); }
/** * @brief Draws the field marker entity is specified in CL_AddTargeting * @sa CL_AddTargeting * @sa RF_BOX */ static void R_DrawBox (const entity_t* e) { const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha}; if (e->texture) { R_Color(color); R_BindTexture(e->texture->texnum); if (VectorNotEmpty(e->eBox.mins) && VectorNotEmpty(e->eBox.maxs)) { R_DrawTexturedBox(e->eBox.mins, e->eBox.maxs); } else { R_DrawTexturedBox(e->oldorigin, e->origin); } R_Color(nullptr); return; } glDisable(GL_TEXTURE_2D); R_Color(color); if (VectorNotEmpty(e->eBox.mins) && VectorNotEmpty(e->eBox.maxs)) { R_DrawBoundingBox(e->eBox); } else { vec3_t points[] = { { e->oldorigin[0], e->oldorigin[1], e->oldorigin[2] }, { e->oldorigin[0], e->origin[1], e->oldorigin[2] }, { e->origin[0], e->origin[1], e->oldorigin[2] }, { e->origin[0], e->oldorigin[1], e->oldorigin[2] } }; glLineWidth(2.0f); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); /** @todo fill one array */ glDrawArrays(GL_LINE_LOOP, 0, 4); refdef.batchCount++; points[0][2] = e->origin[2]; points[1][2] = e->origin[2]; points[2][2] = e->origin[2]; points[3][2] = e->origin[2]; glDrawArrays(GL_LINE_LOOP, 0, 4); refdef.batchCount++; points[0][2] = e->oldorigin[2]; points[1][1] = e->oldorigin[1]; points[2][2] = e->oldorigin[2]; points[3][1] = e->origin[1]; glDrawArrays(GL_LINES, 0, 4); refdef.batchCount++; points[0][0] = e->origin[0]; points[1][0] = e->origin[0]; points[2][0] = e->oldorigin[0]; points[3][0] = e->oldorigin[0]; glDrawArrays(GL_LINES, 0, 4); refdef.batchCount++; R_BindDefaultArray(GL_VERTEX_ARRAY); } glEnable(GL_TEXTURE_2D); R_Color(nullptr); }
void R_DrawGrass () { if (clumpTriangleCount <= 0) return; R_BindTexture(R_FindImage("models/objects/vegi/plants2/plant_skin3", it_pic)->texnum); R_EnableAlphaTest(true); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, gfv_texcoord); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, gfv_pos); glDrawArrays(GL_TRIANGLES, 0, clumpTrianglesForLevel[refdef.worldlevel] * 3); R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_EnableAlphaTest(false); refdef.batchCount++; }
/** * @brief Draws the textured box, the caller should bind the texture * @sa R_DrawBox */ void R_DrawTexturedBox (const vec3_t a0, const vec3_t a1) { const GLfloat texcoords[] = { 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, }; const vec3_t bbox[] = { { a0[0], a0[1], a0[2] }, { a0[0], a0[1], a1[2] }, { a1[0], a0[1], a1[2] }, { a1[0], a0[1], a0[2] }, { a1[0], a1[1], a0[2] }, { a1[0], a1[1], a1[2] }, { a0[0], a1[1], a1[2] }, { a0[0], a1[1], a0[2] }, { a0[0], a0[1], a0[2] }, { a0[0], a0[1], a1[2] }, { a1[0], a0[1], a1[2] }, { a1[0], a0[1], a0[2] }, { a1[0], a1[1], a0[2] }, { a1[0], a1[1], a1[2] }, { a0[0], a1[1], a1[2] }, { a0[0], a1[1], a0[2] } }; const glIndex indexes[] = { 0, 1, 2, 1, 2, 3, 4, 5, 6, 6, 7, 4, 2 + 8, 3 + 8, 4 + 8, 2 + 8, 5 + 8, 4 + 8, 6 + 8, 7 + 8, 0 + 8, 0 + 8, 1 + 8, 6 + 8, }; R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, bbox); /* Draw sides only */ glDrawElements(GL_TRIANGLES, 8 * 3, GLINDEX, indexes); R_BindDefaultArray(GL_VERTEX_ARRAY); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); }
/* * R_BindDefaultArray * * Binds the appropriate shared vertex array to the specified target. */ void R_BindDefaultArray(GLenum target) { switch (target) { case GL_VERTEX_ARRAY: if (r_state.ortho) R_BindArray(target, GL_SHORT, r_state.vertex_array_2d); else R_BindArray(target, GL_FLOAT, r_state.vertex_array_3d); break; case GL_TEXTURE_COORD_ARRAY: R_BindArray(target, GL_FLOAT, r_state.active_texunit->texcoord_array); break; case GL_COLOR_ARRAY: R_BindArray(target, GL_FLOAT, r_state.color_array); break; case GL_NORMAL_ARRAY: R_BindArray(target, GL_FLOAT, r_state.normal_array); break; case GL_TANGENT_ARRAY: R_BindArray(target, GL_FLOAT, r_state.tangent_array); break; default: break; } }
/* * R_BindBuffer */ void R_BindBuffer(GLenum target, GLenum type, GLuint id) { if (!qglBindBuffer) return; if (!r_vertex_buffers->value) return; qglBindBuffer(GL_ARRAY_BUFFER, id); if (type && id) // assign the array pointer as well R_BindArray(target, type, NULL); }
/** * @brief Draws a marker on the ground to indicate pathing CL_AddPathingBox * @sa CL_AddPathing * @sa RF_BOX */ static void R_DrawFloor (const entity_t* e) { GLint oldDepthFunc; glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc); image_t* cellIndicator = R_FindImage("pics/sfx/cell", it_pic); const float dx = PLAYER_WIDTH * 2; const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha}; const float size = 4.0; /** @todo use default_texcoords */ const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } }; const vec3_t points[] = { { e->origin[0] - size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx + size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx + size, e->origin[1] - size, e->origin[2] }, { e->origin[0] - size, e->origin[1] - size, e->origin[2] } }; /* Draw it twice, with and without depth check, so it will still be visible if obscured by a wall */ R_Color(color); R_BindTexture(cellIndicator->texnum); /* circle points */ R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDepthFunc(GL_GREATER); glColor4f(color[0], color[1], color[2], color[3] * 0.25f); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDepthFunc(oldDepthFunc); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount += 2; R_Color(nullptr); }
static void R_DrawAliasTags (const mAliasModel_t *mod) { int i; const uint32_t color[] = {0xFF0000FF, 0xFF00FF00, 0xFFFF0000}; glEnable(GL_LINE_SMOOTH); R_EnableTexture(&texunit_diffuse, false); R_EnableColorArray(true); for (i = 0; i < mod->num_tags; i++) { int j; const mAliasTag_t *tag = &mod->tags[i]; for (j = 0; j < 3; j++) { vec3_t out; const mAliasTagOrientation_t *o = &tag->orient[mod->curFrame]; VectorMA(o->origin, 5, o->axis[j], out); const vec3_t points[] = { { o->origin[0], o->origin[1], o->origin[2] }, { out[0], out[1], out[2] } }; GLbyte colorArray[8]; memcpy(&colorArray[0], &color[j], 4); memcpy(&colorArray[4], &color[j], 4); R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, colorArray); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_LINE_STRIP, 0, 2); refdef.batchCount++; } } /* restore default array bindings */ R_BindDefaultArray(GL_COLOR_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); R_EnableColorArray(false); R_EnableTexture(&texunit_diffuse, true); glDisable(GL_LINE_SMOOTH); }
/* * @brief */ static void R_SetVertexArrayState(const r_model_t *mod, uint32_t mask) { // vertex array if (mask & R_ARRAY_VERTEX) R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, mod->verts); // normals and tangents if (r_state.lighting_enabled) { if (mask & R_ARRAY_NORMAL) R_BindArray(GL_NORMAL_ARRAY, GL_FLOAT, mod->normals); if (r_bumpmap->value) { if (mask & R_ARRAY_TANGENT && mod->tangents) R_BindArray(GL_TANGENT_ARRAY, GL_FLOAT, mod->tangents); } } // diffuse texcoords if (texunit_diffuse.enabled) { if (mask & R_ARRAY_TEX_DIFFUSE) R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, mod->texcoords); } // lightmap coords if (texunit_lightmap.enabled) { if (mask & R_ARRAY_TEX_LIGHTMAP) { R_SelectTexture(&texunit_lightmap); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, mod->lightmap_texcoords); R_SelectTexture(&texunit_diffuse); } } }
/** * @brief Draw the current texture on a quad the size of the renderbuffer */ static inline void R_DrawQuad (void) { /** @todo use default_texcoords */ const vec2_t texcoord[] = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 0.0f, 0.0f } }; const vec2_t verts[] = { { 0.0f, 0.0f }, Vector2FromInt(fbo_render->width, 0.0f), Vector2FromInt(fbo_render->width, fbo_render->height), Vector2FromInt(0.0f, fbo_render->height) }; glVertexPointer(2, GL_FLOAT, 0, verts); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoord); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); }
/** * @brief Draws the model bounding box * @sa R_EntityComputeBoundingBox */ void R_DrawBoundingBox (const vec3_t absmins, const vec3_t absmaxs) { vec3_t bbox[8]; const glIndex indexes[] = { 2, 1, 0, 1, 4, 5, 1, 7, 3, 2, 7, 6, 2, 4, 0 }; const glIndex indexes2[] = { 4, 6, 7 }; R_ComputeBoundingBox(absmins, absmaxs, bbox); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, bbox); /* Draw top and sides */ glDrawElements(GL_TRIANGLE_STRIP, 15, GLINDEX, indexes); /* Draw bottom */ glDrawElements(GL_TRIANGLE_STRIP, 3, GLINDEX, indexes2); R_BindDefaultArray(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); }
const image_t *R_DrawImageArray (const vec2_t texcoords[4], const vec2_t verts[4], const image_t *image) { /* alter the array pointers */ glVertexPointer(2, GL_FLOAT, 0, verts); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); if (image != NULL) R_BindTexture(image->texnum); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; /* and restore them */ R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); return image; }
/** * @brief Draw replacement model (e.g. when model wasn't found) * @sa R_DrawNullEntities */ static void R_DrawNullModel (const entity_t* e) { int i; vec3_t points[6]; R_EnableTexture(&texunit_diffuse, false); glPushMatrix(); glMultMatrixf(e->transform.matrix); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); VectorSet(points[0], 0, 0, -16); for (i = 0; i <= 4; i++) { points[i + 1][0] = 16 * cos(i * (M_PI / 2)); points[i + 1][1] = 16 * sin(i * (M_PI / 2)); points[i + 1][2] = 0; } glDrawArrays(GL_TRIANGLE_FAN, 0, 6); refdef.batchCount++; VectorSet(points[0], 0, 0, 16); for (i = 4; i >= 0; i--) { points[i + 1][0] = 16 * cos(i * (M_PI / 2)); points[i + 1][1] = 16 * sin(i * (M_PI / 2)); points[i + 1][2] = 0; } glDrawArrays(GL_TRIANGLE_FAN, 0, 6); refdef.batchCount++; R_BindDefaultArray(GL_VERTEX_ARRAY); glPopMatrix(); R_EnableTexture(&texunit_diffuse, true); }
/** * @sa R_DrawParticles */ static void R_DrawPtlLine (const ptl_t * p) { const vec3_t points[] = { { p->s[0], p->s[1], p->s[2] }, { p->v[0], p->v[1], p->v[2] } }; R_EnableTexture(&texunit_diffuse, qfalse); glEnable(GL_LINE_SMOOTH); R_Color(p->color); /* draw line from s to v */ R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_LINE_STRIP, 0, 2); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; R_Color(NULL); glDisable(GL_LINE_SMOOTH); R_EnableTexture(&texunit_diffuse, qtrue); }
/** * @brief Draws weather effects */ void Weather::render (void) { /* Don't play the weather particles if the user doesn't want them */ if (!Cvar_GetInteger("cl_particleweather")) { return; } GLfloat prtPos[3 * 4 * Weather::MAX_PARTICLES]; GLfloat prtTexcoord[2 * 4 * Weather::MAX_PARTICLES]; GLushort prtIndex[3 * 2 * Weather::MAX_PARTICLES]; size_t prtCount = 0; //const float splashTimeScale = 0.001f / splashTime; /* from msec to 1/sec units, so division is done only once per frame */ /** @todo shadowcasting at least for the sunlight */ #if 0 // disabled because of bizarre colors vec4_t prtColor = {color[0] * (refdef.ambientColor[0] + refdef.sunDiffuseColor[0]), color[1] * (refdef.ambientColor[1] + refdef.sunDiffuseColor[1]), color[2] * (refdef.ambientColor[2] + refdef.sunDiffuseColor[2]), color[3]}; #else vec_t prtBrightness = VectorLength(refdef.ambientColor) + VectorLength(refdef.sunDiffuseColor); /** @todo proper color to brightness mapping */ vec4_t prtColor = {color[0] * prtBrightness, color[1] * prtBrightness, color[2] * prtBrightness, color[3]}; /* alpha is not to be scaled */ #endif for (size_t i = 0; i < Weather::MAX_PARTICLES; i++) { Weather::particle &prt = particles[i]; if (prt.ttl < 0) continue; /* if particle is alive, construct a camera-facing quad */ GLfloat x, y, z; GLfloat dx, dy, dz; GLfloat thisParticleSize = particleSize; if (prt.vz == 0 && splashTime > 0) { /* splash particle, do zoom and other things */ /** @todo alpha decay */ const float splashFactor = prt.ttl / 500.0f;//1.0f - prt.ttl * splashTimeScale; thisParticleSize *= (splashSize - 1.0f) * splashFactor + 1.0f; dx = dy = thisParticleSize; } else { dx = i & 1 ? thisParticleSize* 2 : thisParticleSize; dy = i & 1 ? thisParticleSize : thisParticleSize * 2 ; /** @todo make a proper projection instead of this hack */ } x = prt.x; y = prt.y; z = prt.z; dz = smearLength * prt.vz * 0.5; /** @todo should use proper velocity vector ... or maybe not */ /* construct a particle geometry; */ GLfloat *pos = &prtPos[3 * 4 * prtCount]; GLfloat *texcoord = &prtTexcoord[2 * 4 * prtCount]; GLushort *idx = &prtIndex[3 * 2 * prtCount]; /** @todo actually rotate billboard in the correct position */ pos[0] = x - dx; pos[1] = y - dy; pos[2] = z + dz * 2; pos[3] = x + dx; pos[4] = y - dy; pos[5] = z + dz *2; pos[6] = x + dx; pos[7] = y + dy; pos[8] = z; pos[9] = x - dx; pos[10] = y + dy; pos[11] = z; texcoord[0] = 0; texcoord[1] = 0; /* upper left vertex */ texcoord[2] = 1.0f; texcoord[3] = 0; /* upper right vertex */ texcoord[4] = 1.0f; texcoord[5] = 1.0f; /* bottom right vertex */ texcoord[6] = 0; texcoord[7] = 1.0f; /* bottom left vertex */ idx[0] = 4 * prtCount; idx[1] = 4 * prtCount + 1; idx[2] = 4 * prtCount + 2; idx[3] = 4 * prtCount + 2; idx[4] = 4 * prtCount + 3; idx[5] = 4 * prtCount; prtCount++; } if (prtCount < 1) return; /* draw the generated array */ R_Color(prtColor); glBindTexture(GL_TEXTURE_2D, wpTexture()); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, prtPos); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, prtTexcoord); R_EnableBlend(true); glDrawElements(GL_TRIANGLES, prtCount * 3 * 2, GL_UNSIGNED_SHORT, prtIndex); R_EnableBlend(false); R_ResetArrayState(); R_Color(nullptr); refdef.batchCount++; }
/** * @brief Draws shadow and highlight effects for the entities (actors) * @note The origins are already transformed */ void R_DrawEntityEffects (void) { const int mask = r_stencilshadows->integer ? RF_BLOOD : (RF_SHADOW | RF_BLOOD); GLint oldDepthFunc; glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc); R_EnableBlend(true); if (actorIndicator == nullptr) { selectedActorIndicator = R_FindImage("pics/sfx/actor_selected", it_effect); actorIndicator = R_FindImage("pics/sfx/actor", it_effect); } for (int i = 0; i < refdef.numEntities; i++) { const entity_t* e = &r_entities[i]; if (e->flags <= RF_BOX) continue; glPushMatrix(); glMultMatrixf(e->transform.matrix); if (e->flags & mask) { const vec3_t points[] = { { -18.0, 14.0, -28.5 }, { 10.0, 14.0, -28.5 }, { 10.0, -14.0, -28.5 }, { -18.0, -14.0, -28.5 } }; /** @todo use default_texcoords */ const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } }; if (e->flags & RF_SHADOW) { R_BindTexture(shadow->texnum); } else { assert(e->texture); R_BindTexture(e->texture->texnum); } R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; } if (e->flags & RF_ACTOR) { const float size = 15.0; int texnum; /* draw the circles for team-members and allied troops */ vec4_t color = {1, 1, 1, 1}; const vec3_t points[] = { { -size, size, -SELECTION_DELTA }, { size, size, -SELECTION_DELTA }, { size, -size, -SELECTION_DELTA }, { -size, -size, -SELECTION_DELTA } }; /** @todo use default_texcoords */ const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } }; if (e->flags & RF_SELECTED) Vector4Set(color, 0, 1, 0, 0.5); else if (e->flags & RF_MEMBER) Vector4Set(color, 0, 0.8, 0, 0.5); else if (e->flags & RF_ALLIED) Vector4Set(color, 0, 1, 0.5, 0.5); else if (e->flags & RF_NEUTRAL) Vector4Set(color, 1, 1, 0, 0.5); else if (e->flags & RF_OPPONENT) Vector4Set(color, 1, 0, 0, 0.5); else Vector4Set(color, 0.3, 0.3, 0.3, 0.5); if (e->flags & RF_SELECTED) texnum = selectedActorIndicator->texnum; else texnum = actorIndicator->texnum; R_BindTexture(texnum); R_Color(color); R_EnableDrawAsGlow(true); /* circle points */ R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; /* add transparency when something is in front of the circle */ color[3] *= 0.25; R_Color(color); glDepthFunc(GL_GREATER); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDepthFunc(oldDepthFunc); refdef.batchCount++; R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); R_Color(nullptr); R_EnableDrawAsGlow(false); } glPopMatrix(); } }
/** * @brief Draw the day and night images of a flat geoscape * multitexture feature is used to blend the images * @sa R_Draw3DGlobe * @param[in] p The horizontal shift of the night map * @param[in] cx The x texture coordinate * @param[in] cy The y texture coordinate * @param[in] iz The zoomlevel of the geoscape - see ccs.zoom * @param[in] map The geoscape map to draw (can be changed in the campaign definition) * @param[in] overlayNation,overlayXVI,overlayRadar Whether these overlays should be drawn or not */ void R_DrawFlatGeoscape (const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char *map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_dayandnightTexture, image_t *r_xviTexture, image_t *r_radarTexture) { image_t *gl; float geoscape_texcoords[4 * 2]; short geoscape_verts[4 * 2]; /* normalize */ const float nx = nodePos[0] * viddef.rx; const float ny = nodePos[1] * viddef.ry; const float nw = nodeSize[0] * viddef.rx; const float nh = nodeSize[1] * viddef.ry; /* load day image */ gl = R_FindImage(va("pics/geoscape/%s_day", map), it_wrappic); if (gl == r_noTexture) Com_Error(ERR_FATAL, "Could not load geoscape day image"); /* alter the array pointers */ glVertexPointer(2, GL_SHORT, 0, geoscape_verts); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords); geoscape_texcoords[0] = cx - iz; geoscape_texcoords[1] = cy - iz; geoscape_texcoords[2] = cx + iz; geoscape_texcoords[3] = cy - iz; geoscape_texcoords[4] = cx + iz; geoscape_texcoords[5] = cy + iz; geoscape_texcoords[6] = cx - iz; geoscape_texcoords[7] = cy + iz; geoscape_verts[0] = nx; geoscape_verts[1] = ny; geoscape_verts[2] = nx + nw; geoscape_verts[3] = ny; geoscape_verts[4] = nx + nw; geoscape_verts[5] = ny + nh; geoscape_verts[6] = nx; geoscape_verts[7] = ny + nh; /* draw day image */ R_BindTexture(gl->texnum); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; /* draw night map */ gl = R_FindImage(va("pics/geoscape/%s_night", map), it_wrappic); /* maybe the campaign map doesn't have a night image */ if (gl != r_noTexture) { float geoscape_nighttexcoords[4 * 2]; R_BindTexture(gl->texnum); R_EnableTexture(&texunit_lightmap, true); R_SelectTexture(&texunit_lightmap); geoscape_nighttexcoords[0] = geoscape_texcoords[0] + p; geoscape_nighttexcoords[1] = geoscape_texcoords[1]; geoscape_nighttexcoords[2] = geoscape_texcoords[2] + p; geoscape_nighttexcoords[3] = geoscape_texcoords[3]; geoscape_nighttexcoords[4] = geoscape_texcoords[4] + p; geoscape_nighttexcoords[5] = geoscape_texcoords[5]; geoscape_nighttexcoords[6] = geoscape_texcoords[6] + p; geoscape_nighttexcoords[7] = geoscape_texcoords[7]; R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_nighttexcoords); R_BindTexture(r_dayandnightTexture->texnum); R_SelectTexture(&texunit_diffuse); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; R_SelectTexture(&texunit_lightmap); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords); R_EnableTexture(&texunit_lightmap, false); } /* draw nation overlay */ if (overlayNation) { gl = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic); if (gl == r_noTexture) Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image"); /* draw day image */ R_BindTexture(gl->texnum); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; } /* draw XVI image */ if (overlayXVI) { gl = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic); if (gl == r_noTexture) Com_Error(ERR_FATAL, "Could not load xvi overlay image"); R_BindTexture(gl->texnum); R_EnableTexture(&texunit_lightmap, true); R_BindLightmapTexture(r_xviTexture->texnum); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; R_EnableTexture(&texunit_lightmap, false); } /* draw radar image */ if (overlayRadar) { R_BindTexture(r_radarTexture->texnum); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); refdef.batchCount++; } /* and restore them */ R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY); R_BindDefaultArray(GL_VERTEX_ARRAY); }