/*!
		\param e effect
		\param width width
		\param height height
		\param offsetTarget use offset target
	*/
	void render(const ProceduralEffect &e, float width, float height, bool offsetTarget)
	{
		if(e.texture1) {
			e.texture1->Apply(1);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
		}

		if(e.texture2) {
			e.texture2->Apply(3);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
		}

		if(offsetTarget)
		{
			if(e.distortion1)
				e.distortion1->Apply(0);
			if(e.distortion2)
				e.distortion2->Apply(2);

			if(!e.distortion1 || !e.distortion2 || !e.effect.enableDistortion)
				return;
		}
		else
		{
			if(e.offset1)
				e.offset1->Apply(0);
			if(e.offset2)
				e.offset2->Apply(2);
		}

		assert(vshader && pshader);
		vshader->apply();

		float constants[8 * 4];
		const TexCoord &c1 = (offsetTarget) ? e.displaceCoord1 : e.coord1;
		const TexCoord &c2 = (offsetTarget) ? e.displaceCoord2 : e.coord2;

		constants[0 + 0] = c1.offsetFactor.x;
		constants[0 + 1] = c1.offsetFactor.y;
		constants[4 + 0] = c1.offsetOffset.x;
		constants[4 + 1] = c1.offsetOffset.y;
		constants[8 + 0] = c1.baseFactor.x;
		constants[8 + 1] = c1.baseFactor.y;
		constants[12 + 0] = c1.baseOffset.x;
		constants[12 + 1] = c1.baseOffset.y;
		constants[16 + 0] = c2.offsetFactor.x;
		constants[16 + 1] = c2.offsetFactor.y;
		constants[20 + 0] = c2.offsetOffset.x;
		constants[20 + 1] = c2.offsetOffset.y;
		constants[24 + 0] = c2.baseFactor.x;
		constants[24 + 1] = c2.baseFactor.y;
		constants[28 + 0] = c2.baseOffset.x;
		constants[28 + 1] = c2.baseOffset.y;

		for (int i = 0; i < 8; i++) {
			glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, constants + (4 * i));
		}

		float scale1 = (offsetTarget) ? e.effect.distortion1.offset.scale.x : e.effect.source1.offset.scale.x;
		float scale2 = (offsetTarget) ? e.effect.distortion2.offset.scale.x : e.effect.source2.offset.scale.x;

		float param[4] = { scale1, 0, 0, 0 };
		glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param);
		param[0] = 0; param[1] = scale1;
		glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 1, param);

		param[0] = scale2; param[1] = 0;
		glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 3, param);
		param[0] = 0; param[1] = scale2;
		glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 4, param);

		if(offsetTarget)
		{
			poffsetShader->apply();

			float scale = (scale1 + scale2) * .25f;
			float c2[4] = { scale, scale, scale, scale };
			glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 2, c2);
		}
		else
		{
			pshader->apply();
		}

		vbuffer->apply(0);
		ibuffer->render(2, 4);

		frozenbyte::storm::PixelShader::disable();
	}