[render] Add basic 2d line drawing

The software renderer uses Bresenham's line slice algorithm as presented
by Michael Abrash in his Graphics Programming Black Book Special Edition
with the serial numbers filed off (as such, more just so *I* can read
the code easily), along with the Chen-Sutherland line clipping
algorithm. The other renderers were more or less trivial in comparison.
This commit is contained in:
Bill Currie 2022-05-28 18:14:26 +09:00
parent ea781c9dcc
commit 125821fcdd
18 changed files with 375 additions and 28 deletions

View file

@ -41,6 +41,7 @@ void gl_Draw_Crosshair (void);
void gl_Draw_CrosshairAt (int ch, int x, int y);
void gl_Draw_TileClear (int x, int y, int w, int h);
void gl_Draw_Fill (int x, int y, int w, int h, int c);
void gl_Draw_Line (int x0, int y0, int x1, int y1, int c);
void gl_Draw_TextBox (int x, int y, int width, int lines, byte alpha);
void gl_Draw_FadeScreen (void);
void gl_Draw_BlendScreen (quat_t color);

View file

@ -41,6 +41,7 @@ void glsl_Draw_Crosshair (void);
void glsl_Draw_CrosshairAt (int ch, int x, int y);
void glsl_Draw_TileClear (int x, int y, int w, int h);
void glsl_Draw_Fill (int x, int y, int w, int h, int c);
void glsl_Draw_Line (int x0, int y0, int x1, int y1, int c);
void glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha);
void glsl_Draw_FadeScreen (void);
void glsl_Draw_BlendScreen (quat_t color);

View file

