package GLSLPost;

sub new($$) {
	my ($class) = @_;
	
	my $self = {};
	
	bless($self);
	
	return $self;
}

sub SetParams($$) {
	my  ($self, $params) = @_;
	
	$image = defined($params->{"fname"}) ? $params->{"fname"} : "";

	if(!defined($params->{"vertex"}) || !defined($params->{"fragment"})) {
		print "Vertex or fragment not specified for GLSLPost post-processing effect\n";
	}
	
	$self->{"uniform"} = {};
	
	foreach $key (keys %{$params}) {
		if($key eq "vertex" || $key eq "fragment") {
			next;
		}
		
		$self->{"uniform"}->{$key} = $params->{$key};
	}
	
	if(!defined($self->{"vertex"}) && defined($params->{"vertex"})) {
		open(VERTEX, $params->{"vertex"}) or print "Unable to read " . $params->{"vertex"}. " vertex program\n";
		my @vertex = <VERTEX>;
		my $vertex = join("\n", @vertex);
		close(VERTEX);
		
		open(FRAGMENT, $params->{"fragment"}) or print "Unable to read " . $params->{"fragment"} . " fragment program\n";
		my @fragment = <FRAGMENT>;
		my $fragment = join("\n", @fragment);
		close(FRAGMENT);

		$self->{"glsl"} = new GLSL($vertex, $fragment);
		$self->{"vertex"} = $params->{"vertex"};
		$self->{"fragment"} = $params->{"fragment"};
	}
	
	$self->{"engine"} = new GLSLQuad($image);

	if(defined($params->{"additive"})) {
		$self->{"additive"} = $params->{"additive"}		
	} else {
		$self->{"additive"} = 0;
	}
	
	if(defined($params->{"scale"})) {
		$self->{"scale"} = $params->{"scale"}		
	} else {
		$self->{"scale"} = 0;
	}

	if(defined($params->{"alpha"})) {
		$self->{"alpha"} = $params->{"alpha"}		
	} else {
		$self->{"alpha"} = 0;
	}
}

# Because this is a post-processing engine, GL_TEXTURE_2D is pre-bound to the source
# texture. That's the only difference with a normal renderer

sub Render($$) {
	my ($self, $msec) = @_;
	
	if(defined($self->{"glsl"})) {
		# Enable glsl shader
		$self->{"glsl"}->Bind();

		# Setup uniforms
		foreach $param (keys %{$self->{"uniform"}}) {
			if(ref($self->{"uniform"}->{$param}) eq "ARRAY") {
				# Got a vector type
				
				@values = @{$self->{"uniform"}->{$param}};

				if(@values == 1) {	
					$self->{"glsl"}->SetUniform1F($param,@values);
				} elsif(@values == 2) {
					$self->{"glsl"}->SetUniform2F($param,@values);
				} elsif(@values == 3) {
					$self->{"glsl"}->SetUniform3F($param,@values);
				} elsif(@values == 4) {
					$self->{"glsl"}->SetUniform4F($param,@values);
				}
			} else {
				# Got a float type
				$self->{"glsl"}->SetUniform1F($param,$self->{"uniform"}->{$param});
			}
		}

		$self->{"glsl"}->SetUniform1i("source", 0);
		$self->{"glsl"}->SetUniform1i("image", 1);

		# used in noise only
		$self->{"glsl"}->SetUniform1i("xrand", int(rand(2))*2)-1; # -1 or 1
		$self->{"glsl"}->SetUniform1i("yrand", int(rand(2))*2)-1; # -1 or 1
	}
		
	$self->{"engine"}->Render($self->{"additive"}, $self->{"scale"}, $self->{"alpha"});	
	if(defined($self->{"glsl"})) {
		$self->{"glsl"}->Unbind();
		# Back to non-shader mode
	}
}

1;
