[renderer] Get sw fisheye working again

Again, gl/vulkan not working yet (on the assumption that sw would be
trickier).

Fisheye overrides water warp because updating the projection map every
frame is far too expensive.

I've added a post-process pass to the interface in order to hide the
implementation details, but I'm not sure I'm happy about how the
multi-pass rendering for cube maps is handled (or having the frame
buffers as exposed as they are), but mainly because Vulkan will make
implementation interesting.
This commit is contained in:
Bill Currie 2022-03-24 15:45:01 +09:00
parent 0c437492b4
commit 20a2e7e06f
11 changed files with 366 additions and 237 deletions

View file

@ -40,6 +40,7 @@ struct skin_s;
struct mod_alias_ctx_s;
struct mod_sprite_ctx_s;
struct entqueue_s;
struct framebuffer_s;
/*
All video plugins must export these functions
@ -112,9 +113,11 @@ typedef struct vid_render_funcs_s {
void (*draw_entities) (struct entqueue_s *queue);
void (*draw_particles) (struct psystem_s *psystem);
void (*draw_transparent) (void);
void (*post_process) (struct framebuffer_s *src);
void (*set_2d) (int scaled);
void (*end_frame) (void);
struct framebuffer_s *(*create_cube_map) (int side);
struct framebuffer_s *(*create_frame_buffer) (int width, int height);
void (*bind_framebuffer) (struct framebuffer_s *framebuffer);

View file

@ -81,4 +81,13 @@ int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec,
mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite,
const animation_t *animation);
// These correspond to the standard box sides for OpenGL cube maps
#define BOX_FRONT 4
#define BOX_RIGHT 0
#define BOX_BEHIND 5
#define BOX_LEFT 1
#define BOX_TOP 2
#define BOX_BOTTOM 3
void R_RenderFisheye (framebuffer_t *cube);
#endif//__r_internal_h

View file

@ -157,6 +157,7 @@ libs_video_renderer_librender_sw_la_SOURCES = \
libs/video/renderer/sw/nonintel.c \
libs/video/renderer/sw/screen.c \
libs/video/renderer/sw/surf8.S \
libs/video/renderer/sw/sw_fisheye.c \
libs/video/renderer/sw/sw_graph.c \
libs/video/renderer/sw/sw_raclip.c \
libs/video/renderer/sw/sw_raclipa.S \

View file

@ -364,14 +364,14 @@ gl_R_RenderView (void)
// translation function to map texture coordinates to fixed/regular
// grid vertices coordinates.
// Render view. Fisheye is done.
#if 0
#define BOX_FRONT 0
#define BOX_RIGHT 1
#define BOX_BEHIND 2
#define BOX_LEFT 3
#define BOX_TOP 4
#define BOX_BOTTOM 5
#endif
static mat4f_t box_rotations[] = {
{ { 1, 0, 0, 0}, // front
{ 0, 1, 0, 0},

View file

@ -66,7 +66,48 @@ static qboolean scr_initialized;// ready to draw
static qpic_t *scr_ram;
static qpic_t *scr_turtle;
static framebuffer_t *fisheye_cube_map;
static framebuffer_t *warp_buffer;
static mat4f_t box_rotations[] = {
[BOX_FRONT] = {
{ 1, 0, 0, 0}, // front
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_RIGHT] = {
{ 0,-1, 0, 0}, // right
{ 1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_BEHIND] = {
{-1, 0, 0, 0}, // back
{ 0,-1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_LEFT] = {
{ 0, 1, 0, 0}, // left
{-1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_TOP] = {
{ 0, 0, 1, 0}, // top
{ 0, 1, 0, 0},
{-1, 0, 0, 0},
{ 0, 0, 0, 1}
},
[BOX_BOTTOM] = {
{ 0, 0,-1, 0}, // bottom
{ 0, 1, 0, 0},
{ 1, 0, 0, 0},
{ 0, 0, 0, 1}
},
};
static void
set_vrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj)
{
@ -138,6 +179,44 @@ SCR_CalcRefdef (void)
r_data->scr_fullupdate = 0;
}
static void
render_scene (void)
{
r_framecount++;
EntQueue_Clear (r_ent_queue);
r_funcs->render_view ();
r_funcs->draw_entities (r_ent_queue);
r_funcs->draw_particles (&r_psystem);
r_funcs->draw_transparent ();
}
static void
render_side (int side)
{
mat4f_t camera;
mat4f_t camera_inverse;
mat4f_t rotinv;
memcpy (camera, r_refdef.camera, sizeof (camera));
memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse));
mmulf (r_refdef.camera, camera, box_rotations[side]);
mat4ftranspose (rotinv, box_rotations[side]);
mmulf (r_refdef.camera_inverse, rotinv, camera_inverse);
//FIXME see fixme in r_screen.c
r_refdef.frame.mat[0] = -r_refdef.camera[1];
r_refdef.frame.mat[1] = r_refdef.camera[0];
r_refdef.frame.mat[2] = r_refdef.camera[2];
r_refdef.frame.mat[3] = r_refdef.camera[3];
r_data->refdef->fov_x = r_data->refdef->fov_y = 90;
r_funcs->bind_framebuffer (&fisheye_cube_map[side]);
render_scene ();
memcpy (r_refdef.camera, camera, sizeof (camera));
memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse));
}
/*
SCR_UpdateScreen
@ -158,6 +237,10 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
r_time1 = Sys_DoubleTime ();
}
if (scr_fisheye->int_val && !fisheye_cube_map) {
fisheye_cube_map = r_funcs->create_cube_map (r_data->vid->height);
}
refdef_t *refdef = r_data->refdef;
if (camera) {
Transform_GetWorldMatrix (camera, refdef->camera);
@ -181,10 +264,6 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
R_SetFrustum (refdef->frustum, &refdef->frame,
refdef->fov_x, refdef->fov_y);
//FIXME breaks fisheye as it calls the view render many times
EntQueue_Clear (r_ent_queue);
r_framecount++;
r_data->realtime = realtime;
scr_copytop = r_data->scr_copyeverything = 0;
@ -203,7 +282,8 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER;
}
if (r_dowarp && !warp_buffer) {
warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height);
warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width,
r_data->vid->height);
}
}
R_MarkLeaves ();
@ -213,10 +293,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
if (r_dowarp) {
r_funcs->bind_framebuffer (warp_buffer);
}
r_funcs->render_view ();
r_funcs->draw_entities (r_ent_queue);
r_funcs->draw_particles (&r_psystem);
r_funcs->draw_transparent ();
if (scr_fisheye->int_val) {
switch (scr_fviews->int_val) {
case 6: render_side (BOX_BEHIND);
case 5: render_side (BOX_BOTTOM);
case 4: render_side (BOX_TOP);
case 3: render_side (BOX_LEFT);
case 2: render_side (BOX_RIGHT);
default:render_side (BOX_FRONT);
}
r_funcs->bind_framebuffer (0);
r_funcs->post_process (fisheye_cube_map);
} else {
render_scene ();
r_funcs->post_process (warp_buffer);
}
r_funcs->set_2d (0);
view_draw (r_data->scr_view);
r_funcs->set_2d (1);

View file

@ -0,0 +1,166 @@
/*
sw_fisheye.c
SW fisheye rendering
Copyright (C) 2003 Arkadi Shishlov <arkadi@it.lv>
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <math.h>
#include "QF/cvar.h"
#include "QF/render.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static void
fisheyelookuptable (byte **buf, int width, int height, framebuffer_t *cube,
double fov)
{
int cube_size = cube->width;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
double dx = x - width / 2;
double dy = -(y - height / 2);
double yaw = sqrt (dx * dx + dy * dy) * fov / width;
double roll = atan2 (dy, dx);
double sx = sin (yaw) * cos (roll);
double sy = sin (yaw) * sin (roll);
double sz = cos (yaw);
// determine which side of the box we need
double abs_x = fabs (sx);
double abs_y = fabs (sy);
double abs_z = fabs (sz);
int side;
double xs = 0, ys = 0;
if (abs_x > abs_y) {
if (abs_x > abs_z) {
side = ((sx > 0.0) ? BOX_RIGHT : BOX_LEFT);
} else {
side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND);
}
} else {
if (abs_y > abs_z) {
side = ((sy > 0.0) ? BOX_TOP : BOX_BOTTOM);
} else {
side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND);
}
}
#define RC(x) ((x / 2) + 0.5)
#define R2(x) ((x / 2) + 0.5)
// scale up our vector [x,y,z] to the box
switch(side) {
case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break;
case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break;
case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break;
case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break;
case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break;
case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break;
}
xs = bound (0, xs, 1);
ys = bound (0, ys, 1);
int sxs = xs * (cube_size - 1);
int sys = ys * (cube_size - 1);
sw_framebuffer_t *fb = cube[side].buffer;
*buf++ = fb->color + sys * fb->rowbytes + sxs;
}
}
}
static void
renderlookup (byte **offs)
{
framebuffer_t *fb = sw_ctx->framebuffer;
sw_framebuffer_t *swfb = fb->buffer;
byte *p = swfb->color;
unsigned x, y;
for (y = 0; y < fb->height; y++) {
for (x = 0; x < fb->width; x++, offs++)
p[x] = **offs;
p += swfb->rowbytes;
}
}
void
R_RenderFisheye (framebuffer_t *cube)
{
int width = r_refdef.vrect.width;
int height = r_refdef.vrect.height;
int fov = scr_ffov->int_val;
static int pwidth = -1;
static int pheight = -1;
static int pfov = -1;
static unsigned psize = -1;
static byte **offs = NULL;
if (fov < 1) fov = 1;
if (pwidth != width || pheight != height || pfov != fov
|| psize != cube->width) {
if (offs) free (offs);
offs = malloc (width*height*sizeof(byte*));
SYS_CHECKMEM (offs);
pwidth = width;
pheight = height;
pfov = fov;
psize = cube->width;
fisheyelookuptable (offs, width, height, cube, fov*M_PI/180.0);
}
#if 0
sw_framebuffer_t *fb = cube[0].buffer;
int rowbytes = fb->rowbytes;
int csize = cube[0].width;
for (int s = 0; s < 6; s++) {
fb = cube[s].buffer;
memset (fb->color, 31, csize);
memset (fb->color + (csize - 1) * rowbytes, 31, csize);
for (int y = 0; y < csize; y++) {
fb->color[y * rowbytes] = 31;
fb->color[y * rowbytes + csize - 1] = 31;
}
}
#endif
renderlookup (offs);
}

View file

@ -713,8 +713,6 @@ R_RenderView_ (void)
R_HighFPPrecision ();
}
static void R_RenderViewFishEye (void);
void
R_RenderView (void)
{
@ -733,10 +731,8 @@ R_RenderView (void)
if ((intptr_t) (&colormap) & 3)
Sys_Error ("Globals are missaligned");
if (!scr_fisheye->int_val)
R_RenderView_ ();
else
R_RenderViewFishEye ();
R_RenderView_ ();
}
void
@ -751,224 +747,6 @@ R_InitTurb (void)
}
}
#define BOX_FRONT 0
#define BOX_RIGHT 1
#define BOX_BEHIND 2
#define BOX_LEFT 3
#define BOX_TOP 4
#define BOX_BOTTOM 5
#if 0
static mat4f_t box_rotations[] = {
{ { 1, 0, 0, 0}, // front
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0,-1, 0, 0}, // right
{ 1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ {-1, 0, 0, 0}, // back
{ 0,-1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0, 1, 0, 0}, // left
{-1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0, 0, 1, 0}, // top
{ 0, 1, 0, 0},
{-1, 0, 0, 0},
{ 0, 0, 0, 1} },
{ { 0, 0,-1, 0}, // bottom
{ 0, 1, 0, 0},
{ 1, 0, 0, 0},
{ 0, 0, 0, 1} },
};
#endif
static int sw_cube_map_size;
static void
fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov)
{
int x, y;
int scrsize = sw_cube_map_size * sw_cube_map_size;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
double dx = x-width/2;
double dy = -(y-height/2);
double yaw = sqrt(dx*dx+dy*dy)*fov/((double)width);
double roll = atan2(dy, dx);
double sx = sin(yaw) * cos(roll);
double sy = sin(yaw) * sin(roll);
double sz = cos(yaw);
// determine which side of the box we need
double abs_x = fabs(sx);
double abs_y = fabs(sy);
double abs_z = fabs(sz);
int side;
double xs = 0, ys = 0;
if (abs_x > abs_y) {
if (abs_x > abs_z) { side = ((sx > 0.0) ? BOX_RIGHT : BOX_LEFT); }
else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); }
} else {
if (abs_y > abs_z) { side = ((sy > 0.0) ? BOX_TOP : BOX_BOTTOM); }
else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); }
}
#define RC(x) ((x / 2) + 0.5)
#define R2(x) ((x / 2) + 0.5)
// scale up our vector [x,y,z] to the box
switch(side) {
case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break;
case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break;
case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break;
case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break;
case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break;
case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break;
}
if (xs < 0.0) xs = 0.0;
if (xs >= 1.0) xs = 0.999;
if (ys < 0.0) ys = 0.0;
if (ys >= 1.0) ys = 0.999;
int sxs = xs * sw_cube_map_size;
int sys = ys * sw_cube_map_size;
*buf++ = scrp+side * scrsize + sys * sw_cube_map_size + sxs;
}
}
}
#if 0
static void
rendercopy (void *dest)
{
void *p = vid.buffer;
// XXX
vid.buffer = dest;
R_RenderView_ ();
vid.buffer = p;
}
static void
renderside (byte *bufs, int side)
{
mat4f_t camera;
mat4f_t camera_inverse;
mat4f_t rotinv;
memcpy (camera, r_refdef.camera, sizeof (camera));
memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse));
mmulf (r_refdef.camera, camera, box_rotations[side]);
mat4ftranspose (rotinv, box_rotations[side]);
mmulf (r_refdef.camera_inverse, rotinv, camera_inverse);
//FIXME see fixme in r_screen.c
r_refdef.frame.mat[0] = -r_refdef.camera[1];
r_refdef.frame.mat[1] = r_refdef.camera[0];
r_refdef.frame.mat[2] = r_refdef.camera[2];
r_refdef.frame.mat[3] = r_refdef.camera[3];
float fov_x = r_refdef.fov_x;
float fov_y = r_refdef.fov_y;
unsigned width = vid.width;
unsigned height = vid.height;
vrect_t rect = r_refdef.vrect;
r_refdef.fov_x = r_refdef.fov_y = 90;
r_refdef.vrect.x = r_refdef.vrect.y = 0;
r_refdef.vrect.height = r_refdef.vrect.width = sw_cube_map_size;
vid.rowbytes = vid.height = vid.width = sw_cube_map_size;
R_ViewChanged ();
rendercopy (bufs);
vid.rowbytes = width;
r_refdef.vrect = rect;
vid.height = height;
vid.width = width;
r_refdef.fov_x = fov_x;
r_refdef.fov_y = fov_y;
memcpy (r_refdef.camera, camera, sizeof (camera));
memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse));
}
#endif
static void
renderlookup (byte **offs, byte* bufs)
{
framebuffer_t *fb = sw_ctx->framebuffer;
sw_framebuffer_t *swfb = fb->buffer;
byte *p = swfb->color;
unsigned x, y;
for (y = 0; y < fb->height; y++) {
for (x = 0; x < fb->width; x++, offs++)
p[x] = **offs;
p += swfb->rowbytes;
}
}
static void
R_RenderViewFishEye (void)
{
sw_cube_map_size = vid.height;
int width = vid.width; //r_refdef.vrect.width;
int height = vid.height; //r_refdef.vrect.height;
int scrsize = sw_cube_map_size * sw_cube_map_size;
int fov = scr_ffov->int_val;
int views = scr_fviews->int_val;
static int pwidth = -1;
static int pheight = -1;
static int pfov = -1;
static int pviews = -1;
static byte *scrbufs = NULL;
static byte **offs = NULL;
if (fov < 1) fov = 1;
if (pwidth != width || pheight != height || pfov != fov) {
if (scrbufs) free (scrbufs);
if (offs) free (offs);
// front|right|back|left|top|bottom
scrbufs = malloc (scrsize*6);
SYS_CHECKMEM (scrbufs);
offs = malloc (width*height*sizeof(byte*));
SYS_CHECKMEM (offs);
pwidth = width;
pheight = height;
pfov = fov;
fisheyelookuptable (offs, width, height, scrbufs, fov*M_PI/180.0);
}
if (views != pviews) {
pviews = views;
memset (scrbufs, 0, scrsize*6);
}
#if 0
switch (views) {
case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND);
case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM);
case 4: renderside (scrbufs + scrsize * BOX_TOP, BOX_TOP);
case 3: renderside (scrbufs + scrsize * BOX_LEFT, BOX_LEFT);
case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT);
default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT);
}
#endif
#if 0
memset (scrbufs + scrsize*0, 31, sw_cube_map_size);
memset (scrbufs + scrsize*1, 31, sw_cube_map_size);
memset (scrbufs + scrsize*2, 31, sw_cube_map_size);
memset (scrbufs + scrsize*3, 31, sw_cube_map_size);
memset (scrbufs + scrsize*4, 31, sw_cube_map_size);
memset (scrbufs + scrsize*5, 31, sw_cube_map_size);
for (int y = 0; y < sw_cube_map_size * 6; y++) {
scrbufs[y * sw_cube_map_size] = 31;
scrbufs[y * sw_cube_map_size + sw_cube_map_size - 1] = 31;
}
#endif
renderlookup (offs, scrbufs);
}
void
R_ClearState (void)
{

View file

@ -268,6 +268,11 @@ gl_draw_transparent (void)
gl_R_DrawWaterSurfaces ();
}
static void
gl_post_process (framebuffer_t *src)
{
}
static void
gl_set_2d (int scaled)
{
@ -300,6 +305,12 @@ gl_end_frame (void)
}
}
static framebuffer_t *
gl_create_cube_map (int size)
{
Sys_Error ("not implemented");
}
static framebuffer_t *
gl_create_frame_buffer (int width, int height)
{
@ -348,9 +359,11 @@ vid_render_funcs_t gl_vid_render_funcs = {
gl_R_RenderEntities,
gl_R_DrawParticles,
gl_draw_transparent,
gl_post_process,
gl_set_2d,
gl_end_frame,
gl_create_cube_map,
gl_create_frame_buffer,
gl_bind_framebuffer,

View file

@ -226,6 +226,11 @@ glsl_draw_transparent (void)
glsl_R_DrawWaterSurfaces ();
}
static void
glsl_post_process (framebuffer_t *src)
{
}
static void
glsl_set_2d (int scaled)
{
@ -244,6 +249,12 @@ glsl_end_frame (void)
qfeglFlush ();
}
static framebuffer_t *
glsl_create_cube_map (int size)
{
Sys_Error ("not implemented");
}
static framebuffer_t *
glsl_create_frame_buffer (int width, int height)
{
@ -292,9 +303,11 @@ vid_render_funcs_t glsl_vid_render_funcs = {
glsl_R_RenderEntities,
glsl_R_DrawParticles,
glsl_draw_transparent,
glsl_post_process,
glsl_set_2d,
glsl_end_frame,
glsl_create_cube_map,
glsl_create_frame_buffer,
glsl_bind_framebuffer,

View file

@ -157,14 +157,27 @@ sw_draw_transparent (void)
}
static void
sw_set_2d (int scaled)
sw_post_process (framebuffer_t *src)
{
if (!scaled && r_dowarp) {
int bind = 0;
if (scr_fisheye->int_val) {
R_RenderFisheye (src);
bind = 1;
} else if (r_dowarp) {
D_WarpScreen ();
bind = 1;
}
if (bind) {
sw_bind_framebuffer (0);
}
}
static void
sw_set_2d (int scaled)
{
}
static void
sw_end_frame (void)
{
@ -198,6 +211,33 @@ sw_end_frame (void)
sw_ctx->update (sw_ctx, &vrect);
}
static framebuffer_t *
sw_create_cube_map (int side)
{
size_t pixels = side * side; // per face
size_t size = sizeof (framebuffer_t) * 6;
size += sizeof (sw_framebuffer_t) * 6;
size += pixels * 6; // color buffer
// depth buffer, scan table and zspantable are shared between cube faces
// FIXME need *6 depth and zspan for multi-threaded
size += pixels * sizeof (short); // depth buffer
framebuffer_t *cube = malloc (size);
__auto_type buffer_base = (sw_framebuffer_t *) &cube[6];
byte *color_base = (byte *) &buffer_base[6];
short *depth_base = (short *) (color_base + 6 * pixels);
for (int i = 0; i < 6; i++) {
cube[i].width = side;
cube[i].height = side;
__auto_type buffer = buffer_base + i;
cube[i].buffer = buffer;
buffer->color = color_base + i * pixels;
buffer->depth = depth_base;
buffer->rowbytes = side;
}
return cube;
}
static framebuffer_t *
sw_create_frame_buffer (int width, int height)
{
@ -297,9 +337,11 @@ vid_render_funcs_t sw_vid_render_funcs = {
R_DrawEntitiesOnList,
R_DrawParticles,
sw_draw_transparent,
sw_post_process,
sw_set_2d,
sw_end_frame,
sw_create_cube_map,
sw_create_frame_buffer,
sw_bind_framebuffer,

View file

@ -308,6 +308,11 @@ vulkan_draw_transparent (void)
{
}
static void
vulkan_post_process (framebuffer_t *src)
{
}
static void
vulkan_set_2d (int scaled)
{
@ -418,6 +423,12 @@ vulkan_end_frame (void)
vulkan_ctx->curFrame %= vulkan_ctx->frames.size;
}
static framebuffer_t *
vulkan_create_cube_map (int size)
{
Sys_Error ("not implemented");
}
static framebuffer_t *
vulkan_create_frame_buffer (int width, int height)
{
@ -705,9 +716,11 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
vulkan_draw_entities,
vulkan_draw_particles,
vulkan_draw_transparent,
vulkan_post_process,
vulkan_set_2d,
vulkan_end_frame,
vulkan_create_cube_map,
vulkan_create_frame_buffer,
vulkan_bind_framebuffer,