double ApplyLUT2LUMA(FIBITMAP *src, FIBITMAP *dst, char * LUT, int threadcount) { _mark(); unsigned spitch = FreeImage_GetPitch(src); unsigned dpitch = FreeImage_GetPitch(dst); unsigned w = FreeImage_GetWidth(src); unsigned h = FreeImage_GetHeight(src); BYTE * srcbits = FreeImage_GetBits(src); BYTE * dstbits = FreeImage_GetBits(dst); BYTE LUT8[256]; WORD LUT16[65536]; int bpp = FreeImage_GetBPP(src); if (bpp == 24) { for (int x=0; x<256; x++) { LUT8[x] = ((BYTE *) LUT)[x]; } #pragma omp parallel for num_threads(threadcount) for(unsigned y = 0; y < h; y++) { for(unsigned x = 0; x < w; x++) { BYTE * bdstpix = (BYTE *) (dstbits + dpitch*y + 3*x); BYTE * pixel = (BYTE *) (srcbits + spitch*y + 3*x); int lumaorig = (int) LUMA(pixel[FI_RGBA_RED],pixel[FI_RGBA_GREEN],pixel[FI_RGBA_BLUE]); int diff = lumaorig - LUT8[lumaorig]; bdstpix[FI_RGBA_RED] = std::min(std::max(bdstpix[FI_RGBA_RED] + diff,0),255); bdstpix[FI_RGBA_GREEN] = std::min(std::max(bdstpix[FI_RGBA_GREEN] + diff,0),255); bdstpix[FI_RGBA_BLUE] = std::min(std::max(bdstpix[FI_RGBA_BLUE] + diff,0),255); } } } if (bpp == 48) { for (int x=0; x<65536; x++) { LUT16[x] = ((WORD *)LUT)[x]; } #pragma omp parallel for num_threads(threadcount) for(unsigned y = 0; y < h-1; y++) { for(unsigned x = 0; x < w-1; x++) { FIRGB16 * wdstpix = (FIRGB16 *) (dstbits + dpitch*y + 6*x); FIRGB16 * pixel = (FIRGB16 *) (srcbits + spitch*y + 6*x); int lumaorig = (int) LUMA(pixel->red,pixel->green,pixel->blue); int diff = lumaorig - LUT16[lumaorig]; wdstpix->red = std::min(std::max(pixel->red + diff,0),65535); wdstpix->green = std::min(std::max(pixel->green + diff,0),65535); wdstpix->blue = std::min(std::max(pixel->blue + diff,0),65535); } } } return _duration(); }
static void set_rgb16_lum_from_rgb16(const uint16_t topr, const uint16_t topg, const uint16_t topb, uint16_t *botr, uint16_t *botg, uint16_t *botb) { // Spec: SetLum() // Colours potentially can go out of band to both sides, hence the // temporary representation inflation. const uint16_t botlum = LUMA(*botr, *botg, *botb) / (1<<15); const uint16_t toplum = LUMA(topr, topg, topb) / (1<<15); const int16_t diff = botlum - toplum; int32_t r = topr + diff; int32_t g = topg + diff; int32_t b = topb + diff; // Spec: ClipColor() // Clip out of band values int32_t lum = LUMA(r, g, b) / (1<<15); int32_t cmin = MIN3(r, g, b); int32_t cmax = MAX3(r, g, b); if (cmin < 0) { r = lum + (((r - lum) * lum) / (lum - cmin)); g = lum + (((g - lum) * lum) / (lum - cmin)); b = lum + (((b - lum) * lum) / (lum - cmin)); } if (cmax > (1<<15)) { r = lum + (((r - lum) * ((1<<15)-lum)) / (cmax - lum)); g = lum + (((g - lum) * ((1<<15)-lum)) / (cmax - lum)); b = lum + (((b - lum) * ((1<<15)-lum)) / (cmax - lum)); } #ifdef HEAVY_DEBUG assert((0 <= r) && (r <= (1<<15))); assert((0 <= g) && (g <= (1<<15))); assert((0 <= b) && (b <= (1<<15))); #endif *botr = r; *botg = g; *botb = b; }
/* =============== ComputeColors =============== */ static void ComputeColors( shaderStage_t *pStage ) { int i; // // rgbGen // switch ( pStage->rgbGen ) { case CGEN_IDENTITY: Com_Memset( tess.svars.colors, 0xff, tess.numVertexes * 4 ); break; default: case CGEN_IDENTITY_LIGHTING: Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); break; case CGEN_LIGHTING_DIFFUSE: RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); break; case CGEN_EXACT_VERTEX: Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); break; case CGEN_CONST: for ( i = 0; i < tess.numVertexes; i++ ) { *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; } break; case CGEN_VERTEX: if ( tr.identityLight == 1 ) { Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); } else { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight; tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight; tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight; tess.svars.colors[i][3] = tess.vertexColors[i][3]; } } break; case CGEN_ONE_MINUS_VERTEX: if ( tr.identityLight == 1 ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0]; tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1]; tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2]; } } else { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight; tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight; tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight; } } break; case CGEN_FOG: { fog_t *fog; fog = tr.world->fogs + tess.fogNum; for ( i = 0; i < tess.numVertexes; i++ ) { * ( int * )&tess.svars.colors[i] = fog->colorInt; } } break; case CGEN_WAVEFORM: RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors ); break; case CGEN_ENTITY: RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors ); break; case CGEN_ONE_MINUS_ENTITY: RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; } // // alphaGen // switch ( pStage->alphaGen ) { case AGEN_SKIP: break; case AGEN_IDENTITY: if ( pStage->rgbGen != CGEN_IDENTITY ) { if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) || pStage->rgbGen != CGEN_VERTEX ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = 0xff; } } } break; case AGEN_CONST: if ( pStage->rgbGen != CGEN_CONST ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = pStage->constantColor[3]; } } break; case AGEN_WAVEFORM: RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors ); break; case AGEN_LIGHTING_SPECULAR: RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors ); break; case AGEN_ENTITY: RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors ); break; case AGEN_ONE_MINUS_ENTITY: RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; case AGEN_VERTEX: if ( pStage->rgbGen != CGEN_VERTEX ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = tess.vertexColors[i][3]; } } break; case AGEN_ONE_MINUS_VERTEX: for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3]; } break; case AGEN_PORTAL: { unsigned char alpha; for ( i = 0; i < tess.numVertexes; i++ ) { float len; vec3_t v; VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v ); len = VectorLength( v ); len /= tess.shader->portalRange; if ( len < 0 ) { alpha = 0; } else if ( len > 1 ) { alpha = 0xff; } else { alpha = len * 0xff; } tess.svars.colors[i][3] = alpha; } } break; } // // fog adjustment for colors to fade out as fog increases // if ( tess.fogNum ) { switch ( pStage->adjustColorsForFog ) { case ACFF_MODULATE_RGB: RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_MODULATE_ALPHA: RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_MODULATE_RGBA: RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_NONE: break; } } // if in greyscale rendering mode turn all color values into greyscale. if(r_greyscale->integer) { int scale; for(i = 0; i < tess.numVertexes; i++) { scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; } } else if(r_greyscale->value) { float scale; for(i = 0; i < tess.numVertexes; i++) { scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); tess.svars.colors[i][0] = LERP(tess.svars.colors[i][0], scale, r_greyscale->value); tess.svars.colors[i][1] = LERP(tess.svars.colors[i][1], scale, r_greyscale->value); tess.svars.colors[i][2] = LERP(tess.svars.colors[i][2], scale, r_greyscale->value); } } }
static void ProjectDlightTexture_scalar( void ) { int i, l; vec3_t origin; float *texCoords; byte *colors; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; vec3_t floatColor; float modulate = 0.0f; if ( !backEnd.refdef.num_dlights ) { return; } for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } texCoords = texCoordsArray[0]; colors = colorArray[0]; dl = &backEnd.refdef.dlights[l]; VectorCopy( dl->transformed, origin ); radius = dl->radius; scale = 1.0f / radius; if(r_greyscale->integer) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } else if(r_greyscale->value) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); } else { floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; } for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { int clip = 0; vec3_t dist; VectorSubtract( origin, tess.xyz[i], dist ); backEnd.pc.c_dlightVertexes++; texCoords[0] = 0.5f + dist[0] * scale; texCoords[1] = 0.5f + dist[1] * scale; if( !r_dlightBacks->integer && // dist . tess.normal[i] ( dist[0] * tess.normal[i][0] + dist[1] * tess.normal[i][1] + dist[2] * tess.normal[i][2] ) < 0.0f ) { clip = 63; } else { if ( texCoords[0] < 0.0f ) { clip |= 1; } else if ( texCoords[0] > 1.0f ) { clip |= 2; } if ( texCoords[1] < 0.0f ) { clip |= 4; } else if ( texCoords[1] > 1.0f ) { clip |= 8; } texCoords[0] = texCoords[0]; texCoords[1] = texCoords[1]; // modulate the strength based on the height and color if ( dist[2] > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist[2] < -radius ) { clip |= 32; modulate = 0.0f; } else { dist[2] = Q_fabs(dist[2]); if ( dist[2] < radius * 0.5f ) { modulate = 1.0f; } else { modulate = 2.0f * (radius - dist[2]) * scale; } } } clipBits[i] = clip; colors[0] = ri.ftol(floatColor[0] * modulate); colors[1] = ri.ftol(floatColor[1] * modulate); colors[2] = ri.ftol(floatColor[2] * modulate); colors[3] = 255; } // build a list of triangles that need light numIndexes = 0; for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { int a, b, c; a = tess.indexes[i]; b = tess.indexes[i+1]; c = tess.indexes[i+2]; if ( clipBits[a] & clipBits[b] & clipBits[c] ) { continue; // not lighted } hitIndexes[numIndexes] = a; hitIndexes[numIndexes+1] = b; hitIndexes[numIndexes+2] = c; numIndexes += 3; } if ( !numIndexes ) { continue; } qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); GL_Bind( tr.dlightImage ); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->additive ) { GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } R_DrawElements( numIndexes, hitIndexes ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } }
static void ProjectDlightTexture_altivec( void ) { int i, l; vec_t origin0, origin1, origin2; float texCoords0, texCoords1; vector float floatColorVec0, floatColorVec1; vector float modulateVec, colorVec, zero; vector short colorShort; vector signed int colorInt; vector unsigned char floatColorVecPerm, modulatePerm, colorChar; vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff); float *texCoords; byte *colors; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; unsigned hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; vec3_t floatColor; float modulate = 0.0f; if ( !backEnd.refdef.num_dlights ) { return; } // There has to be a better way to do this so that floatColor // and/or modulate are already 16-byte aligned. floatColorVecPerm = vec_lvsl(0,(float *)floatColor); modulatePerm = vec_lvsl(0,(float *)&modulate); modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0); zero = (vector float)vec_splat_s8(0); for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } texCoords = texCoordsArray[0]; colors = colorArray[0]; dl = &backEnd.refdef.dlights[l]; origin0 = dl->transformed[0]; origin1 = dl->transformed[1]; origin2 = dl->transformed[2]; radius = dl->radius; scale = 1.0f / radius; if(r_greyscale->integer) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } else if(r_greyscale->value) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); } else { floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; } floatColorVec0 = vec_ld(0, floatColor); floatColorVec1 = vec_ld(11, floatColor); floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm); for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { int clip = 0; vec_t dist0, dist1, dist2; dist0 = origin0 - tess.xyz[i][0]; dist1 = origin1 - tess.xyz[i][1]; dist2 = origin2 - tess.xyz[i][2]; backEnd.pc.c_dlightVertexes++; texCoords0 = 0.5f + dist0 * scale; texCoords1 = 0.5f + dist1 * scale; if( !r_dlightBacks->integer && // dist . tess.normal[i] ( dist0 * tess.normal[i][0] + dist1 * tess.normal[i][1] + dist2 * tess.normal[i][2] ) < 0.0f ) { clip = 63; } else { if ( texCoords0 < 0.0f ) { clip |= 1; } else if ( texCoords0 > 1.0f ) { clip |= 2; } if ( texCoords1 < 0.0f ) { clip |= 4; } else if ( texCoords1 > 1.0f ) { clip |= 8; } texCoords[0] = texCoords0; texCoords[1] = texCoords1; // modulate the strength based on the height and color if ( dist2 > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist2 < -radius ) { clip |= 32; modulate = 0.0f; } else { dist2 = Q_fabs(dist2); if ( dist2 < radius * 0.5f ) { modulate = 1.0f; } else { modulate = 2.0f * (radius - dist2) * scale; } } } clipBits[i] = clip; modulateVec = vec_ld(0,(float *)&modulate); modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm); colorVec = vec_madd(floatColorVec0,modulateVec,zero); colorInt = vec_cts(colorVec,0); // RGBx colorShort = vec_pack(colorInt,colorInt); // RGBxRGBx colorChar = vec_packsu(colorShort,colorShort); // RGBxRGBxRGBxRGBx colorChar = vec_sel(colorChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255 vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors); // store color } // build a list of triangles that need light numIndexes = 0; for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { int a, b, c; a = tess.indexes[i]; b = tess.indexes[i+1]; c = tess.indexes[i+2]; if ( clipBits[a] & clipBits[b] & clipBits[c] ) { continue; // not lighted } hitIndexes[numIndexes] = a; hitIndexes[numIndexes+1] = b; hitIndexes[numIndexes+2] = c; numIndexes += 3; } if ( !numIndexes ) { continue; } qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); GL_Bind( tr.dlightImage ); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->additive ) { GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } R_DrawElements( numIndexes, hitIndexes ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } }
/* =============== ComputeColors =============== */ static void ComputeColors( shaderStage_t *pStage ) { int i; // // rgbGen // switch ( pStage->rgbGen ) { case CGEN_IDENTITY: memset( tess.svars.colors, 0xff, tess.numVertexes * 4 ); break; default: case CGEN_IDENTITY_LIGHTING: memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); break; case CGEN_LIGHTING_DIFFUSE: RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); break; case CGEN_EXACT_VERTEX: memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); break; case CGEN_CONST: for ( i = 0; i < tess.numVertexes; i++ ) { *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; } break; case CGEN_VERTEX: if ( tr.identityLight == 1 ) { memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); } else { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight; tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight; tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight; tess.svars.colors[i][3] = tess.vertexColors[i][3]; } } break; case CGEN_ONE_MINUS_VERTEX: if ( tr.identityLight == 1 ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0]; tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1]; tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2]; } } else { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight; tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight; tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight; } } break; case CGEN_FOG: { fog_t *fog; fog = tr.world->fogs + tess.fogNum; for ( i = 0; i < tess.numVertexes; i++ ) { *( int * )&tess.svars.colors[i] = fog->colorInt; } } break; case CGEN_WAVEFORM: RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors ); break; case CGEN_ENTITY: RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors ); break; case CGEN_ONE_MINUS_ENTITY: RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; } // // alphaGen // switch ( pStage->alphaGen ) { case AGEN_SKIP: break; case AGEN_IDENTITY: if ( pStage->rgbGen != CGEN_IDENTITY ) { if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) || pStage->rgbGen != CGEN_VERTEX ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = 0xff; } } } break; case AGEN_CONST: if ( pStage->rgbGen != CGEN_CONST ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = pStage->constantColor[3]; } } break; case AGEN_WAVEFORM: RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors ); break; case AGEN_LIGHTING_SPECULAR: RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors ); break; case AGEN_ENTITY: RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors ); break; case AGEN_ONE_MINUS_ENTITY: RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; // Ridah case AGEN_NORMALZFADE: { float alpha, range, lowest, highest, dot; vec3_t worldUp; qboolean zombieEffect = qfalse; if ( VectorCompare( backEnd.currentEntity->e.fireRiseDir, vec3_origin ) ) { VectorSet( backEnd.currentEntity->e.fireRiseDir, 0, 0, 1 ); } if ( backEnd.currentEntity->e.hModel ) { // world surfaces dont have an axis VectorRotate( backEnd.currentEntity->e.fireRiseDir, backEnd.currentEntity->e.axis, worldUp ); } else { VectorCopy( backEnd.currentEntity->e.fireRiseDir, worldUp ); } lowest = pStage->zFadeBounds[0]; if ( lowest == -1000 ) { // use entity alpha lowest = backEnd.currentEntity->e.shaderTime; zombieEffect = qtrue; } highest = pStage->zFadeBounds[1]; if ( highest == -1000 ) { // use entity alpha highest = backEnd.currentEntity->e.shaderTime; zombieEffect = qtrue; } range = highest - lowest; for ( i = 0; i < tess.numVertexes; i++ ) { dot = DotProduct( tess.normal[i], worldUp ); // special handling for Zombie fade effect if ( zombieEffect ) { alpha = (float)backEnd.currentEntity->e.shaderRGBA[3] * ( dot + 1.0 ) / 2.0; alpha += ( 2.0 * (float)backEnd.currentEntity->e.shaderRGBA[3] ) * ( 1.0 - ( dot + 1.0 ) / 2.0 ); if ( alpha > 255.0 ) { alpha = 255.0; } else if ( alpha < 0.0 ) { alpha = 0.0; } tess.svars.colors[i][3] = (byte)( alpha ); continue; } if ( dot < highest ) { if ( dot > lowest ) { if ( dot < lowest + range / 2 ) { alpha = ( (float)pStage->constantColor[3] * ( ( dot - lowest ) / ( range / 2 ) ) ); } else { alpha = ( (float)pStage->constantColor[3] * ( 1.0 - ( ( dot - lowest - range / 2 ) / ( range / 2 ) ) ) ); } if ( alpha > 255.0 ) { alpha = 255.0; } else if ( alpha < 0.0 ) { alpha = 0.0; } // finally, scale according to the entity's alpha if ( backEnd.currentEntity->e.hModel ) { alpha *= (float)backEnd.currentEntity->e.shaderRGBA[3] / 255.0; } tess.svars.colors[i][3] = (byte)( alpha ); } else { tess.svars.colors[i][3] = 0; } } else { tess.svars.colors[i][3] = 0; } } } break; // done. case AGEN_VERTEX: if ( pStage->rgbGen != CGEN_VERTEX ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = tess.vertexColors[i][3]; } } break; case AGEN_ONE_MINUS_VERTEX: for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3]; } break; case AGEN_PORTAL: { unsigned char alpha; for ( i = 0; i < tess.numVertexes; i++ ) { float len; vec3_t v; VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v ); len = VectorLength( v ); len /= tess.shader->portalRange; if ( len < 0 ) { alpha = 0; } else if ( len > 1 ) { alpha = 0xff; } else { alpha = len * 0xff; } tess.svars.colors[i][3] = alpha; } } break; } // // fog adjustment for colors to fade out as fog increases // if ( tess.fogNum ) { switch ( pStage->adjustColorsForFog ) { case ACFF_MODULATE_RGB: RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_MODULATE_ALPHA: RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_MODULATE_RGBA: RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_NONE: break; } } // if in greyscale rendering mode turn all color values into greyscale. if(r_greyscale->integer) { int scale; for(i = 0; i < tess.numVertexes; i++) { scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; } } else if(r_greyscale->value) { float scale; for(i = 0; i < tess.numVertexes; i++) { scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); tess.svars.colors[i][0] = LERP(tess.svars.colors[i][0], scale, r_greyscale->value); tess.svars.colors[i][1] = LERP(tess.svars.colors[i][1], scale, r_greyscale->value); tess.svars.colors[i][2] = LERP(tess.svars.colors[i][2], scale, r_greyscale->value); } } }
void setupFilterPrimitives_c(EncoderPrimitives& p) { LUMA(4, 4); LUMA(8, 8); CHROMA_420(4, 4); LUMA(4, 8); CHROMA_420(2, 4); LUMA(8, 4); CHROMA_420(4, 2); LUMA(16, 16); CHROMA_420(8, 8); LUMA(16, 8); CHROMA_420(8, 4); LUMA(8, 16); CHROMA_420(4, 8); LUMA(16, 12); CHROMA_420(8, 6); LUMA(12, 16); CHROMA_420(6, 8); LUMA(16, 4); CHROMA_420(8, 2); LUMA(4, 16); CHROMA_420(2, 8); LUMA(32, 32); CHROMA_420(16, 16); LUMA(32, 16); CHROMA_420(16, 8); LUMA(16, 32); CHROMA_420(8, 16); LUMA(32, 24); CHROMA_420(16, 12); LUMA(24, 32); CHROMA_420(12, 16); LUMA(32, 8); CHROMA_420(16, 4); LUMA(8, 32); CHROMA_420(4, 16); LUMA(64, 64); CHROMA_420(32, 32); LUMA(64, 32); CHROMA_420(32, 16); LUMA(32, 64); CHROMA_420(16, 32); LUMA(64, 48); CHROMA_420(32, 24); LUMA(48, 64); CHROMA_420(24, 32); LUMA(64, 16); CHROMA_420(32, 8); LUMA(16, 64); CHROMA_420(8, 32); CHROMA_422(4, 8); CHROMA_422(4, 4); CHROMA_422(2, 4); CHROMA_422(2, 8); CHROMA_422(8, 16); CHROMA_422(8, 8); CHROMA_422(4, 16); CHROMA_422(8, 12); CHROMA_422(6, 16); CHROMA_422(8, 4); CHROMA_422(2, 16); CHROMA_422(16, 32); CHROMA_422(16, 16); CHROMA_422(8, 32); CHROMA_422(16, 24); CHROMA_422(12, 32); CHROMA_422(16, 8); CHROMA_422(4, 32); CHROMA_422(32, 64); CHROMA_422(32, 32); CHROMA_422(16, 64); CHROMA_422(32, 48); CHROMA_422(24, 64); CHROMA_422(32, 16); CHROMA_422(8, 64); CHROMA_444(4, 4); CHROMA_444(8, 8); CHROMA_444(4, 8); CHROMA_444(8, 4); CHROMA_444(16, 16); CHROMA_444(16, 8); CHROMA_444(8, 16); CHROMA_444(16, 12); CHROMA_444(12, 16); CHROMA_444(16, 4); CHROMA_444(4, 16); CHROMA_444(32, 32); CHROMA_444(32, 16); CHROMA_444(16, 32); CHROMA_444(32, 24); CHROMA_444(24, 32); CHROMA_444(32, 8); CHROMA_444(8, 32); CHROMA_444(64, 64); CHROMA_444(64, 32); CHROMA_444(32, 64); CHROMA_444(64, 48); CHROMA_444(48, 64); CHROMA_444(64, 16); CHROMA_444(16, 64); p.extendRowBorder = extendCURowColBorder; }
void Setup_C_IPFilterPrimitives(EncoderPrimitives& p) { LUMA(4, 4); LUMA(8, 8); CHROMA_420(4, 4); LUMA(4, 8); CHROMA_420(2, 4); LUMA(8, 4); CHROMA_420(4, 2); LUMA(16, 16); CHROMA_420(8, 8); LUMA(16, 8); CHROMA_420(8, 4); LUMA(8, 16); CHROMA_420(4, 8); LUMA(16, 12); CHROMA_420(8, 6); LUMA(12, 16); CHROMA_420(6, 8); LUMA(16, 4); CHROMA_420(8, 2); LUMA(4, 16); CHROMA_420(2, 8); LUMA(32, 32); CHROMA_420(16, 16); LUMA(32, 16); CHROMA_420(16, 8); LUMA(16, 32); CHROMA_420(8, 16); LUMA(32, 24); CHROMA_420(16, 12); LUMA(24, 32); CHROMA_420(12, 16); LUMA(32, 8); CHROMA_420(16, 4); LUMA(8, 32); CHROMA_420(4, 16); LUMA(64, 64); CHROMA_420(32, 32); LUMA(64, 32); CHROMA_420(32, 16); LUMA(32, 64); CHROMA_420(16, 32); LUMA(64, 48); CHROMA_420(32, 24); LUMA(48, 64); CHROMA_420(24, 32); LUMA(64, 16); CHROMA_420(32, 8); LUMA(16, 64); CHROMA_420(8, 32); CHROMA_444(4, 4); CHROMA_444(8, 8); CHROMA_444(4, 8); CHROMA_444(8, 4); CHROMA_444(16, 16); CHROMA_444(16, 8); CHROMA_444(8, 16); CHROMA_444(16, 12); CHROMA_444(12, 16); CHROMA_444(16, 4); CHROMA_444(4, 16); CHROMA_444(32, 32); CHROMA_444(32, 16); CHROMA_444(16, 32); CHROMA_444(32, 24); CHROMA_444(24, 32); CHROMA_444(32, 8); CHROMA_444(8, 32); CHROMA_444(64, 64); CHROMA_444(64, 32); CHROMA_444(32, 64); CHROMA_444(64, 48); CHROMA_444(48, 64); CHROMA_444(64, 16); CHROMA_444(16, 64); p.luma_p2s = filterConvertPelToShort_c<MAX_CU_SIZE>; p.chroma_p2s[X265_CSP_I444] = filterConvertPelToShort_c<MAX_CU_SIZE>; p.chroma_p2s[X265_CSP_I420] = filterConvertPelToShort_c<MAX_CU_SIZE / 2>; p.extendRowBorder = extendCURowColBorder; }
static void ProjectDlightTexture_scalar( void ) { int i, l; vec3_t origin; float *texCoords; byte *colors; int *intColors; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; float radiusInverseCubed; float intensity, remainder; vec3_t floatColor; float modulate = 0.0f; qboolean vertexLight; if ( !backEnd.refdef.num_dlights ) { return; } for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } // clear colors Com_Memset( colorArray, 0, sizeof( colorArray ) ); texCoords = texCoordsArray[0]; colors = colorArray[0]; dl = &backEnd.refdef.dlights[l]; VectorCopy( dl->transformed, origin ); radius = dl->radius; scale = 1.0f / radius; radiusInverseCubed = dl->radiusInverseCubed; intensity = dl->intensity; vertexLight = ( ( dl->flags & REF_DIRECTED_DLIGHT ) || ( dl->flags & REF_VERTEX_DLIGHT ) ); // directional lights have max intensity and washout remainder intensity if ( dl->flags & REF_DIRECTED_DLIGHT ) { remainder = intensity * 0.125; } else { remainder = 0.0f; } if(r_greyscale->integer) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } else if(r_greyscale->value) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); } else { floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; } for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { int clip = 0; vec3_t dist; VectorSubtract( origin, tess.xyz[i], dist ); backEnd.pc.c_dlightVertexes++; // directional dlight, origin is a directional normal if ( dl->flags & REF_DIRECTED_DLIGHT ) { // twosided surfaces use absolute value of the calculated lighting modulate = intensity * DotProduct( dl->origin, tess.normal[ i ] ); if ( tess.shader->cullType == CT_TWO_SIDED ) { modulate = fabs( modulate ); } modulate += remainder; } // spherical vertex lit dlight else if ( dl->flags & REF_VERTEX_DLIGHT ) { vec3_t dir; dir[ 0 ] = radius - fabs( dist[ 0 ] ); if ( dir[ 0 ] <= 0.0f ) { continue; } dir[ 1 ] = radius - fabs( dist[ 1 ] ); if ( dir[ 1 ] <= 0.0f ) { continue; } dir[ 2 ] = radius - fabs( dist[ 2 ] ); if ( dir[ 2 ] <= 0.0f ) { continue; } modulate = intensity * dir[ 0 ] * dir[ 1 ] * dir[ 2 ] * radiusInverseCubed; } // vertical cylinder dlight else { texCoords[0] = 0.5f + dist[0] * scale; texCoords[1] = 0.5f + dist[1] * scale; if( !r_dlightBacks->integer && // dist . tess.normal[i] ( dist[0] * tess.normal[i][0] + dist[1] * tess.normal[i][1] + dist[2] * tess.normal[i][2] ) < 0.0f ) { clip = 63; } else { if ( texCoords[0] < 0.0f ) { clip |= 1; } else if ( texCoords[0] > 1.0f ) { clip |= 2; } if ( texCoords[1] < 0.0f ) { clip |= 4; } else if ( texCoords[1] > 1.0f ) { clip |= 8; } texCoords[0] = texCoords[0]; texCoords[1] = texCoords[1]; // modulate the strength based on the height and color if ( dist[2] > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist[2] < -radius ) { clip |= 32; modulate = 0.0f; } else { dist[2] = Q_fabs(dist[2]); if ( dist[2] < radius * 0.5f ) { modulate = intensity; } else { modulate = intensity * 2.0f * (radius - dist[2]) * scale; } } } } // optimizations if ( vertexLight && modulate < ( 1.0f / 128.0f ) ) { continue; } else if ( modulate > 1.0f ) { modulate = 1.0f; } clipBits[i] = clip; colors[0] = Com_Clamp( 0, 255, ri.ftol(floatColor[0] * modulate) ); colors[1] = Com_Clamp( 0, 255, ri.ftol(floatColor[1] * modulate) ); colors[2] = Com_Clamp( 0, 255, ri.ftol(floatColor[2] * modulate) ); colors[3] = 255; } // build a list of triangles that need light intColors = (int*) colorArray; numIndexes = 0; for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { int a, b, c; a = tess.indexes[i]; b = tess.indexes[i+1]; c = tess.indexes[i+2]; if ( vertexLight ) { if ( !( intColors[ a ] | intColors[ b ] | intColors[ c ] ) ) { continue; } } else { if ( clipBits[a] & clipBits[b] & clipBits[c] ) { continue; // not lighted } } hitIndexes[numIndexes] = a; hitIndexes[numIndexes+1] = b; hitIndexes[numIndexes+2] = c; numIndexes += 3; } if ( !numIndexes ) { continue; } if ( !vertexLight ) { qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); } else { qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); } qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); if ( dl->dlshader ) { shader_t *dls = dl->dlshader; for ( i = 0; i < dls->numUnfoggedPasses; i++ ) { shaderStage_t *stage = dls->stages[i]; R_BindAnimatedImage( &dls->stages[i]->bundle[0] ); GL_State( stage->stateBits | GLS_DEPTHFUNC_EQUAL ); R_DrawElements( numIndexes, hitIndexes ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } } else { R_FogOff(); if ( !vertexLight ) { GL_Bind( tr.dlightImage ); } else { GL_Bind( tr.whiteImage ); } // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->flags & REF_ADDITIVE_DLIGHT ) { GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } R_DrawElements( numIndexes, hitIndexes ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; RB_FogOn(); } } }
static void ProjectDlightTexture_altivec( void ) { int i, l; vec_t origin0, origin1, origin2; float texCoords0, texCoords1; vector float floatColorVec0, floatColorVec1; vector float modulateVec, colorVec, zero; vector short colorShort; vector signed int colorInt; vector unsigned char floatColorVecPerm, modulatePerm, colorChar; vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff); float *texCoords; byte *colors; int *intColors; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; float radiusInverseCubed; float intensity, remainder; vec3_t floatColor; float modulate = 0.0f; qboolean vertexLight; if ( !backEnd.refdef.num_dlights ) { return; } // There has to be a better way to do this so that floatColor // and/or modulate are already 16-byte aligned. floatColorVecPerm = vec_lvsl(0,(float *)floatColor); modulatePerm = vec_lvsl(0,(float *)&modulate); modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0); zero = (vector float)vec_splat_s8(0); for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } // clear colors Com_Memset( colorArray, 0, sizeof( colorArray ) ); texCoords = texCoordsArray[0]; colors = colorArray[0]; dl = &backEnd.refdef.dlights[l]; origin0 = dl->transformed[0]; origin1 = dl->transformed[1]; origin2 = dl->transformed[2]; radius = dl->radius; scale = 1.0f / radius; radiusInverseCubed = dl->radiusInverseCubed; intensity = dl->intensity; vertexLight = ( ( dl->flags & REF_DIRECTED_DLIGHT ) || ( dl->flags & REF_VERTEX_DLIGHT ) ); // directional lights have max intensity and washout remainder intensity if ( dl->flags & REF_DIRECTED_DLIGHT ) { remainder = intensity * 0.125; } else { remainder = 0.0f; } if(r_greyscale->integer) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } else if(r_greyscale->value) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); } else { floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; } floatColorVec0 = vec_ld(0, floatColor); floatColorVec1 = vec_ld(11, floatColor); floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm); for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { int clip = 0; vec_t dist0, dist1, dist2; dist0 = origin0 - tess.xyz[i][0]; dist1 = origin1 - tess.xyz[i][1]; dist2 = origin2 - tess.xyz[i][2]; backEnd.pc.c_dlightVertexes++; // directional dlight, origin is a directional normal if ( dl->flags & REF_DIRECTED_DLIGHT ) { // twosided surfaces use absolute value of the calculated lighting modulate = intensity * DotProduct( dl->origin, tess.normal[ i ] ); if ( tess.shader->cullType == CT_TWO_SIDED ) { modulate = fabs( modulate ); } modulate += remainder; } // spherical vertex lit dlight else if ( dl->flags & REF_VERTEX_DLIGHT ) { vec3_t dir; dir[ 0 ] = radius - fabs( dist0 ); if ( dir[ 0 ] <= 0.0f ) { continue; } dir[ 1 ] = radius - fabs( dist1 ); if ( dir[ 1 ] <= 0.0f ) { continue; } dir[ 2 ] = radius - fabs( dist2 ); if ( dir[ 2 ] <= 0.0f ) { continue; } modulate = intensity * dir[ 0 ] * dir[ 1 ] * dir[ 2 ] * radiusInverseCubed; } // vertical cylinder dlight else { texCoords0 = 0.5f + dist0 * scale; texCoords1 = 0.5f + dist1 * scale; if( !r_dlightBacks->integer && // dist . tess.normal[i] ( dist0 * tess.normal[i][0] + dist1 * tess.normal[i][1] + dist2 * tess.normal[i][2] ) < 0.0f ) { clip = 63; } else { if ( texCoords0 < 0.0f ) { clip |= 1; } else if ( texCoords0 > 1.0f ) { clip |= 2; } if ( texCoords1 < 0.0f ) { clip |= 4; } else if ( texCoords1 > 1.0f ) { clip |= 8; } texCoords[0] = texCoords0; texCoords[1] = texCoords1; // modulate the strength based on the height and color if ( dist2 > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist2 < -radius ) { clip |= 32; modulate = 0.0f; } else { dist2 = Q_fabs(dist2); if ( dist2 < radius * 0.5f ) { modulate = intensity; } else { modulate = intensity * 2.0f * (radius - dist2) * scale; } } } } clipBits[i] = clip; // optimizations if ( vertexLight && modulate < ( 1.0f / 128.0f ) ) { continue; } else if ( modulate > 1.0f ) { modulate = 1.0f; } // ZTM: FIXME: should probably clamp to 0-255 range before converting to char, // but I don't know how to do altvec stuff or if it's even used anymore modulateVec = vec_ld(0,(float *)&modulate); modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm); colorVec = vec_madd(floatColorVec0,modulateVec,zero); colorInt = vec_cts(colorVec,0); // RGBx colorShort = vec_pack(colorInt,colorInt); // RGBxRGBx colorChar = vec_packsu(colorShort,colorShort); // RGBxRGBxRGBxRGBx colorChar = vec_sel(colorChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255 vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors); // store color } // build a list of triangles that need light intColors = (int*) colorArray; numIndexes = 0; for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { int a, b, c; a = tess.indexes[i]; b = tess.indexes[i+1]; c = tess.indexes[i+2]; if ( vertexLight ) { if ( !( intColors[ a ] | intColors[ b ] | intColors[ c ] ) ) { continue; } } else { if ( clipBits[a] & clipBits[b] & clipBits[c] ) { continue; // not lighted } } hitIndexes[numIndexes] = a; hitIndexes[numIndexes+1] = b; hitIndexes[numIndexes+2] = c; numIndexes += 3; } if ( !numIndexes ) { continue; } if ( !vertexLight ) { qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); } else { qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); } qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); if ( dl->dlshader ) { shader_t *dls = dl->dlshader; for ( i = 0; i < dls->numUnfoggedPasses; i++ ) { shaderStage_t *stage = dls->stages[i]; R_BindAnimatedImage( &dls->stages[i]->bundle[0] ); GL_State( stage->stateBits | GLS_DEPTHFUNC_EQUAL ); R_DrawElements( numIndexes, hitIndexes ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } } else { R_FogOff(); if ( !vertexLight ) { GL_Bind( tr.dlightImage ); } else { GL_Bind( tr.whiteImage ); } // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->flags & REF_ADDITIVE_DLIGHT ) { GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } R_DrawElements( numIndexes, hitIndexes ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; RB_FogOn(); } } }
// opt can fit in four bits, if the width and height need more than eight bits each. #define KEY(width, height, bits, opt) (unsigned)(width) << 24 | (height) << 16 | (bits) << 8 | (opt) #if defined(MVTOOLS_X86) #define LUMA_SSE2(width, height) \ { KEY(width, height, 8, SSE2), luma_sse2<width, height> }, #else #define LUMA_SSE2(width, height) #endif #define LUMA(width, height) \ { KEY(width, height, 8, Scalar), luma_c<width, height, uint8_t> }, \ { KEY(width, height, 16, Scalar), luma_c<width, height, uint16_t> }, static const std::unordered_map<uint32_t, LUMAFunction> luma_functions = { LUMA(4, 4) LUMA(8, 4) LUMA(8, 8) LUMA(16, 2) LUMA(16, 8) LUMA(16, 16) LUMA(32, 16) LUMA(32, 32) LUMA(64, 32) LUMA(64, 64) LUMA(128, 64) LUMA(128, 128) LUMA_SSE2(4, 4) LUMA_SSE2(8, 4) LUMA_SSE2(8, 8) LUMA_SSE2(16, 2)