ref_soft: Implement rendermodes, colors, alpha textures/blending

This commit is contained in:
mittorn 2019-03-20 21:44:21 +07:00
parent ae6b460f35
commit f23ecc6895
6 changed files with 205 additions and 31 deletions

View File

@ -376,6 +376,7 @@ void R_AllowFog(qboolean allowed)
void GL_SetRenderMode(int mode)
{
vid.rendermode = mode;
/// TODO: table shading/blending???
/// maybe, setup block drawing function pointers here
}

View File

@ -108,12 +108,12 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1,
{
sv = (skip + v)*(t2-t1)/h + t1;
source = pic->pixels[0] + sv*pic->width + s1;
if (w == s2 - s1)
memcpy (dest, source, w * 2);
else
{
f = 0;
fstep = s2*0x10000/w;
if( w == s2 - s1 )
fstep = 0x10000;
#if 0
for (u=0 ; u<w ; u+=4)
{
dest[u] = source[f>>16];
@ -125,6 +125,37 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1,
dest[u+3] = source[f>>16];
f += fstep;
}
#else
for (u=0 ; u<w ; u++)
{
pixel_t src = source[f>>16];
int alpha = vid.alpha;
if( pic->transparent )
{
alpha &= src >> 16 - 3;
src = src << 3;
}
if( vid.color != COLOR_WHITE )
src = vid.modmap[src & 0xff00|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 1);
if( vid.rendermode == kRenderTransAdd)
{
pixel_t screen = dest[u];
dest[u] = vid.addmap[src & 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0);
}
else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) )
{
pixel_t screen = dest[u];
dest[u] = vid.alphamap[(vid.alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 1);
}
else
dest[u] = src;
f += fstep;
}
#endif
}
}
}
@ -160,7 +191,7 @@ void R_DrawTileClear( int texnum, int x, int y, int w, int h )
image_t *pic;
pixel_t *psrc, *pdest;
//GL_SetRenderMode( kRenderNormal );
GL_SetRenderMode( kRenderNormal );
_TriColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
GL_Bind( XASH_TEXTURE0, texnum );
@ -239,6 +270,7 @@ R_Set2DMode
*/
void R_Set2DMode( qboolean enable )
{
vid.color = COLOR_WHITE;
if( enable )
{
// if( glState.in2DMode )

View File

@ -38,9 +38,103 @@ int tex;
unsigned short *buffer;
#define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x)
void R_InitBlit()
void R_BuildScreenMap()
{
int i;
#ifdef SEPARATE_BLIT
for( i = 0; i < 256; i++ )
{
unsigned int r,g,b;
// 332 to 565
r = ((i >> (8 - 3) )<< 2 ) & MASK(5);
g = ((i >> (8 - 3 - 3)) << 3) & MASK(6);
b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
vid.screen_major[i] = r << (6 + 5) | (g << 5) | b;
// restore minor GBRGBRGB
r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0);
g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0);
b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0);
vid.screen_minor[i] = r << (6 + 5) | (g << 5) | b;
}
#else
for( i = 0; i < 256; i++ )
{
unsigned int r,g,b , major, j;
// 332 to 565
r = ((i >> (8 - 3) )<< 2 ) & MASK(5);
g = ((i >> (8 - 3 - 3)) << 3) & MASK(6);
b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
major = r << (6 + 5) | (g << 5) | b;
for( j = 0; j < 256; j++ )
{
// restore minor GBRGBRGB
r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0);
g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0);
b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0);
vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major;
}
}
#endif
}
void R_BuildBlendMaps()
{
unsigned int r1, g1, b1;
unsigned int r2, g2, b2;
for( r1 = 0; r1 < BIT(3); r1++ )
for( g1 = 0; g1 < BIT(3); g1++ )
for( b1 = 0; b1 < BIT(2); b1++ )
for( r2 = 0; r2 < BIT(3); r2++ )
for( g2 = 0; g2 < BIT(3); g2++ )
for( b2 = 0; b2 < BIT(2); b2++ )
{
unsigned int r, g, b;
unsigned short index1 = r1 << (2 + 3) | g1 << 2 | b1;
unsigned short index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 8;
unsigned int a;
r = r1 + r2;
g = g1 + g2;
b = b1 + b2;
if( r > MASK(2) )
r = MASK(2);
if( g > MASK(2) )
g = MASK(2);
if( b > MASK(1) )
b = MASK(1);
ASSERT(!vid.addmap[index2|index1]);
vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b;
r = r1 * r2 / MASK(2);
g = g1 * g2 / MASK(2);
b = b1 * b2 / MASK(1);
vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b;
for( a = 0; a < 8; a++ )
{
r = r1 * a / 7 + r2 * (7 - a) / 7;
g = g1 * a / 7 + g2 * (7 - a) / 7;
b = b1 * a / 7 + b2 * (7 - a) / 7;
vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b;
}
}
}
void R_InitBlit()
{
LOAD(glBegin);
LOAD(glEnd);
LOAD(glTexCoord2f);
@ -58,7 +152,7 @@ void R_InitBlit()
LOAD(glGetError);
LOAD(glGenTextures);
LOAD(glTexParameteri);
#ifdef GLDEBUG
if( gpGlobals->developer )
{
gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n");
@ -70,25 +164,14 @@ void R_InitBlit()
// enable all the low priority messages
pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true );
#endif
pglGenTextures( 1, &tex );
buffer = Mem_Malloc( r_temppool, 1920*1080*2 );
for( i = 0; i < 256; i++ )
{
unsigned int r,g,b;
// 332 to 565
r = ((i >> (8 - 3) )<< 2 ) & MASK(5);
g = ((i >> (8 - 3 - 3)) << 3) & MASK(6);
b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
vid.screen_major[i] = r << (6 + 5) | (g << 5) | b;
// restore minor GBRGBRGB
r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0);
g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0);
b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0);
vid.screen_minor[i] = r << (6 + 5) | (g << 5) | b;
}
R_BuildScreenMap();
R_BuildBlendMaps();
}
void R_BlitScreen()
@ -99,11 +182,18 @@ void R_BlitScreen()
for( i = 0; i < vid.width * vid.height;i++)
{
#ifdef SEPARATE_BLIT
// need only 1024 bytes table, but slower
// wtf?? maybe some prefetch???
byte major = buf[(i<<1)+1];
byte minor = buf[(i<<1)];
buffer[i] = vid.screen_major[major]|vid.screen_minor[minor];
buffer[i] = vid.screen_major[major] |vid.screen_minor[minor];
#else
buffer[i] = vid.screen[vid.buffer[i]];
#endif
}
pglBindTexture(GL_TEXTURE_2D, tex);
pglViewport( 0, 0, gpGlobals->width, gpGlobals->height );
pglMatrixMode( GL_PROJECTION );
@ -119,6 +209,7 @@ void R_BlitScreen()
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//gEngfuncs.Con_Printf("%d\n",pglGetError());
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer );
//gEngfuncs.Con_Printf("%d\n",pglGetError());
pglBegin( GL_QUADS );
@ -136,4 +227,5 @@ void R_BlitScreen()
pglEnd();
pglDisable( GL_TEXTURE_2D );
gEngfuncs.GL_SwapBuffers();
memset( vid.buffer, 0, vid.width * vid.height * 2 );
}

