/** * @brief Generic tooltip function */ int UI_DrawTooltip (const char* string, int x, int y, int maxWidth) { const char* font = "f_small"; int height = 0, width = 0; if (Q_strnull(string) || !font) return 0; R_FontTextSize(font, string, maxWidth, LONGLINES_WRAP, &width, &height, nullptr, nullptr); if (!width) return 0; x += 5; y += 5; if (x + width + 3 > VID_NORM_WIDTH) x -= width + 10; if (y + height + 3 > VID_NORM_HEIGHT) y -= height + 10; UI_DrawFill(x - 1, y - 1, width + 4, height + 4, tooltipBG); R_Color(tooltipColor); UI_DrawString(font, ALIGN_UL, x + 1, y + 1, x + 1, maxWidth, 0, string); R_Color(nullptr); return width; }
/** * @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); }
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 a rect to the screen. Also has support for stippled rendering of the rect. * * @param[in] x X-position of the rect * @param[in] y Y-position of the rect * @param[in] w Width of the rect * @param[in] h Height of the rect * @param[in] color RGBA color of the rect * @param[in] lineWidth Line strength in pixel of the rect * @param[in] pattern Specifies a 16-bit integer whose bit pattern determines * which fragments of a line will be drawn when the line is rasterized. * Bit zero is used first; the default pattern is all 1's * @note The stipple factor is @c 2 for this function */ void R_DrawRect (int x, int y, int w, int h, const vec4_t color, float lineWidth, int pattern) { const float nx = x * viddef.rx; const float ny = y * viddef.ry; const float nw = w * viddef.rx; const float nh = h * viddef.ry; const vec2_t points[] = { { nx, ny }, { nx + nw, ny }, { nx + nw, ny + nh }, { nx, ny + nh } }; R_Color(color); glDisable(GL_TEXTURE_2D); glLineWidth(lineWidth); #ifndef HAVE_GLES glLineStipple(2, pattern); glEnable(GL_LINE_STIPPLE); #endif glVertexPointer(2, GL_FLOAT, 0, points); glDrawArrays(GL_LINE_LOOP, 0, 4); R_BindDefaultArray(GL_VERTEX_ARRAY); refdef.batchCount++; glEnable(GL_TEXTURE_2D); glLineWidth(1.0f); #ifndef HAVE_GLES glDisable(GL_LINE_STIPPLE); #endif 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 uiTextEntryNode::draw (uiNode_t* node) { const float* textColor; vec2_t pos; const char* font = UI_GetFontFromNode(node); uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (node->disabled) { textColor = node->disabledColor; iconStatus = SPRITE_STATUS_DISABLED; } else if (node->state) { textColor = node->color; iconStatus = SPRITE_STATUS_HOVER; } else { textColor = node->color; } if (UI_HasFocus(node)) { textColor = node->selectedColor; } UI_GetNodeAbsPos(node, pos); if (EXTRADATA(node).background) { UI_DrawSpriteInBox(false, EXTRADATA(node).background, iconStatus, pos[0], pos[1], node->box.size[0], node->box.size[1]); } if (char const* const text = UI_GetReferenceString(node, node->text)) { char buf[MAX_VAR]; if (EXTRADATA(node).isPassword) { size_t size = UTF8_strlen(text); if (size > MAX_VAR - 2) size = MAX_VAR - 2; memset(buf, HIDECHAR, size); buf[size] = '\0'; } else { /* leave one byte empty for the text-based cursor */ UTF8_strncpyz(buf, text, sizeof(buf) - 1); } /** @todo Make the cursor into a real graphical object instead of using a text character. */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_ON); } else { UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_OFF); } } if (*buf != '\0') { R_Color(textColor); UI_DrawStringInBox(font, (align_t)node->contentAlign, pos[0] + node->padding, pos[1] + node->padding, node->box.size[0] - node->padding - node->padding, node->box.size[1] - node->padding - node->padding, buf); R_Color(nullptr); } } }
/** * @brief Developer tool for viewing BSP vertex normals. Only Phong interpolated * surfaces show their normals when r_shownormals > 1. */ void R_DrawBspNormals (int tile) { int i, j, k; const mBspSurface_t* surf; const mBspModel_t* bsp; const vec4_t color = {1.0, 0.0, 0.0, 1.0}; if (!r_shownormals->integer) return; R_EnableTexture(&texunit_diffuse, false); R_ResetArrayState(); /* default arrays */ R_Color(color); k = 0; bsp = &r_mapTiles[tile]->bsp; surf = bsp->surfaces; for (i = 0; i < bsp->numsurfaces; i++, surf++) { if (surf->frame != r_locals.frame) continue; /* not visible */ if (surf->texinfo->flags & SURF_WARP) continue; /* don't care */ if (r_shownormals->integer > 1 && !(surf->texinfo->flags & SURF_PHONG)) continue; /* don't care */ /* avoid overflows, draw in batches */ if (k > r_state.array_size - 512) { glDrawArrays(GL_LINES, 0, k / 3); k = 0; refdef.batchCount++; } for (j = 0; j < surf->numedges; j++) { vec3_t end; const GLfloat* vertex = &bsp->verts[(surf->index + j) * 3]; const GLfloat* normal = &bsp->normals[(surf->index + j) * 3]; VectorMA(vertex, 12.0, normal, end); memcpy(&r_state.vertex_array_3d[k], vertex, sizeof(vec3_t)); memcpy(&r_state.vertex_array_3d[k + 3], end, sizeof(vec3_t)); k += sizeof(vec3_t) / sizeof(vec_t) * 2; R_ReallocateStateArrays(k); } } glDrawArrays(GL_LINES, 0, k / 3); refdef.batchCount++; R_EnableTexture(&texunit_diffuse, true); R_Color(nullptr); }
void uiSelectBoxNode::draw (uiNode_t* node) { uiNode_t* option; int selBoxX, selBoxY; const char* ref; const char* font; vec2_t nodepos; const char* imageName; const image_t* image; static vec4_t invisColor = {1.0, 1.0, 1.0, 0.7}; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == nullptr) return; UI_GetNodeAbsPos(node, nodepos); imageName = UI_GetReferenceString(node, node->image); if (!imageName) imageName = "ui/selectbox"; image = UI_LoadImage(imageName); font = UI_GetFontFromNode(node); selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH; selBoxY = nodepos[1] + SELECTBOX_SPACER; /* left border */ UI_DrawNormImage(false, nodepos[0], nodepos[1], SELECTBOX_SIDE_WIDTH, node->box.size[1], SELECTBOX_SIDE_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 0.0f, 0.0f, image); /* stretched middle bar */ UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1], node->box.size[0]-SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1], 12.0f, SELECTBOX_DEFAULT_HEIGHT, 7.0f, 0.0f, image); /* right border (arrow) */ UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_RIGHT_WIDTH, nodepos[1], SELECTBOX_DEFAULT_HEIGHT, node->box.size[1], 12.0f + SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 12.0f, 0.0f, image); /* draw the label for the current selected option */ for (option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) { if (!Q_streq(OPTIONEXTRADATA(option).value, ref)) continue; if (option->invis) R_Color(invisColor); const char* label = CL_Translate(OPTIONEXTRADATA(option).label); UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY, selBoxX, node->box.size[0] - 4, 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP); R_Color(nullptr); break; } /* must we draw the drop-down list */ if (UI_GetMouseCapture() == node) { UI_CaptureDrawOver(node); } }
/** * @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); }
/** * @brief Handles CustomButton draw */ static void UI_CustomButtonNodeDraw (uiNode_t *node) { const char *text; int texY; const float *textColor; const char *image; vec2_t pos; static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; const char *font = UI_GetFontFromNode(node); if (!node->onClick || node->disabled) { /** @todo need custom color when button is disabled */ textColor = disabledColor; texY = UI_CUSTOMBUTTON_TEX_HEIGHT * 2; iconStatus = SPRITE_STATUS_DISABLED; } else if (node->state) { textColor = node->selectedColor; texY = UI_CUSTOMBUTTON_TEX_HEIGHT; iconStatus = SPRITE_STATUS_HOVER; } else { textColor = node->color; texY = 0; } UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) { const int texX = rint(EXTRADATA(node).texl[0]); texY += EXTRADATA(node).texl[1]; UI_DrawNormImageByName(qfalse, pos[0], pos[1], node->size[0], node->size[1], texX + node->size[0], texY + node->size[1], texX, texY, image); } if (EXTRADATA(node).background) { UI_DrawSpriteInBox(qfalse, EXTRADATA(node).background, iconStatus, pos[0], pos[1], node->size[0], node->size[1]); } if (EXTRADATA(node).super.icon) { UI_DrawSpriteInBox(EXTRADATA(node).super.flipIcon, EXTRADATA(node).super.icon, iconStatus, pos[0], pos[1], node->size[0], node->size[1]); } text = UI_GetReferenceString(node, node->text); if (text != NULL && *text != '\0') { R_Color(textColor); UI_DrawStringInBox(font, node->contentAlign, pos[0] + node->padding, pos[1] + node->padding, node->size[0] - node->padding - node->padding, node->size[1] - node->padding - node->padding, text, LONGLINES_PRETTYCHOP); R_Color(NULL); } }
/** * @brief Re-draws the mesh using the stencil test. Meshes with stale lighting * information, or with a lighting point above our view, are not drawn. */ static void R_DrawMeshShadow (entity_t *e, const mAliasMesh_t *mesh) { vec4_t color; const bool oldBlend = r_state.blend_enabled; const bool lighting = r_state.lighting_enabled; r_program_t *program = r_state.active_program; if (!r_stencilshadows->integer) return; if (!r_shadows->value) return; if (r_wire->integer) return; if (e->flags & RF_NO_SHADOW) return; if (e->flags & RF_TRANSLUCENT) return; if (!R_UpdateShadowOrigin(e)) return; if (e->lighting->shadowOrigin[2] > refdef.viewOrigin[2]) return; Vector4Set(color, 0.0, 0.0, 0.0, r_shadows->value * MESH_SHADOW_ALPHA); R_Color(color); R_EnableTexture(&texunit_diffuse, false); R_EnableBlend(true); R_RotateForMeshShadow(e); R_EnableStencilTest(true); if (lighting) R_EnableLighting(NULL, false); glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3); refdef.batchCount++; if (lighting) R_EnableLighting(program, true); R_EnableStencilTest(false); R_RotateForMeshShadow(NULL); R_EnableBlend(oldBlend); R_EnableTexture(&texunit_diffuse, true); R_Color(NULL); }
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 Set the surface state according to surface flags and bind the texture * @sa R_DrawSurfaces */ static void R_SetSurfaceState (const mBspSurface_t *surf) { image_t *image; if (r_state.blend_enabled) { /* alpha blend */ vec4_t color = {1.0, 1.0, 1.0, 1.0}; switch (surf->texinfo->flags & (SURF_BLEND33 | SURF_BLEND66)) { case SURF_BLEND33: color[3] = 0.33; break; case SURF_BLEND66: color[3] = 0.66; break; } R_Color(color); } image = surf->texinfo->image; R_BindTexture(image->texnum); /* texture */ if (texunit_lightmap.enabled) { /* lightmap */ if (surf->flags & MSURF_LIGHTMAP) R_BindLightmapTexture(surf->lightmap_texnum); } R_SetSurfaceBumpMappingParameters(surf, image->normalmap, image->specularmap); R_EnableGlowMap(image->glowmap); R_CheckError(); }
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 */ 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); }
/** * @brief Sets the active shell color for the given entity. */ static void R_SetMeshShellColor_default(const r_entity_t *e) { vec4_t color = { 0.0, 0.0, 0.0, 1.0 }; VectorCopy(e->shell, color); R_Color(color); }
/** * @brief Draws all mesh model shells for the current frame. */ void R_DrawMeshShells_default(const r_entities_t *ents) { if (!r_shell->value) { return; } if (r_draw_wireframe->value) { return; } R_EnableShell(program_shell, true); for (size_t i = 0; i < ents->count; i++) { const r_entity_t *e = ents->entities[i]; if ((e->effects & EF_SHELL) == 0) { continue; } if (e->effects & EF_NO_DRAW) { continue; } r_view.current_entity = e; R_DrawMeshShell_default(e); } r_view.current_entity = NULL; R_EnableShell(NULL, false); R_Color(NULL); }
/** * @param[in] status The state of the sprite node * @param[in] sprite Context sprite * @param[in] posX Absolute X position of the top-left corner * @param[in] posY Absolute Y position of the top-left corner * @param[in] sizeX Width of the bounded box * @param[in] sizeY Height of the bounded box * @todo use named const for status */ void UI_DrawSpriteInBox (const uiSprite_t* sprite, uiSpriteStatus_t status, int posX, int posY, int sizeX, int sizeY) { int texX; int texY; const char* image; /** @todo Add warning */ if (status >= SPRITE_STATUS_MAX) return; /** @todo merge all this cases */ if (sprite->single || sprite->blend) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1]; image = sprite->image[SPRITE_STATUS_NORMAL]; } else if (sprite->pack64) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1] + (64 * status); image = sprite->image[SPRITE_STATUS_NORMAL]; } else { texX = sprite->pos[status][0]; texY = sprite->pos[status][1]; image = sprite->image[status]; if (!image) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1]; image = sprite->image[SPRITE_STATUS_NORMAL]; } } if (!image) return; posX += (sizeX - sprite->size[0]) / 2; posY += (sizeY - sprite->size[1]) / 2; if (sprite->blend) { const vec_t *color; color = sprite->color[status]; R_Color(color); } UI_DrawNormImageByName(posX, posY, sprite->size[0], sprite->size[1], texX + sprite->size[0], texY + sprite->size[1], texX, texY, image); if (sprite->blend) R_Color(NULL); }
void uiLineChartNode::draw (uiNode_t *node) { lineStrip_t *lineStrip; const int dataId = EXTRADATA(node).dataId; vec3_t pos; if (dataId == 0) return; if (ui_global.sharedData[dataId].type != UI_SHARED_LINESTRIP) { Com_Printf("UI_LineStripNodeDraw: Node '%s' have use an invalide dataId type. LineStrip expected. dataId invalidated\n", UI_GetPath(node)); EXTRADATA(node).dataId = 0; return; } UI_GetNodeAbsPos(node, pos); pos[2] = 0; UI_Transform(pos, nullptr, nullptr); /* Draw axes */ if (EXTRADATA(node).displayAxes) { int axes[6]; axes[0] = 0; axes[1] = 0; axes[2] = 0; axes[3] = (int) node->box.size[1]; axes[4] = (int) node->box.size[0]; axes[5] = (int) node->box.size[1]; R_Color(EXTRADATA(node).axesColor); R_DrawLineStrip(3, axes); } /* Draw all linestrips. */ lineStrip = ui_global.sharedData[dataId].data.lineStrip; for (; lineStrip; lineStrip = lineStrip->next) { /* Draw this line if it's valid. */ if (lineStrip->pointList && lineStrip->numPoints > 0) { R_Color(lineStrip->color); R_DrawLineStrip(lineStrip->numPoints, lineStrip->pointList); } } R_Color(nullptr); UI_Transform(nullptr, nullptr, nullptr); }
/** * @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 */ void R_DrawCoronas(void) { if (!r_coronas->value) return; if (!r_view.num_coronas) return; R_EnableTexture(&texunit_diffuse, false); R_EnableColorArray(true); R_ResetArrayState(); R_BlendFunc(GL_SRC_ALPHA, GL_ONE); for (uint16_t i = 0; i < r_view.num_coronas; i++) { const r_corona_t *c = &r_view.coronas[i]; const vec_t f = c->radius * c->flicker * sin(0.09 * r_view.time); // use at least 12 verts, more for larger coronas const uint16_t num_verts = Clamp(c->radius / 8.0, 12, 64); memcpy(&r_state.color_array[0], c->color, sizeof(vec3_t)); r_state.color_array[3] = r_coronas->value; // set origin color // and the corner colors memset(&r_state.color_array[4], 0, num_verts * 2 * sizeof(vec4_t)); memcpy(&r_state.vertex_array_3d[0], c->origin, sizeof(vec3_t)); uint32_t vert_index = 3; // and the origin for (uint16_t j = 0; j <= num_verts; j++) { // now draw the corners const vec_t a = j / (vec_t) num_verts * M_PI * 2; vec3_t v; VectorCopy(c->origin, v); VectorMA(v, cos(a) * (c->radius + f), r_view.right, v); VectorMA(v, sin(a) * (c->radius + f), r_view.up, v); memcpy(&r_state.vertex_array_3d[vert_index], v, sizeof(vec3_t)); vert_index += 3; } glDrawArrays(GL_TRIANGLE_FAN, 0, vert_index / 3); } R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_EnableColorArray(false); R_EnableTexture(&texunit_diffuse, true); R_Color(NULL); }
/** * @brief Renders a particle model for the battlescape * @param[in,out] mi The model information that is used to render the particle model. * @sa R_DrawPtlModel */ void R_DrawModelParticle (modelInfo_t * mi) { image_t *skin; mAliasMesh_t *mesh; /* check if the model exists */ if (!mi->model) return; skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin); if (skin == NULL) { Com_Printf("Model '%s' is broken\n", mi->name); return; } R_Color(mi->color); glPushMatrix(); glTranslatef(mi->origin[0], mi->origin[1], mi->origin[2]); glRotatef(mi->angles[YAW], 0, 0, 1); glRotatef(mi->angles[PITCH], 0, 1, 0); glRotatef(-mi->angles[ROLL], 1, 0, 0); /* draw it */ R_BindTexture(skin->texnum); /* draw the model */ mesh = &mi->model->alias.meshes[0]; refdef.aliasCount += mesh->num_tris; if (mi->model->alias.num_frames == 1) R_DrawAliasStaticWithReset(mesh, vec4_origin); else R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin); /* show model bounding box */ if (r_showbox->integer) R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs); glPopMatrix(); R_Color(NULL); }
/** * @brief Draws an animated, colored shell for the specified entity. Rather than * re-lerping or re-scaling the entity, the currently bound vertex arrays * are simply re-drawn using a small depth offset and varying texcoord delta. */ static void R_DrawMeshModelShell (const mAliasMesh_t *mesh, const vec4_t color) { /* check whether rgb is set */ if (!VectorNotEmpty(color)) return; R_Color(color); R_BindTexture(r_envmaptextures[1]->texnum); R_EnableShell(true); glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3); refdef.batchCount++; R_EnableShell(false); R_Color(NULL); }
/** * @brief Manages all state for the specified surface and stage. * @sa R_DrawMaterialSurfaces */ static void R_SetSurfaceStageState (const mBspSurface_t *surf, const materialStage_t *stage) { /* bind the texture */ R_BindTexture(stage->image->texnum); /* and optionally the lightmap */ R_StageLighting(surf, stage); R_StageGlow(stage); /* load the texture matrix for rotations, stretches, etc.. */ R_StageTextureMatrix(surf, stage); /* set the blend function, ensuring a good default */ if (stage->flags & STAGE_BLEND) R_BlendFunc(stage->blend.src, stage->blend.dest); else R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* for terrain, enable the color array */ if (stage->flags & (STAGE_TAPE | STAGE_TERRAIN | STAGE_DIRTMAP)) R_EnableColorArray(true); else R_EnableColorArray(false); /* when not using the color array, resolve the shade color */ if (!r_state.color_array_enabled) { vec4_t color; if (stage->flags & STAGE_COLOR) /* explicit */ VectorCopy(stage->color, color); else if (stage->flags & STAGE_ENVMAP) /* implied */ VectorCopy(surf->lightColor, color); /** @todo WTF? surely it was supposed to use the specular color */ else /* default */ VectorSet(color, 1.0, 1.0, 1.0); /* modulate the alpha value for pulses */ if (stage->flags & STAGE_PULSE) { /* disable fog, since it also sets alpha */ R_EnableFog(false); color[3] = stage->pulse.dhz; } else { /* ensure fog is available */ R_EnableFog(true); color[3] = 1.0; } R_Color(color); } }
/** * @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); }
/** * @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 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 */ static void Cl_DrawConsole_Background(void) { const r_image_t *image = R_LoadImage("ui/conback", IT_UI); if (image->type != IT_NULL) { const vec_t x_scale = r_context.width / (vec_t) image->width; const vec_t y_scale = r_context.height / (vec_t) image->height; const vec_t scale = Max(x_scale, y_scale); if (cls.state == CL_ACTIVE) { R_Color((const vec4_t) { 1.0, 1.0, 1.0, cl_console_background_alpha->value }); R_DrawImage(0, -r_context.window_height * 0.3333333, scale, image); R_Color(NULL); } else {
/** * @note No need to reset the blend mode - R_Setup2D will do this * @sa R_Setup2D */ void R_DrawParticles (void) { ptl_t *p; int i; if (!r_particles->integer) return; for (i = 0, p = r_particleArray; i < r_numParticles; i++, p++) if (p->inuse && !p->invis) { /* test for visibility */ if (p->levelFlags && !((1 << refdef.worldlevel) & p->levelFlags)) continue; if (p->program != NULL) R_UseProgram(p->program); /* set blend mode and draw gfx */ R_SetBlendMode(p->blend); switch (p->style) { case STYLE_LINE: R_DrawPtlLine(p); break; case STYLE_CIRCLE: R_DrawPtlCircle(p); break; default: break; } if (p->pic) R_DrawSprite(p); if (p->model) R_DrawParticleModel(p); R_TexEnv(GL_MODULATE); R_UseProgram(NULL); } R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_Color(NULL); }
static void X_Frame_f( void ) { if ( ! x_maze.bits || VAR_Changed( x_mazeWidth ) || VAR_Changed( x_mazeHeight ) ) { x_maze.size = x_view.size = c2xy( Clampf( VAR_Num( x_mazeWidth ), 64, 1024 ), Clampf( VAR_Num( x_mazeHeight ), 64, 1024 ) ); int numBytes = x_maze.size.x * x_maze.size.y; x_maze.bits = A_Realloc( x_maze.bits, numBytes * sizeof( *x_maze.bits ) ); x_view.bits = A_Realloc( x_view.bits, numBytes * sizeof( *x_view.bits ) ); GenerateTestMaze( x_maze.size, x_maze.bits ); R_BlitToTexture( x_maze.image, x_maze.bits, x_maze.size, 1 ); CON_Printf( "Changed size of the maze to %d,%d\n", x_maze.size.x, x_maze.size.y ); } if ( VAR_Changed( x_showCursor ) ) { R_ShowCursor( VAR_Num( x_showCursor ) ); } v2_t windowSize = R_GetWindowSize(); x_pixelScale = windowSize.y / ( float )x_maze.size.y; v2_t mouse = I_GetMousePositionV(); v2_t origin = v2Scale( mouse, 1 / x_pixelScale ); memset( x_view.bits, 0, sizeof( *x_view.bits ) * x_view.size.x * x_view.size.y ); if ( ! VAR_Num( x_skipMaze ) ) { // draw the textures before rasterizing // so we can draw debug stuff in the raster routine R_ColorC( colorScaleRGB( colGreen, 0.5f ) ); R_BlendPic( 0, 0, x_maze.size.x * x_pixelScale, windowSize.y, 0, 0, 1, 1, x_maze.image ); } R_Color( 1, 1, 1, 0.5 ); R_BlendPic( 0, 0, x_view.size.x * x_pixelScale, windowSize.y, 0, 0, 1, 1, x_view.image ); for ( int i = 0; i < Clampi( VAR_Num( x_numOctants ), 0, 8 ); i++ ) { RasterizeFOVOctant( origin.x, origin.y, Clampf( VAR_Num( x_losRadius ), 0, 1024 ), x_maze.size.x, x_maze.size.y, i, VAR_Num( x_skipAttenuation ), VAR_Num( x_skipClipToRadius ), VAR_Num( x_darkWalls ), x_maze.bits, x_view.bits ); } R_BlitToTexture( x_view.image, x_view.bits, x_view.size, 1 ); //X_DrawCursor( x_cp437Texture, x_cp437TextureSize, mouse ); }