@ -50,6 +50,8 @@ void Vulkan_Draw_TileClear (int x, int y, int w, int h,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_Fill (int x, int y, int w, int h, int c,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx);

View file

@ -144,6 +144,17 @@ void Draw_TileClear (int x, int y, int w, int h);
*/
void Draw_Fill (int x, int y, int w, int h, int c);
/** Clear a line with a solid color.
\param x0 horizontal position of the line start point
\param y0 horizontal position of the line start point
\param x1 horizontal position of the line end point
\param y1 horizontal position of the line end point
\param c 8 bit color index.
The color comes from the quake palette.
*/
void Draw_Line (int x0, int y0, int x1, int y1, int c);
/** Draw a text box on the screen
\param x horizontal location of the upper left corner of the box
\param y vertical location of the upper left corner of the box

View file

@ -91,6 +91,7 @@ typedef struct vid_render_funcs_s {
void (*Draw_CrosshairAt) (int ch, int x, int y);
void (*Draw_TileClear) (int x, int y, int w, int h);
void (*Draw_Fill) (int x, int y, int w, int h, int c);
void (*Draw_Line) (int x0, int y0, int x1, int y1, int c);
void (*Draw_TextBox) (int x, int y, int width, int lines, byte alpha);
void (*Draw_FadeScreen) (void);
void (*Draw_BlendScreen) (quat_t color);

View file

@ -910,6 +910,22 @@ gl_Draw_Fill (int x, int y, int w, int h, int c)
qfglEnable (GL_TEXTURE_2D);
}
void
gl_Draw_Line (int x0, int y0, int x1, int y1, int c)
{
qfglDisable (GL_TEXTURE_2D);
qfglColor3ubv (vid.palette + c * 3);
qfglBegin (GL_LINES);
qfglVertex2f (x0, y0);
qfglVertex2f (x1, y1);
qfglEnd ();
qfglColor3ubv (color_white);
qfglEnable (GL_TEXTURE_2D);
}
void
gl_Draw_FadeScreen (void)
{

View file

@ -104,6 +104,7 @@ static struct {
static scrap_t *draw_scrap; // hold all 2d images
static byte white_block[8 * 8];
static dstring_t *draw_queue;
static dstring_t *line_queue;
static qpic_t *conchars;
static int conback_texture;
static qpic_t *crosshair_pic;
@ -388,6 +389,7 @@ glsl_Draw_Init (void)
//crosshaircolor->callback (crosshaircolor);
draw_queue = dstring_new ();
line_queue = dstring_new ();
vert_shader = GLSL_BuildShader (twod_vert_effects);
frag_shader = GLSL_BuildShader (twod_frag_effects);
@ -461,14 +463,26 @@ static void
flush_2d (void)
{
GLSL_ScrapFlush (draw_scrap);
qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap));
if (draw_queue->size) {
qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT,
0, 32, draw_queue->str);
qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT,
0, 32, draw_queue->str + 16);
qfeglDrawArrays (GL_TRIANGLES, 0, draw_queue->size / 32);
}
if (line_queue->size) {
qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT,
0, 32, line_queue->str);
qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT,
0, 32, line_queue->str + 16);
qfeglDrawArrays (GL_LINES, 0, line_queue->size / 32);
}
draw_queue->size = 0;
line_queue->size = 0;
}
void
@ -693,6 +707,32 @@ glsl_Draw_Fill (int x, int y, int w, int h, int c)
draw_pic (x, y, w, h, white_pic, 0, 0, 8, 8, color);
}
void
glsl_Draw_Line (int x0, int y0, int x1, int y1, int c)
{
glpic_t *gl = (glpic_t *) white_pic->data;
subpic_t *sp = gl->subpic;
float sl = sp->rect->x * sp->size;
float sh = sp->rect->x * sp->size;
float tl = sp->rect->y * sp->size;
float th = sp->rect->y * sp->size;
quat_t color = { VectorExpand (vid.palette + c * 3), 255 };
QuatScale (color, 1/255.0, color);
drawvert_t verts[2] = {
{ .xyst = { x0, y0, sl, tl }, .color = { QuatExpand (color) }, },
{ .xyst = { x1, y1, sh, th }, .color = { QuatExpand (color) }, },
};
void *v;
int size = sizeof (verts);
line_queue->size += size;
dstring_adjust (line_queue);
v = line_queue->str + line_queue->size - size;
memcpy (v, verts, size);
}
static inline void
draw_blendscreen (quat_t color)
{
@ -784,12 +824,13 @@ void
GLSL_DrawReset (void)
{
draw_queue->size = 0;
line_queue->size = 0;
}
void
GLSL_FlushText (void)
{
if (draw_queue->size)
if (draw_queue->size || line_queue->size)
flush_2d ();
}

View file

@ -42,6 +42,8 @@
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/ui/view.h"
#include "r_internal.h"
typedef struct {
@ -296,6 +298,18 @@ bi_Draw_Fill (progs_t *pr, void *_res)
r_funcs->Draw_Fill (x, y, w, h, color);
}
static void
bi_Draw_Line (progs_t *pr, void *_res)
{
int x0 = P_INT (pr, 0);
int y0 = P_INT (pr, 1);
int x1 = P_INT (pr, 2);
int y1 = P_INT (pr, 3);
int color = P_INT (pr, 4);
r_funcs->Draw_Line (x0, y0, x1, y1, color);
}
static void
bi_Draw_Crosshair (progs_t *pr, void *_res)
{
@ -306,6 +320,18 @@ bi_Draw_Crosshair (progs_t *pr, void *_res)
r_funcs->Draw_CrosshairAt (ch, x, y);
}
static void
bi_Draw_Width (progs_t *pr, void *_res)
{
R_INT (pr) = r_data->vid->conview->xlen;
}
static void
bi_Draw_Height (progs_t *pr, void *_res)
{
R_INT (pr) = r_data->vid->conview->ylen;
}
static const char *
bi_draw_get_key (const void *p, void *unused)
{
@ -338,6 +364,8 @@ bi_draw_destroy (progs_t *pr, void *_res)
#define p(type) PR_PARAM(type)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
static builtin_t builtins[] = {
bi(Draw_Width, 0),
bi(Draw_Height, 0),
bi(Draw_FreePic, 1, p(ptr)),
bi(Draw_MakePic, 3, p(int), p(int), p(string)),
bi(Draw_CachePic, 2, p(string), p(int)),
@ -351,6 +379,7 @@ static builtin_t builtins[] = {
bi(Draw_nString, 4, p(int), p(int), p(string), p(int)),
bi(Draw_AltString, 3, p(int), p(int), p(string)),
bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)),
bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)),
bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)),
{0}
};

View file

@ -766,6 +766,165 @@ Draw_Fill (int x, int y, int w, int h, int c)
dest[u] = c;
}
static inline byte *
draw_horizontal (byte *dest, int xs, int len, int c)
{
while (len-- > 0) {
*dest = c;
dest += xs;
}
return dest;
}
static inline byte *
draw_vertical (byte *dest, int len, int c)
{
while (len-- > 0) {
*dest = c;
dest += d_rowbytes;
}
return dest;
}
static void
draw_line (int x0, int y0, int x1, int y1, int c)
{
// Bresenham's line slice algorith (ala Michael Abrash)
int dx, dy, sx;
// always go top to bottom
if (y1 < y0) {
int t;
t = y1; y1 = y0; y0 = t;
t = x1; x1 = x0; x0 = t;
}
dy = y1 - y0;
if ((dx = x1 - x0) < 0) {
sx = -1;
dx = -dx;
} else {
sx = 1;
}
byte *dest = d_viewbuffer + y0 * d_rowbytes + x0;
if (!dx) {
draw_vertical (dest, dy, c);
return;
}
if (!dy) {
draw_horizontal (dest, sx, dx, c);
return;
}
if (dx == dy) {
while (dy-- > 0) {
*dest = c;
dest += d_rowbytes + sx;
}
return;
}
if (dx > dy) {
int step = dx / dy;
int adj_up = (dx % dy) * 2;
int adj_down = dy * 2;
int error = (dx % dy) - adj_down;
int initial = step / 2 + 1;
int final = initial;
if (!adj_up && !(step & 1)) {
initial--;
}
if (step & 1) {
error += dy;
}
dest = draw_horizontal (dest, sx, initial, c);
dest += d_rowbytes;
while (dy-- > 1) {
int run = step;
if ((error += adj_up) > 0) {
run++;
error -= adj_down;
}
dest = draw_horizontal (dest, sx, run, c);
dest += d_rowbytes;
}
dest = draw_horizontal (dest, sx, final, c);
} else {
int step = dy / dx;
int adj_up = (dy % dx) * 2;
int adj_down = dx * 2;
int error = (dy % dx) - adj_down;
int initial = step / 2 + 1;
int final = initial;
if (!adj_up && !(step & 1)) {
initial--;
}
if (step & 1) {
error += dx;
}
dest = draw_vertical (dest, initial, c);
dest += sx;
while (dx-- > 1) {
int run = step;
if ((error += adj_up) > 0) {
run++;
error -= adj_down;
}
dest = draw_vertical (dest, run, c);
dest += sx;
}
dest = draw_vertical (dest, final, c);
}
}
static inline byte
test_point (int x, int y)
{
byte c = 0;
if (x < 0) {
c |= 1;
} else if (x >= vid.conview->xlen) {
c |= 2;
}
if (y < 0) {
c |= 4;
} else if (y >= vid.conview->ylen) {
c |= 8;
}
return c;
}
void
Draw_Line (int x0, int y0, int x1, int y1, int c)
{
byte c0 = test_point (x0, y0);
byte c1 = test_point (x1, y1);
int xmax = vid.conview->xlen - 1;
int ymax = vid.conview->ylen - 1;
while (c0 | c1) {
// Cohen-Sutherland line clipping
if (c0 & c1) {
return;
}
int dx = x1 - x0;
int dy = y1 - y0;
if (c0 & 1) { y0 = (( 0 - x0) * dy + dx * y0) / dx; x0 = 0; }
if (c0 & 2) { y0 = ((xmax - x0) * dy + dx * y0) / dx; x0 = xmax; }
if (c1 & 1) { y1 = (( 0 - x1) * dy + dx * y1) / dx; x1 = 0; }
if (c1 & 2) { y1 = ((xmax - x1) * dy + dx * y1) / dx; x1 = xmax; }
if (c0 & 4) { x0 = (( 0 - y0) * dx + dy * x0) / dy; y0 = 0; }
if (c0 & 8) { x0 = ((ymax - y0) * dx + dy * x0) / dy; y0 = ymax; }
if (c1 & 4) { x1 = (( 0 - y1) * dx + dy * x1) / dy; y1 = 0; }
if (c1 & 8) { x1 = ((ymax - y1) * dx + dy * x1) / dy; y1 = ymax; }
c0 = test_point (x0, y0);
c1 = test_point (x1, y1);
}
draw_line (x0, y0, x1, y1, c);
}
void
Draw_FadeScreen (void)

View file

@ -495,6 +495,7 @@ vid_render_funcs_t gl_vid_render_funcs = {
gl_Draw_CrosshairAt,
gl_Draw_TileClear,
gl_Draw_Fill,
gl_Draw_Line,
gl_Draw_TextBox,
gl_Draw_FadeScreen,
gl_Draw_BlendScreen,

View file

@ -439,6 +439,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
glsl_Draw_CrosshairAt,
glsl_Draw_TileClear,
glsl_Draw_Fill,
glsl_Draw_Line,
glsl_Draw_TextBox,
glsl_Draw_FadeScreen,
glsl_Draw_BlendScreen,

View file

@ -459,6 +459,7 @@ vid_render_funcs_t sw_vid_render_funcs = {
Draw_CrosshairAt,
Draw_TileClear,
Draw_Fill,
Draw_Line,
Draw_TextBox,
Draw_FadeScreen,
Draw_BlendScreen,

View file

@ -189,6 +189,12 @@ vulkan_Draw_Fill (int x, int y, int w, int h, int c)
Vulkan_Draw_Fill (x, y, w, h, c, vulkan_ctx);
}
static void
vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c)
{
Vulkan_Draw_Line (x0, y0, x1, y1, c, vulkan_ctx);
}
static void
vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha)
{
@ -731,6 +737,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
vulkan_Draw_CrosshairAt,
vulkan_Draw_TileClear,
vulkan_Draw_Fill,
vulkan_Draw_Line,
vulkan_Draw_TextBox,
vulkan_Draw_FadeScreen,
vulkan_Draw_BlendScreen,

View file

@ -482,6 +482,10 @@
topology = triangle_list;
primitiveRestartEnable = false;
};
lines = {
topology = line_list;
primitiveRestartEnable = false;
};
twod = {
topology = triangle_strip;
primitiveRestartEnable = true;
@ -1045,6 +1049,10 @@
};
layout = twod_layout;
};
lines = {
@inherit = $properties.pipelines.twod;
inputAssembly = $properties.inputAssembly.lines;
};
lighting = {
@inherit = $properties.pipelines.comp_base;
subpass = 3;

View file

@ -1072,8 +1072,10 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
int world_id = worldent.renderer.model->render_id;
bctx->main_pass.ent_frame = 0; // world is always frame 0
bctx->main_pass.inst_id = world_id;
if (bctx->main_pass.instances) {
DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities,
worldent.renderer.render_id);
}
R_VisitWorldNodes (brush, ctx);
if (!bctx->vertex_buffer) {
return;

View file

@ -82,8 +82,11 @@ typedef struct cachepic_s {
typedef struct drawframe_s {
size_t vert_offset;
drawvert_t *verts;
size_t line_offset;
drawvert_t *quad_verts;
drawvert_t *line_verts;
uint32_t num_quads;
uint32_t num_lines;
VkCommandBuffer cmd;
VkDescriptorSet descriptors;
} drawframe_t;
@ -109,7 +112,8 @@ typedef struct drawctx_s {
VkDeviceMemory vert_memory;
VkBuffer ind_buffer;
VkDeviceMemory ind_memory;
VkPipeline pipeline;
VkPipeline quad_pipeline;
VkPipeline line_pipeline;
VkPipelineLayout layout;
drawframeset_t frames;
} drawctx_t;
@ -119,6 +123,11 @@ typedef struct drawctx_s {
#define VERTS_PER_QUAD (4)
#define INDS_PER_QUAD (5) // one per vert plus primitive reset
#define MAX_LINES (32768)
#define VERTS_PER_LINE (2)
#define VERTS_PER_FRAME (MAX_LINES*VERTS_PER_LINE + MAX_QUADS*VERTS_PER_QUAD)
static void
create_quad_buffers (vulkan_ctx_t *ctx)
{
@ -133,7 +142,7 @@ create_quad_buffers (vulkan_ctx_t *ctx)
VkBuffer vbuf, ibuf;
VkDeviceMemory vmem, imem;
vert_size = frames * MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t);
vert_size = frames * VERTS_PER_FRAME * sizeof (drawvert_t);
ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t);
vbuf = QFV_CreateBuffer (device, vert_size,
@ -161,10 +170,14 @@ create_quad_buffers (vulkan_ctx_t *ctx)
for (size_t f = 0; f < frames; f++) {
drawframe_t *frame = &dctx->frames.a[f];
size_t ind = f * MAX_QUADS * VERTS_PER_QUAD;
size_t ind = f * VERTS_PER_FRAME;
size_t lind = ind + MAX_QUADS * VERTS_PER_QUAD;
frame->vert_offset = ind * sizeof (drawvert_t);
frame->verts = vert_data + ind;
frame->line_offset = lind;
frame->quad_verts = vert_data + ind;
frame->line_verts = frame->quad_verts + MAX_QUADS * VERTS_PER_QUAD;
frame->num_quads = 0;
frame->num_lines = 0;
}
// The indices will never change so pre-generate and stash them
@ -347,7 +360,8 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx)
destroy_quad_buffers (ctx);
dfunc->vkDestroyPipeline (device->dev, dctx->pipeline, 0);
dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0);
dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0);
Hash_DelTable (dctx->pic_cache);
delete_memsuper (dctx->pic_memsuper);
delete_memsuper (dctx->string_memsuper);
@ -409,7 +423,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
flush_draw_scrap (ctx);
dctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod");
dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod");
dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines");
dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout");
@ -457,7 +472,7 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic,
return;
}
drawvert_t *verts = frame->verts + frame->num_quads * VERTS_PER_QUAD;
drawvert_t *verts = frame->quad_verts + frame->num_quads * VERTS_PER_QUAD;
frame->num_quads++;
subpic_t *subpic = *(subpic_t **) pic->data;
@ -767,6 +782,32 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx)
draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, frame);
}
void
Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx)
{
drawctx_t *dctx = ctx->draw_context;
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
if (frame->num_quads >= MAX_QUADS) {
return;
}
quat_t color = { VectorExpand (vid.palette + c * 3), 255 };
QuatScale (color, 1/255.0, color);
drawvert_t *verts = frame->line_verts + frame->num_lines * VERTS_PER_LINE;
verts[0] = (drawvert_t) {
.xy = { x0, y0 },
.color = { QuatExpand (color) },
};
verts[1] = (drawvert_t) {
.xy = { x1, y1 },
.color = { QuatExpand (color) },
};
frame->num_lines++;
}
static inline void
draw_blendscreen (quat_t color, vulkan_ctx_t *ctx)
{
@ -816,16 +857,23 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
drawctx_t *dctx = ctx->draw_context;
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
if (!dframe->num_quads && !dframe->num_lines) {
return;
}
VkCommandBuffer cmd = dframe->cmd;
//FIXME which pass?
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd);
VkMappedMemoryRange range = {
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
VkMappedMemoryRange ranges[] = {
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
dctx->vert_memory, dframe->vert_offset,
dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t),
dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t) },
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
dctx->vert_memory, dframe->line_offset,
dframe->num_lines * VERTS_PER_LINE * sizeof (drawvert_t) },
};
dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range);
dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges);
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
@ -843,10 +891,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1});
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
dctx->pipeline);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
VkDeviceSize offsets[] = {dframe->vert_offset};
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets);
dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0,
@ -858,13 +902,27 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
VkPipelineLayout layout = dctx->layout;
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 2, set, 0, 0);
if (dframe->num_quads) {
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
dctx->quad_pipeline);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD,
1, 0, 0, 0);
}
if (dframe->num_lines) {
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
dctx->line_pipeline);
dfunc->vkCmdDraw (cmd, dframe->num_lines * VERTS_PER_LINE,
1, MAX_QUADS * VERTS_PER_QUAD, 0);
}
QFV_duCmdEndLabel (device, cmd);
dfunc->vkEndCommandBuffer (cmd);
dframe->num_quads = 0;
dframe->num_lines = 0;
}
void

View file

@ -10,6 +10,9 @@ struct _qpic_t {
};
typedef struct _qpic_t *qpic_t;
@extern int Draw_Width (void);
@extern int Draw_Height (void);
@extern void Draw_FreePic (qpic_t pic);
@extern qpic_t Draw_MakePic (int width, int heiight, string data);
@extern qpic_t Draw_CachePic (string name, int alpha);
@ -24,6 +27,7 @@ typedef struct _qpic_t *qpic_t;
@extern void Draw_nString (int x, int y, string text, int n);
@extern void Draw_AltString (int x, int y, string text);
@extern void Draw_Fill (int x, int y, int w, int h, int c);
@extern void Draw_Line (int x0, int y0, int x1, int y1, int c);
@extern void Draw_Crosshair (int ch, int x, int y);
@extern void text_box (int x, int y, int width, int lines);

View file

@ -1,5 +1,8 @@
#include <draw.h>
int Draw_Width (void) = #0;
int Draw_Height (void) = #0;
void Draw_FreePic (qpic_t pic) = #0;
qpic_t Draw_MakePic (int width, int heiight, string data) = #0;
qpic_t (string name, int alpha) Draw_CachePic = #0;
@ -14,6 +17,7 @@ void (int x, int y, string text) Draw_String = #0;
void (int x, int y, string text, int n) Draw_nString = #0;
void (int x, int y, string text) Draw_AltString = #0;
void (int x, int y, int w, int h, int c) Draw_Fill = #0;
void (int x0, int y0, int x1, int y1, int c) Draw_Line = #0;
void (int ch, int x, int y) Draw_Crosshair = #0;
void (int x, int y, int width, int lines) text_box =