View File

@ -220,7 +220,7 @@ static void GL_SetTextureFormat( image_t *tex, pixformat_t format, int channelMa
qboolean haveAlpha = ( channelMask & IMAGE_HAS_ALPHA );
Assert( tex != NULL );
tex->transparent = !!( channelMask & IMAGE_HAS_ALPHA );
//tex->transparent = !!( channelMask & IMAGE_HAS_ALPHA );
}
/*
@ -509,16 +509,26 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic )
if( !pic->buffer )
return true;
/// TODO: generate mipmaps
if( tex->flags & TF_HAS_ALPHA )
tex->transparent = true;
tex->pixels[0] = Mem_Calloc( r_temppool, tex->width * tex->height * sizeof(pixel_t) + 64 );
for( i = 0; i < tex->width * tex->height; i++ )
{
unsigned int r, g, b, major, minor;
#if 0
r = pic->buffer[i * 4 + 0] * MASK(5-1) / 255;
g = pic->buffer[i * 4 + 1] * MASK(6-1) / 255;
b = pic->buffer[i * 4 + 2] * MASK(5-1) / 255;
#else
// seems to look better
r = pic->buffer[i * 4 + 0] * BIT(5) / 256;
g = pic->buffer[i * 4 + 1] * BIT(6) / 256;
b = pic->buffer[i * 4 + 2] * BIT(5) / 256;
#endif
// 565 to 332
major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2)));
@ -526,9 +536,14 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic )
minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0);
tex->pixels[0][i] = major << 8 | (minor & 0xFF);
if( tex->transparent )
{
unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3);
tex->pixels[0][i] = (tex->pixels[0][i] >> 3) | alpha;
}
}
/// TODO: generate mipmaps
#if 0

View File

@ -124,13 +124,27 @@ typedef struct vrect_s
struct vrect_s *pnext;
} vrect_t;
#define COLOR_WHITE 0xFFFF
#define SEPARATE_BLIT
typedef struct
{
pixel_t *buffer; // invisible buffer
pixel_t *colormap; // 256 * VID_GRADES size
pixel_t *alphamap; // 256 * 256 translucency map
//pixel_t *alphamap; // 256 * 256 translucency map
#ifdef SEPARATE_BLIT
pixel_t screen_minor[256];
pixel_t screen_major[256];
#else
pixel_t screen[256*256];
#endif
byte addmap[256*256];
byte modmap[256*256];
pixel_t alphamap[8*256*256];
pixel_t color;
byte alpha;
// maybe compute colormask for minor byte?
int rendermode;
int rowbytes; // may be > width if displayed in a window
// can be negative for stupid dibs
int width;

View File

@ -39,7 +39,7 @@ set rendermode
*/
void TriRenderMode( int mode )
{
ds.renderMode = mode;
ds.renderMode = vid.rendermode = mode;
#if 0
switch( mode )
{
@ -130,9 +130,29 @@ _TriColor4f
=============
*/
void _TriColor4f( float r, float g, float b, float a )
void _TriColor4f( float rr, float gg, float bb, float aa )
{
//pglColor4f( r, g, b, a );
unsigned short r,g,b;
if( rr == 1 && gg == 1 && bb == 1 )
{
vid.color = COLOR_WHITE;
return;
}
r = rr * 31, g = gg * 63, b = bb * 31;
vid.alpha = aa * 7;
if( vid.alpha > 7 )
vid.alpha = 7;
unsigned int major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2)));
// save minor GBRGBRGB
unsigned int minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0);
vid.color = major << 8 | (minor & 0xFF);
}
/*
@ -148,7 +168,7 @@ void TriColor4ub( byte r, byte g, byte b, byte a )
ds.triRGBA[2] = b * (1.0f / 255.0f);
ds.triRGBA[3] = a * (1.0f / 255.0f);
_TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f );
_TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], ds.triRGBA[3] ); //1.0f );
}
/*