/*
==============
RE_StretchPicGradient
==============
*/
void RE_StretchPicGradient( float x, float y, float w, float h,
                            float s1, float t1, float s2, float t2, qhandle_t hShader, const float *gradientColor,
                            int gradientType )
{
	stretchPicCommand_t *cmd;

	cmd = (stretchPicCommand_t*) R_GetCommandBuffer( sizeof( *cmd ) );

	if ( !cmd )
	{
		return;
	}

	cmd->commandId = RC_STRETCH_PIC_GRADIENT;
	cmd->shader = R_GetShaderByHandle( hShader );
	cmd->x = x;
	cmd->y = y;
	cmd->w = w;
	cmd->h = h;
	cmd->s1 = s1;
	cmd->t1 = t1;
	cmd->s2 = s2;
	cmd->t2 = t2;

	if ( !gradientColor )
	{
		static float colorWhite[ 4 ] = { 1, 1, 1, 1 };

		gradientColor = colorWhite;
	}

	floatToUnorm8( gradientColor, cmd->gradientColor );
	cmd->gradientType = gradientType;
}
Exemple #2
0
void Tess_AddTetrahedron( vec4_t tetraVerts[ 4 ], const vec4_t colorf )
{
	int k;
	u8vec4_t color;

	Tess_CheckOverflow( 12, 12 );

	floatToUnorm8( colorf, color );

	// ground triangle
	for ( k = 0; k < 3; k++ )
	{
		VectorCopy( tetraVerts[ k ], tess.verts[ tess.numVertexes ].xyz );
		Vector4Copy( color, tess.verts[ tess.numVertexes ].color );
		tess.indexes[ tess.numIndexes++ ] = tess.numVertexes;
		tess.numVertexes++;
	}

	// side triangles
	for ( k = 0; k < 3; k++ )
	{
		VectorCopy( tetraVerts[ 3 ], tess.verts[ tess.numVertexes ].xyz );  // offset
		Vector4Copy( color, tess.verts[ tess.numVertexes ].color );
		tess.indexes[ tess.numIndexes++ ] = tess.numVertexes;
		tess.numVertexes++;

		VectorCopy( tetraVerts[ k ], tess.verts[ tess.numVertexes ].xyz );
		Vector4Copy( color, tess.verts[ tess.numVertexes ].color );
		tess.indexes[ tess.numIndexes++ ] = tess.numVertexes;
		tess.numVertexes++;

		VectorCopy( tetraVerts[( k + 1 ) % 3 ], tess.verts[ tess.numVertexes ].xyz );
		Vector4Copy( color, tess.verts[ tess.numVertexes ].color );
		tess.indexes[ tess.numIndexes++ ] = tess.numVertexes;
		tess.numVertexes++;
	}

	tess.attribsSet |= ATTR_POSITION | ATTR_COLOR;
}
Exemple #3
0
/*
==============
Tess_AddQuadStampExt
==============
*/
void Tess_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, const vec4_t color, float s1, float t1, float s2, float t2 )
{
	int    i;
	vec3_t normal;
	int    ndx;

	GLimp_LogComment( "--- Tess_AddQuadStampExt ---\n" );

	Tess_CheckOverflow( 4, 6 );

	ndx = tess.numVertexes;

	// triangle indexes for a simple quad
	tess.indexes[ tess.numIndexes ] = ndx;
	tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
	tess.indexes[ tess.numIndexes + 2 ] = ndx + 3;

	tess.indexes[ tess.numIndexes + 3 ] = ndx + 3;
	tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
	tess.indexes[ tess.numIndexes + 5 ] = ndx + 2;

	tess.verts[ ndx ].xyz[ 0 ] = origin[ 0 ] + left[ 0 ] + up[ 0 ];
	tess.verts[ ndx ].xyz[ 1 ] = origin[ 1 ] + left[ 1 ] + up[ 1 ];
	tess.verts[ ndx ].xyz[ 2 ] = origin[ 2 ] + left[ 2 ] + up[ 2 ];

	tess.verts[ ndx + 1 ].xyz[ 0 ] = origin[ 0 ] - left[ 0 ] + up[ 0 ];
	tess.verts[ ndx + 1 ].xyz[ 1 ] = origin[ 1 ] - left[ 1 ] + up[ 1 ];
	tess.verts[ ndx + 1 ].xyz[ 2 ] = origin[ 2 ] - left[ 2 ] + up[ 2 ];

	tess.verts[ ndx + 2 ].xyz[ 0 ] = origin[ 0 ] - left[ 0 ] - up[ 0 ];
	tess.verts[ ndx + 2 ].xyz[ 1 ] = origin[ 1 ] - left[ 1 ] - up[ 1 ];
	tess.verts[ ndx + 2 ].xyz[ 2 ] = origin[ 2 ] - left[ 2 ] - up[ 2 ];

	tess.verts[ ndx + 3 ].xyz[ 0 ] = origin[ 0 ] + left[ 0 ] - up[ 0 ];
	tess.verts[ ndx + 3 ].xyz[ 1 ] = origin[ 1 ] + left[ 1 ] - up[ 1 ];
	tess.verts[ ndx + 3 ].xyz[ 2 ] = origin[ 2 ] + left[ 2 ] - up[ 2 ];

	// constant normal all the way around
	VectorSubtract( vec3_origin, backEnd.viewParms.orientation.axis[ 0 ], normal );
	R_TBNtoQtangents( left, up, normal, tess.verts[ ndx ].qtangents );
	Vector4Copy( tess.verts[ ndx ].qtangents, tess.verts[ ndx + 1 ].qtangents );
	Vector4Copy( tess.verts[ ndx ].qtangents, tess.verts[ ndx + 2 ].qtangents );
	Vector4Copy( tess.verts[ ndx ].qtangents, tess.verts[ ndx + 3 ].qtangents );

	// standard square texture coordinates
	tess.verts[ ndx ].texCoords[ 0 ] = floatToHalf( s1 );
	tess.verts[ ndx ].texCoords[ 1 ] = floatToHalf( t1 );

	tess.verts[ ndx + 1 ].texCoords[ 0 ] = floatToHalf( s2 );
	tess.verts[ ndx + 1 ].texCoords[ 1 ] = floatToHalf( t1 );

	tess.verts[ ndx + 2 ].texCoords[ 0 ] = floatToHalf( s2 );
	tess.verts[ ndx + 2 ].texCoords[ 1 ] = floatToHalf( t2 );

	tess.verts[ ndx + 3 ].texCoords[ 0 ] = floatToHalf( s1 );
	tess.verts[ ndx + 3 ].texCoords[ 1 ] = floatToHalf( t2 );

	// constant color all the way around
	// should this be identity and let the shader specify from entity?

	u8vec4_t iColor;
	floatToUnorm8( color, iColor );
	for ( i = 0; i < 4; i++ )
	{
		Vector4Copy( iColor, tess.verts[ ndx + i ].color );
	}

	tess.numVertexes += 4;
	tess.numIndexes += 6;

	tess.attribsSet |= ATTR_POSITION | ATTR_QTANGENT | ATTR_COLOR | ATTR_TEXCOORD;
}
Exemple #4
0
/*
==============
Tess_AddQuadStampExt2
==============
*/
void Tess_AddQuadStampExt2( vec4_t quadVerts[ 4 ], const vec4_t color, float s1, float t1, float s2, float t2 )
{
	int    i;
	vec3_t normal, tangent, binormal;
	int    ndx;

	GLimp_LogComment( "--- Tess_AddQuadStampExt2 ---\n" );

	Tess_CheckOverflow( 4, 6 );

	ndx = tess.numVertexes;

	// triangle indexes for a simple quad
	tess.indexes[ tess.numIndexes ] = ndx;
	tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
	tess.indexes[ tess.numIndexes + 2 ] = ndx + 3;

	tess.indexes[ tess.numIndexes + 3 ] = ndx + 3;
	tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
	tess.indexes[ tess.numIndexes + 5 ] = ndx + 2;

	VectorCopy( quadVerts[ 0 ], tess.verts[ ndx + 0 ].xyz );
	VectorCopy( quadVerts[ 1 ], tess.verts[ ndx + 1 ].xyz );
	VectorCopy( quadVerts[ 2 ], tess.verts[ ndx + 2 ].xyz );
	VectorCopy( quadVerts[ 3 ], tess.verts[ ndx + 3 ].xyz );

	tess.attribsSet |= ATTR_POSITION | ATTR_COLOR | ATTR_TEXCOORD | ATTR_QTANGENT;

	// constant normal all the way around
	vec2_t st[ 3 ] = { { s1, t1 }, { s2, t1 }, { s2, t2 } };
	R_CalcFaceNormal( normal, quadVerts[ 0 ], quadVerts[ 1 ], quadVerts[ 2 ] );
	R_CalcTangents( tangent, binormal,
			quadVerts[ 0 ], quadVerts[ 1 ], quadVerts[ 2 ],
			st[ 0 ], st[ 1 ], st[ 2 ] );
	//if ( !calcNormals )
	//{
	//	VectorNegate( backEnd.viewParms.orientation.axis[ 0 ], normal );
	//}

	R_TBNtoQtangents( tangent, binormal, normal, tess.verts[ ndx ].qtangents );
	Vector4Copy( tess.verts[ ndx ].qtangents, tess.verts[ ndx + 1 ].qtangents );
	Vector4Copy( tess.verts[ ndx ].qtangents, tess.verts[ ndx + 2 ].qtangents );
	Vector4Copy( tess.verts[ ndx ].qtangents, tess.verts[ ndx + 3 ].qtangents );

	// standard square texture coordinates
	tess.verts[ ndx ].texCoords[ 0 ] = floatToHalf( s1 );
	tess.verts[ ndx ].texCoords[ 1 ] = floatToHalf( t1 );

	tess.verts[ ndx + 1 ].texCoords[ 0 ] = floatToHalf( s2 );
	tess.verts[ ndx + 1 ].texCoords[ 1 ] = floatToHalf( t1 );

	tess.verts[ ndx + 2 ].texCoords[ 0 ] = floatToHalf( s2 );
	tess.verts[ ndx + 2 ].texCoords[ 1 ] = floatToHalf( t2 );

	tess.verts[ ndx + 3 ].texCoords[ 0 ] = floatToHalf( s1 );
	tess.verts[ ndx + 3 ].texCoords[ 1 ] = floatToHalf( t2 );

	// constant color all the way around
	// should this be identity and let the shader specify from entity?

	u8vec4_t iColor;
	floatToUnorm8( color, iColor );
	for ( i = 0; i < 4; i++ )
	{
		Vector4Copy( iColor, tess.verts[ ndx + i ].color );
	}

	tess.numVertexes += 4;
	tess.numIndexes += 6;
}
Exemple #5
0
bool
Image::writePNG(std::ostream &os, bool strip_alpha) const
{
    png_structp png_ptr;
    png_infop info_ptr;
    int color_type;

    switch (channels) {
    case 4:
        color_type = strip_alpha ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA;
        break;
    case 3:
        color_type = PNG_COLOR_TYPE_RGB;
        break;
    case 2:
        color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
        break;
    case 1:
        color_type = PNG_COLOR_TYPE_GRAY;
        break;
    default:
        assert(0);
        goto no_png;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        goto no_png;

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_write_struct(&png_ptr,  NULL);
        goto no_png;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        goto no_png;
    }

    png_set_write_fn(png_ptr, &os, pngWriteCallback, NULL);

    png_set_IHDR(png_ptr, info_ptr, width, height, 8,
                 color_type, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_set_compression_level(png_ptr, png_compression_level);

    png_write_info(png_ptr, info_ptr);

    if (channels == 4 && strip_alpha) {
        png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
    }

    switch (channelType) {
    case TYPE_UNORM8:
        for (const unsigned char *row = start(); row != end(); row += stride()) {
            png_write_rows(png_ptr, (png_bytepp) &row, 1);
        }
        break;
    case TYPE_FLOAT:
        png_bytep rowUnorm8 = new png_byte[width * channels];
        for (const unsigned char *row = start(); row != end(); row += stride()) {
            const float *rowFloat = (const float *)row;
            for (unsigned x = 0, i = 0; x < width; ++x) {
                for (unsigned channel = 0; channel < channels; ++channel, ++i) {
                    float c = rowFloat[i];
                    bool srgb = channels >= 3 && channel < 3;
                    rowUnorm8[i] = srgb ? floatToSRGB(c) : floatToUnorm8(c);
                }
            }
            png_write_rows(png_ptr, (png_bytepp) &rowUnorm8, 1);
        }
        delete [] rowUnorm8;
        break;
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);

    return true;

no_png:
    return false;
}