MHDoom finished

Discuss anything not covered by any of the other categories.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

:lol: yeah
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

Small warning mods built for vanilla will most likely crash with MHDoom because of missing exports (i removed a lot of unused stuff) those mods would have to be rebuilt with MHDoom as the sdk,
sorry about that but even dhewm3 has that problem, to many changes in code.

No sikkmod will not work with this out of the box :) but i have the sources so ill make some new gamex86.dll's that will work ;).

Btw feel free to submit patches to github if you have something you feel would be a great improvement :)
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

Doooh ok i found out what caused the shadow problem was a minor optimization i made to avoid state changing as much but i used the wrong call disabling something that should have been enabled :oops:
Fixed on github now.

Also uploading sikkmods game dll sources if someone wants to use them.
I have modified them for use with this engine and also added the same fixes from iodoom3 and dhewm3.
Productivity is a state of mind.
Spiney
Posts: 63
Joined: Mon Feb 13, 2012 1:35 pm

Re: MHDoom finished

Post by Spiney »

As for image quality, perhaps this trick would help a little?
http://www.iquilezles.org/www/articles/ ... exture.htm
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

That could be an option unfortunatly its a GLSL shader and i have no idea how to port that to ARB2 assembly shading :S

Another option is something similar i once nicked from twilight its an interpolation method that does allmost exactly the same but its in plain C :) shoulf be pretty easy to convert it to C++ though.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

Well was not super easy but here it is in case someone else wants to try it.

Code: Select all

/*
================
BorderCheck macro. the pixels that get passed in should be pre-converted
to the YCbCr colorspace.
================
*/
#define BorderCheck(pix1, pix2, dY, dCb, dCr) ( (abs(*pix1 - *pix2) > dY) || (abs(*(pix1+1) - *(pix2+1)) > dCb) || (abs(*(pix1+2) - *(pix2+2)) > dCr) )

/*
================
LinearScale macro.
================
*/
#define LinearScale(src1, src2, pct) (( src1 * (1 - pct) ) + ( src2 * pct))

/*
================
GetOffSet macro.
================
*/
#define GetOffSet(new, start, cur) (new + (cur - ((unsigned char*)start)))

/*
================
Clamp macro.
================
*/
#define Clamp(a,b,c) (max(a, min(b, c)))

/*
================
RGBAtoTCbCrA - converts a source RGBA pixel into a destination YCbCrA pixel
================
*/
static inline void RGBAtoYCbCrA( unsigned char* dest, unsigned char* src )
{
	unsigned char s0, s1, s2;
	s0 = *( src );
	s1 = *( src + 1 );
	s2 = *( src + 2 );
#define MIX(i,n,m0,m1,m2) (*(dest+i) = (unsigned char) (n + (((s0 * m0) + (s1 * m0) + (s2 * m2))/256.0f)))
	MIX( 0, 16.0f, 65.738f, 129.057f, 25.064f );
	MIX( 1, 128.0f, -37.945f, -74.494f, 112.439f );
	MIX( 2, 128.0f, 112.439f, -94.154f, -18.285f );
#undef MIX
	*( dest + 3 ) = *( src + 3 );
}

