//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	FeatureGrid::BLENDFUNCTION (
		FeatureInstance *featureInstance, 
		unsigned char *pix_buf, 
		int start_span, 
		int end_span,
		int downScale
	)
{
	Feature *feature = featureInstance->feature;

	Verify(feature->featureMask0!=NULL);
	Verify(feature->featureMask1!=NULL);
	
#ifdef SHOW_MATERIAL
	DWORD mat_color = downScale & 0xffffff;
	downScale >>= 24;
#else
	int texture_width = (featureInstance->feature->featureTexture->width) >> downScale;
	int count_down = featureInstance->countDownToBorder;
	WORD *data_ptr_word = (WORD *)featureInstance->currentTexturePtr;
#endif
	unsigned char *mask0data = featureInstance->currentMask0Ptr;
	unsigned char *mask1data = featureInstance->currentMask1Ptr;

	int mask0_x_off = featureInstance->mask0_x_off >> downScale;
	int mask0_z_off = featureInstance->mask0_z_off >> downScale;

	int mask1_x_off = featureInstance->mask1_x_off >> downScale;
	int mask1_z_off = featureInstance->mask1_z_off >> downScale;

	int shifter0 = feature->GetZMask0Scale() + feature->GetXMask0Scale() - 2*downScale;
	int shifter1 = feature->GetZMask1Scale() + feature->GetXMask1Scale() - 2*downScale;

	int x0_stretch = 1<<(feature->GetXMask0Scale()-downScale);
	int z0_stretch = 1<<(feature->GetZMask0Scale()-downScale);
	
	int x1_stretch = 1<<(feature->GetXMask1Scale()-downScale);
	int z1_stretch = 1<<(feature->GetZMask1Scale()-downScale);

#ifdef MASK0_HORIZONTAL_FLIP
	int advancer0 = x0_stretch-1;
#else
	int advancer0 = ~(x0_stretch-1);
#endif

#ifdef MASK1_HORIZONTAL_FLIP
	int advancer1 = x1_stretch-1;
#else
	int advancer1 = ~(x1_stretch-1);
#endif

	int adv0, adv1, mixH0, mixH1;
	int pitch0 = feature->featureMask0->width + 2; // 2 - padding
	int pitch1 = feature->featureMask1->width + 2; // 2 - padding

	{
		int mix0, mix1, mix00, mix01, mix10, mix11;

		mix00 = *mask0data;
		mix01 = *(mask0data + 1);
		mix10 = *(mask0data + pitch0);
		mix11 = *(mask0data + pitch0 + 1);

		mix0 = (mix00*(z0_stretch - mask0_z_off) + mix10*mask0_z_off);
		mix1 = (mix01*(z0_stretch - mask0_z_off) + mix11*mask0_z_off);

		mixH0 = (mix0*(x0_stretch - mask0_x_off) + mix1*mask0_x_off);

		adv0 = mix1 - mix0;

		//=================================================

		mix00 = *mask1data;
		mix01 = *(mask1data + 1);
		mix10 = *(mask1data + pitch1);
		mix11 = *(mask1data + pitch1 + 1);

		mix0 = (mix00*(z1_stretch - mask1_z_off) + mix10*mask1_z_off);
		mix1 = (mix01*(z1_stretch - mask1_z_off) + mix11*mask1_z_off);

		mixH1 = (mix0*(x1_stretch - mask1_x_off) + mix1*mask1_x_off);

		adv1 = mix1 - mix0;
	}

	int *pix_buf_int = (int *)pix_buf;
	for(int i=0;;)
	{
		int mix = (mixH0>>shifter0) + (mixH1>>shifter1);

#ifdef MASK0_HORIZONTAL_FLIP
		mixH0 -= adv0;
#else
		mixH0 += adv0;
#endif

#ifdef MASK1_HORIZONTAL_FLIP
		mixH1 -= adv1;
#else
		mixH1 += adv1;
#endif

#ifdef SHOW_MATERIAL
		if(mix > 0x80)
		{
			pix_buf_int[i] = mat_color;
		}
#else	// SHOW_MATERIAL
		if(mix!=0)
		{
			mix = mix&0xffffff00 ? 0xff : mix;

			DWORD dst = pix_buf_int[i];
#ifdef TEXTURE_HORIZONTAL_FLIP
			DWORD src = data_ptr_word[-i];
#else
			DWORD src = data_ptr_word[i];
#endif

			DWORD buf;
			DWORD srcmix = mix<<3;

			mix = 0xff-mix;

			buf = ((dst & 0xff)*mix + (src & 0x1f)*srcmix)>>8;

			buf |= (((dst>>8)&0xff)*mix + ((src & 0x3e0) >> 5)*srcmix)&0xff00;

			buf |= ((((dst>>16)&0xff)*mix + (src >> 10)*srcmix)&0xff00)<<8;

			pix_buf_int[i] = buf;
		}
#endif	// SHOW_MATERIAL


		if(++i>=end_span-start_span)
		{
			break;
		}

#ifdef MASK0_HORIZONTAL_FLIP
	#ifndef SHOW_MATERIAL
		if(--count_down <= 0)
		{
			data_ptr_word += texture_width;
			count_down = texture_width;
		}
	#endif	//	SHOW_MATERIAL
		if(--mask0_x_off < 0)
		{
			mask0_x_off = advancer0;
			mask0data -= feature->featureMask0->depth;
#else
	#ifndef SHOW_MATERIAL
		if(--count_down <= 0)
		{
			data_ptr_word -= texture_width;
			count_down = texture_width;
		}
	#endif	//	SHOW_MATERIAL
		if(++mask0_x_off & advancer0)
		{
			mask0_x_off = 0;
			mask0data += feature->featureMask0->depth;
#endif

			int mix0, mix1, mix00, mix01, mix10, mix11;

			mix00 = *mask0data;
			mix01 = *(mask0data + 1);
			mix10 = *(mask0data + pitch0);
			mix11 = *(mask0data + pitch0 + 1);

			mix0 = (mix00*(z0_stretch - mask0_z_off) + mix10*mask0_z_off);
			mix1 = (mix01*(z0_stretch - mask0_z_off) + mix11*mask0_z_off);

			mixH0 = (mix0*(x0_stretch - mask0_x_off) + mix1*mask0_x_off);

			adv0 = mix1 - mix0;
		}

#ifdef MASK1_HORIZONTAL_FLIP
		if(--mask1_x_off < 0)
		{
			mask1_x_off = advancer1;
			mask1data -= feature->featureMask1->depth;
#else
		if(++mask1_x_off & advancer1)
		{
			mask1_x_off = 0;
			mask1data += feature->featureMask1->depth;
#endif

			int mix0, mix1, mix00, mix01, mix10, mix11;

			mix00 = *mask1data;
			mix01 = *(mask1data + 1);
			mix10 = *(mask1data + pitch1);
			mix11 = *(mask1data + pitch1 + 1);

			mix0 = (mix00*(z1_stretch - mask1_z_off) + mix10*mask1_z_off);
			mix1 = (mix01*(z1_stretch - mask1_z_off) + mix11*mask1_z_off);

			mixH1 = (mix0*(x1_stretch - mask1_x_off) + mix1*mask1_x_off);

			adv1 = mix1 - mix0;
		}
	}
}