/*
================
R_ResampleTexture - resamples the texture given in indata, of the
dimensions inwidth by inheight to outdata, of the dimensions outwidth by
outheight, using a method based on the brief description of SmartFlt
given at http://www.hiend3d.com/smartflt.html
this could probably do with some optimizations.
================
*/
void R_ResampleTexture( void* indata, int inwidth, int inheight, void* outdata, int outwidth, int outheight )
{
	float xstep = ( static_cast< float >( inwidth ) ) / ( static_cast< float >( outwidth ) );
	float ystep = ( static_cast< float >( inheight ) ) / ( static_cast< float >( outheight ) );

	int dY = r_smartflt_y.GetInteger();
	int dCb = r_smartflt_cb.GetInteger();
	int dCr = r_smartflt_cr.GetInteger();

	int DestX, DestY;
	float SrcX, SrcY;

	// buffer to stor the YCbCrA version of the input texture.
	unsigned char* Ybuffer = reinterpret_cast< byte* >( R_StaticAlloc( inwidth * inheight * 4 ) );
	unsigned char* id = reinterpret_cast< byte* >( indata );
	unsigned char* od = reinterpret_cast< byte* >( outdata );
	unsigned char* idrowstart = id;

	// convert the input texture to YCbCr into a temp buffer, for border detections.
	for( DestX = 0, idrowstart = Ybuffer; DestX < ( inwidth * inheight ); DestX++, idrowstart += 4, id += 4 )
	{
		RGBAtoYCbCrA( idrowstart, id );
	}

	for( DestY = 0, SrcY = 0; DestY < outheight; DestY++, SrcY += ystep )
	{
		// four "work" pointers to make code a little nicer.
		unsigned char*	w0, *w1, *w2, *w3;

		// right == clockwise, left == counter-clockwise
		unsigned char*	nearest, *left, *right, *opposite;
		float			pctnear, pctleft, pctright, pctopp;
		float			w0pct, w1pct, w2pct, w3pct;
		float			x, y, tmpx, tmpy;
		char			edges[6];

		// clamp SrcY to cover for possible float error
		// to make sure the edges fall into the special cases
		if( SrcY > ( inheight - 1.01f ) )
		{
			SrcY = ( inheight - 1.01f );
		}

		// go to the start of the next row. "od" should be pointing at the right place already.
		idrowstart = ( reinterpret_cast< byte* >( indata ) ) + ( static_cast< int >( SrcY ) ) * inwidth * 4;

		for( DestX = 0, SrcX = 0; DestX < outwidth; DestX++, od += 4, SrcX += xstep )
		{
			// clamp SrcY to cover for possible float error
			// to make sure that the edges fall into the special cases
			if( SrcX > ( inwidth - 1.01f ) )
			{
				SrcX = inwidth - 1.01f;
			}
			id = idrowstart + ( static_cast< int >( SrcX ) ) * 4;

			x = ( static_cast< int >( SrcX ) );
			y = ( static_cast< int >( SrcY ) );

			// if we happen to be directly on a source row
			if( SrcY == y )
			{
				// and also directly on a source column
				if( SrcX == x )
				{
					// then we are directly on a source pixel
					// just copy it and move on.
					memcpy( od, id, 4 );
					continue;
				}

				// if there is a border between the two surrounding source pixels
				if( BorderCheck( GetOffSet( Ybuffer, indata, id ), GetOffSet( Ybuffer, indata, ( id + 4 ) ), dY, dCb, dCr ) )
				{
					// if we are closer to the left
					if( x == ( static_cast< int >( SrcX + 0.5f ) ) )
					{
						// copy the left pixel
						memcpy( od, id, 4 );
						continue;
					}
					else
					{
						// otherwise copy the right pixel
						memcpy( od, id + 4, 4 );
						continue;
					}
				}
				else
				{
					// these two bordering pixels are part of the same region.
					// blend them using a weighted average
					x = SrcX - x;

					w0 = id;
					w1 = id + 4;

					*od = static_cast< unsigned char >( LinearScale( *w0, *w1, x ) );
					*( od + 1 ) = static_cast< unsigned char >( LinearScale( *( w0 + 1 ), *( w1 + 1 ), x ) );
					*( od + 2 ) = static_cast< unsigned char >( LinearScale( *( w0 + 2 ), *( w1 + 2 ), x ) );
					*( od + 3 ) = static_cast< unsigned char >( LinearScale( *( w0 + 3 ), *( w1 + 3 ), x ) );

					continue;
				}
			}

			// if we aren't direcly on a source row, but we are on a source column
			if( SrcX == x )
			{
				// if there is a border between this source pixel and the one on
				// the next row
				if( BorderCheck( GetOffSet( Ybuffer, indata, id ), GetOffSet( Ybuffer, indata, ( id + inwidth * 4 ) ), dY, dCb, dCr ) )
				{
					// if we are closer to the top
					if( y == ( static_cast< int >( SrcY + 0.5f ) ) )
					{
						// copy the top
						memcpy( od, id, 4 );
						continue;
					}
					else
					{
						// copy the bottom
						memcpy( od, ( id + inwidth * 4 ), 4 );
						continue;
					}
				}
				else
				{
					// the two pixels are part of the same region, blend them
					// together with a weighted average
					y = SrcY - y;

					w0 = id;
					w1 = id + ( inwidth * 4 );

					*od = static_cast< unsigned char >( LinearScale( *w0, *w1, y ) );
					*( od + 1 ) = static_cast< unsigned char >( LinearScale( *( w0 + 1 ), *( w1 + 1 ), y ) );
					*( od + 2 ) = static_cast< unsigned char >( LinearScale( *( w0 + 2 ), *( w1 + 2 ), y ) );
					*( od + 3 ) = static_cast< unsigned char >( LinearScale( *( w0 + 3 ), *( w1 + 3 ), y ) );

					continue;
				}
			}

			// now for the non-simple case: somewhere between four pixels.
			// w0 is top-left, w1 is top-right, w2 is bottom-left, and w3 is bottom-right
			w0 = id;
			w1 = id + 4;
			w2 = id + ( inwidth * 4 );
			w3 = w2 + 4;

			x = SrcX - x;
			y = SrcY - y;

			w0pct = 1.0f - sqrtf( x * x + y * y );
			w1pct = 1.0f - sqrtf( ( 1 - x ) * ( 1 - x ) + y * y );
			w2pct = 1.0f - sqrtf( x * x + ( 1 - y ) * ( 1 - y ) );
			w3pct = 1.0f - sqrtf( ( 1 - x ) * ( 1 - x ) + ( 1 - y ) * ( 1 - y ) );

			// set up our symbolic identification.
			// "nearest" is the pixel whose quadrant we are in.
			// "left" is counter-clockwise from "nearest"
			// "right" is clockwise from "nearest"
			// "opposite" is, well, opposite.
			if( x < 0.5f )
			{
				tmpx = x;

				if( y < 0.5f )
				{
					nearest = w0;
					left = w2;
					right = w1;
					opposite = w3;
					pctnear = w0pct;
					pctleft = w2pct;
					pctright = w1pct;
					pctopp = w3pct;
					tmpy = y;
				}
				else
				{
					nearest = w2;
					left = w3;
					right = w0;
					opposite = w1;
					pctnear = w2pct;
					pctleft = w3pct;
					pctright = w0pct;
					pctopp = w1pct;
					tmpy = 1.0f - y;
				}
			}
			else
			{
				tmpx = 1.0f - x;

				if( y < 0.5f )
				{
					nearest = w1;
					left = w0;
					right = w3;
					opposite = w2;
					pctnear = w1pct;
					pctleft = w0pct;
					pctright = w3pct;
					pctopp = w2pct;
					tmpy = y;
				}
				else
				{
					nearest = w3;
					left = w1;
					right = w2;
					opposite = w0;
					pctnear = w3pct;
					pctleft = w1pct;
					pctright = w2pct;
					pctopp = w0pct;
					tmpy = 1.0f - y;
				}
			}
			x = tmpx;
			y = tmpy;

			w0 = GetOffSet( Ybuffer, indata, nearest );
			w1 = GetOffSet( Ybuffer, indata, right );
			w2 = GetOffSet( Ybuffer, indata, left );
			w3 = GetOffSet( Ybuffer, indata, opposite );

			edges[0] = BorderCheck( w0, w2, dY, dCb, dCr );
			edges[1] = BorderCheck( w0, w1, dY, dCb, dCr );
			edges[2] = BorderCheck( w0, w3, dY, dCb, dCr );

			edges[3] = BorderCheck( w3, w2, dY, dCb, dCr );
			edges[4] = BorderCheck( w3, w1, dY, dCb, dCr );
			edges[5] = BorderCheck( w2, w1, dY, dCb, dCr );

#undef GetOffSet

			// do the edge detections.
			if( edges[0] && edges[1] && edges[2] && !edges[5] )
			{
				// borders all around, and no border between the left and right.
				// if there is no border between the opposite side and only one
				// of the two other corners, or if we are closer to the corner
				if( ( edges[3] && !edges[4] ) || ( !edges[3] && edges[4] ) || ( x + y < 0.5f ) )
				{
					// closer to to the corner.
					memcpy( od, nearest, 4 );
				}
				else
				{
					// closer to the center. (note, there is a diagonal line between the nearest pixel
					// and the center of the four.)

					// exclude the "nearest" pixel
					// pctnear = 0.0f;
					// if there is a border around the opposite corner,
					// exclude it from the current pixel.
					if( edges[3] && edges[4] )
					{
						// pctopp = 0.0f;
						*od = static_cast< unsigned char >( Clamp( 0, ( ( ( *left * pctleft ) + ( *right * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
						*( od + 1 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 1 ) * pctleft ) + ( *( right + 1 ) * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
						*( od + 2 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 2 ) * pctleft ) + ( *( right + 2 ) * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
						*( od + 3 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 3 ) * pctleft ) + ( *( right + 3 ) * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
					}
					else
					{
						*od = static_cast< unsigned char >( Clamp( 0, ( ( ( *left * pctleft ) + ( *right * pctright ) + ( *opposite * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
						*( od + 1 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 1 ) * pctleft ) + ( *( right + 1 ) * pctright ) + ( *( opposite + 1 ) * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
						*( od + 2 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 2 ) * pctleft ) + ( *( right + 2 ) * pctright ) + ( *( opposite + 2 ) * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
						*( od + 3 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 3 ) * pctleft ) + ( *( right + 3 ) * pctright ) + ( *( opposite + 3 ) * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
					}
				}
			}
			else if( edges[0] && edges[1] && edges[2] )
			{
				memcpy( od, nearest, 4 );
			}
			else
			{
				float num[4], denom = pctnear;

				num[0] = ( *nearest * pctnear );
				num[1] = ( *( nearest + 1 ) * pctnear );
				num[2] = ( *( nearest + 2 ) * pctnear );
				num[3] = ( *( nearest + 3 ) * pctnear );

				if( !edges[0] )
				{
					num[0] += *left * pctleft;
					num[1] += *( left + 1 ) * pctleft;
					num[2] += *( left + 2 ) * pctleft;
					num[3] += *( left + 3 ) * pctleft;
					denom += pctleft;
				}

				if( edges[1] )
				{
					num[0] += *right * pctright;
					num[1] += *( right + 1 ) * pctright;
					num[2] += *( right + 2 ) * pctright;
					num[3] += *( right + 3 ) * pctright;
					denom += pctright;
				}

				if( edges[2] )
				{
					num[0] += *opposite * pctopp;
					num[1] += *( opposite + 1 ) * pctopp;
					num[2] += *( opposite + 2 ) * pctopp;
					num[3] += *( opposite + 3 ) * pctopp;
					denom += pctopp;
				}

				// blend the source pixels together to get the output pixel.
				// if a source pixel doesn't affect the output, it's percent should be set to 0 in the edge check
				// code above. if only one pixel affects the output, its percentage should be set to 1 and all
				// the others set to 0. (yeah, it is ugly, but I don't see a need to optimize this code (yet)
				*od = static_cast< unsigned char >( Clamp( 0, num[0] / denom, 255 ) );
				*( od + 1 ) = static_cast< unsigned char >( Clamp( 0, num[1] / denom, 255 ) );
				*( od + 2 ) = static_cast< unsigned char >( Clamp( 0, num[2] / denom, 255 ) );
				*( od + 3 ) = static_cast< unsigned char >( Clamp( 0, num[3] / denom, 255 ) );
			}
		}
	}
	R_StaticFree( Ybuffer );
}
To use it you will have to make a few changes in Doom3

find R_LoadImage

and at the bottom of the function find this if( scaled_width != w || scaled_height != h )

and replace the block of code with this

Code: Select all

		if( scaled_width != w || scaled_height != h )
		{
			if( globalImages->image_roundDown.GetBool() && scaled_width > w )
			{
				scaled_width >>= 1;
			}
			
			if( globalImages->image_roundDown.GetBool() && scaled_height > h )
			{
				scaled_height >>= 1;
			}
			pic_p = ( byte* ) R_StaticAlloc( scaled_width * scaled_height * 4 );
			R_ResampleTexture( *pic, w, h, pic_p, scaled_width, scaled_height );
			R_StaticFree( *pic );
			*pic = pic_p;
			*width = scaled_width;
			*height = scaled_height;
		} 
place a few cvars at the top of image_process.cpp

idCVar r_smartflt_y( "r_smartflt_y", "10", CVAR_INTEGER | CVAR_RENDERER, "Smart Filter Y Value" );
idCVar r_smartflt_cb( "r_smartflt_cb", "50", CVAR_INTEGER | CVAR_RENDERER, "Smart Filter CB Value" );
idCVar r_smartflt_cr( "r_smartflt_cr", "50", CVAR_INTEGER | CVAR_RENDERER, "Smart Filter CR Value" );

and externals in tr_local.h

extern idCVar r_smartflt_y;
extern idCVar r_smartflt_cb;
extern idCVar r_smartflt_cr;

you can toy with different values to get the smoothest result.

worst example of Doom3's ingame lowres images below

Image
Productivity is a state of mind.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: MHDoom finished

Post by toneddu2000 »

great reckless! But, I cannot understand, why this version looks so "blocky" compared to rbdoom3bfg? What mh did to this version?
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

He bumped everything to ultra levels and then a bit more :)
btw BFG uses higher res textures but there compressed and in binary format so its not easy making texture packs for it.

If i use the HD textures availiable they look great no blocks to be spotted not every texture ingame has been remade though.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

shadow bug was indeed an ATI related problem sigh.

if you need a fast fix open pak000.pk4 with a zip program go into the glprogs folder and open interaction.vfp preferably with notepad++ and replace everything in it with this.

Code: Select all

!!ARBvp1.0 OPTION ARB_position_invariant ;

# VPROG_INTERACTION
# 
# input:
# 
# attrib[8] TEX0	texture coordinates
# attrib[9] TEX1	normal
# attrib[10] TEX2	tangent[0]
# attrib[11] TEX3	tangent[1]
# COL			vertex color
#
# c[4]	localLightOrigin
# c[5]	localViewOrigin
# c[6]	lightProjection S
# c[7]	lightProjection T
# c[8]	lightProjection Q
# c[9]	lightFalloff S
# c[10]	bumpMatrix S
# c[11]	bumpMatrix T
# c[12]	diffuseMatrix S
# c[13]	diffuseMatrix T
# c[14]	specularMatrix S
# c[15]	specularMatrix T
# c[16]	vertex color modulate
# c[17]	vertex color add
# 
# output:
# 
# texture 0 is the cube map
# texture 1 is the per-surface bump map
# texture 2 is the light falloff texture
# texture 3 is the light projection texture
# texture 4 is the per-surface diffuse map
# texture 5 is the per-surface specular map
# texture 6 is the specular lookup table

TEMP	R0, R1, R2;

PARAM	defaultTexCoord = { 0, 0.5, 0, 1 };

# calculate vector to light in R0
SUB		R0, program.env[4], vertex.position;

# put into texture space for TEX0
DP3		result.texcoord[0].x, vertex.attrib[9], R0;
DP3		result.texcoord[0].y, vertex.attrib[10], R0;
DP3		result.texcoord[0].z, vertex.attrib[11], R0;

# textures 1 takes the base coordinates by the texture matrix
MOV		result.texcoord[1], defaultTexCoord;
DP4		result.texcoord[1].x, vertex.attrib[8], program.env[10];
DP4		result.texcoord[1].y, vertex.attrib[8], program.env[11];

# texture 2 has one texgen
MOV		result.texcoord[2], defaultTexCoord;
DP4		result.texcoord[2].x, vertex.position, program.env[9];

# texture 3 has three texgens
DP4		result.texcoord[3].x, vertex.position, program.env[6];
DP4		result.texcoord[3].y, vertex.position, program.env[7];
DP4		result.texcoord[3].w, vertex.position, program.env[8];

# textures 4 takes the base coordinates by the texture matrix
MOV		result.texcoord[4], defaultTexCoord;
DP4		result.texcoord[4].x, vertex.attrib[8], program.env[12];
DP4		result.texcoord[4].y, vertex.attrib[8], program.env[13];

# textures 5 takes the base coordinates by the texture matrix
MOV		result.texcoord[5], defaultTexCoord;
DP4		result.texcoord[5].x, vertex.attrib[8], program.env[14];
DP4		result.texcoord[5].y, vertex.attrib[8], program.env[15];

# texture 6's texcoords will be the halfangle in texture space

# calculate normalized vector to light in R0
SUB		R0, program.env[4], vertex.position;
DP3		R1, R0, R0;
RSQ		R1, R1.x;
MUL		R0, R0, R1.x;

# calculate normalized vector to viewer in R1
SUB		R1, program.env[5], vertex.position;
DP3		R2, R1, R1;
RSQ		R2, R2.x;
MUL		R1, R1, R2.x;

# add together to become the half angle vector in object space (non-normalized)
ADD		R0, R0, R1;

# put into texture space
DP3		result.texcoord[6].x, vertex.attrib[9], R0;
DP3		result.texcoord[6].y, vertex.attrib[10], R0;
DP3		result.texcoord[6].z, vertex.attrib[11], R0;

# generate the vertex color, which can be 1.0, color, or 1.0 - color
# for 1.0 : env[16] = 0, env[17] = 1
# for color : env[16] = 1, env[17] = 0
# for 1.0-color : env[16] = -1, env[17] = 1
MAD		result.color, vertex.color, program.env[16], program.env[17];

END


#======================================================================

!!ARBfp1.0 
OPTION ARB_precision_hint_nicest;

# texture 0 is the cube map
# texture 1 is the per-surface bump map
# texture 2 is the light falloff texture
# texture 3 is the light projection texture
# texture 4 is the per-surface diffuse map
# texture 5 is the per-surface specular map
# texture 6 is the specular lookup table

# env[0] is the diffuse modifier
# env[1] is the specular modifier

TEMP	light, color, R1, R2, localNormal, specular;

PARAM	subOne = { -1, -1, -1, -1 };
PARAM	scaleTwo = { 2, 2, 2, 2 };
PARAM 	specExp = { 16, 0, 0, 0 };

# load the specular half angle first, because
# the ATI shader gives a "too many indirections" error
# if this is done right before the texture indirection

#-----------------
#TEX	specular, fragment.texcoord[6], texture[0], CUBE;
#MAD	specular, specular, scaleTwo, subOne;


# instead of using the normalization cube map, normalize with math
DP3		specular, fragment.texcoord[6],fragment.texcoord[6];
RSQ		specular, specular.x;
MUL		specular, specular.x, fragment.texcoord[6];
#-----------------


#
# the amount of light contacting the fragment is the
# product of the two light projections and the surface
# bump mapping
#

# perform the diffuse bump mapping

#----------------- NVIDIA
#TEX	light, fragment.texcoord[0], texture[0], CUBE;
#MAD	light, light, scaleTwo, subOne;

# instead of using the normalization cube map, normalize with math
DP3		light, fragment.texcoord[0],fragment.texcoord[0];
RSQ		light, light.x;
MUL		light, light.x, fragment.texcoord[0];
#----------------- ATI

TEX	localNormal, fragment.texcoord[1], texture[1], 2D;
MOV localNormal.x, localNormal.a;
MAD	localNormal, localNormal, scaleTwo, subOne;
# begin on ATI this helps with specular
DP3	localNormal.w, localNormal, localNormal;
RSQ	localNormal.w, localNormal.w;
MUL	localNormal, localNormal, localNormal.w;
# end on ATI this helps with specular
DP3	light, light, localNormal;

# modulate by the light projection
TXP	R1, fragment.texcoord[3], texture[3], 2D;
MUL	light, light, R1;

# modulate by the light falloff
TXP	R1, fragment.texcoord[2], texture[2], 2D;
MUL	light, light, R1;

#
# the light will be modulated by the diffuse and
# specular surface characteristics
#

# modulate by the diffuse map and constant diffuse factor
TEX	R1, fragment.texcoord[4], texture[4], 2D;
MUL	color, R1, program.env[0];

# perform the specular bump mapping
DP3	specular, specular, localNormal;

# perform a dependent table read for the specular falloff
POW	R1, specular.x, specExp.x;

# modulate by the constant specular factor
MUL	R1, R1, program.env[1];

# modulate by the specular map * 2
TEX	R2, fragment.texcoord[5], texture[5], 2D;
ADD	R2, R2, R2;
MAD	color, R1, R2, color;


MUL	color, light, color;

# modify by the vertex color
#MUL result.color, color, fragment.color;

# this should be better on future hardware, but current drivers make it slower
MUL result.color.xyz, color, fragment.color;

END

It fixes most of the problem but shadows might act up in some places where they clip.
Productivity is a state of mind.
Spiney
Posts: 63
Joined: Mon Feb 13, 2012 1:35 pm

Re: MHDoom finished

Post by Spiney »

I also noticed some flickering/disappearing shadows at the cantina windows on Mars city and some other places. (GF GTX660, driver 320.49)
Did you change the texture filtering on those pics? That doesn't look right even for something that low res, could be block compression?
Iirc MH swapped the normalization lookup texture with math, giving cleaner/crisper results, like you now get specular inside the bilinear filtered crevices between adjacent texels.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: MHDoom finished

Post by toneddu2000 »

reckless wrote:He bumped everything to ultra levels and then a bit more :)
Ah, ok thanks.
reckless wrote:btw BFG uses higher res textures but there compressed and in binary format so its not easy making texture packs for it.
What a shame. And the compression algorithm I suppose was not released with the source?
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

Compression is DXT5 i think so its doable with the directx sdk atleast, worst part seems to be that the images uses a binary format so its a mess to craft new ones.

@spiney havent touched the texture filtering but i bumped the versions on TGA and Jpeg maybe a bug snuck in the TGA code hmm ?.

If anyone spots the bug feel free to submit patches its the only thing holding off atm else it runs great even on ATI.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

Hmm so im not the only one noticing the shadows sometimes behave weird.
Also in some places with this bug i noticed i could see the outlines on the stencil shadows Oo (faint ghostly copy of the model casting the shadow).
Strangely enough the unmodified source does the same so its not something caused by the changes i have made atleast, bugger though as i have no idea whats causing it or where to start looking even :S.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: MHDoom finished

Post by revelator »

Ok the plot thickens :S after painfully going through the source comparing every single file to vanilla i was unable to find any change that would cause this,
today i updated the project to use msvc 2013 and ...shadows work fine again W.T.F @trademark !!! sadly the msvc 2013 build is a lot slower than the 2010 build (still playable but huh ?).
Productivity is a state of mind.
qbism
Posts: 1238
Joined: Thu Nov 04, 2004 5:51 am
Contact:

Re: MHDoom finished

Post by qbism »

Did you update any libs after switching to VS2013? Sometimes I wonder if the toolset version difference between 2008, 2010, and 2013 releases (some range like V90 to V120) makes a difference for 3d performance, but never tested it.
Post Reply