/src/Shader.cpp
#include "Shader.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Shader::Shader(void) {
}

Shader::~Shader(void) {
}

GLuint Shader::compileShader(const char *code, GLenum type) {
	int status;
	GLuint shader;

	shader = glCreateShader(type);
	glShaderSource(shader, 1, &code, NULL);
	glCompileShader(shader);

	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status != GL_TRUE) {
		char log[4096];
		int len;

		glGetShaderInfoLog(shader, 4096, &len, log);
		printf("Shader compilation failed:\n%s\n", log);
		exit(1);
	}
	return shader;
}

void Shader::linkProgram() {
	int status;

	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status);
	if (status != GL_TRUE) {
		char log[4096];
		int len;

		glGetProgramInfoLog(shaderProgram, 4096, &len, log);
		printf("Shader program link failed:\n%s\n", log);
	}
}

void Shader::basicInit() {
	// uniforms
	uProjection = glGetUniformLocation(shaderProgram, "Projection");
	uTransform = glGetUniformLocation(shaderProgram, "Transform");

	// attributes
	aPosition = glGetAttribLocation(shaderProgram, "Position");
	glEnableVertexAttribArray(aPosition);

	this->resetTransform();
}

void Shader::useProgram() {
	glUseProgram(shaderProgram);
}

void Shader::setProjection(GLfloat *matrix) {
	glUniformMatrix4fv(uProjection, 1, GL_FALSE, matrix);
}

void Shader::setTransform(GLfloat *matrix) {
	glUniformMatrix4fv(uTransform, 1, GL_FALSE, matrix);
}

void Shader::setTranslation(int x, int y) {
	memset(transform, 0, sizeof(transform));
	transform[0][0] = 1;
	transform[1][1] = 1;
	transform[2][2] = 1;
	transform[3][3] = 1;
	transform[3][0] = x;
	transform[3][1] = y;
	this->setTransform((GLfloat *)transform);
}

void Shader::resetTransform() {
	static GLfloat identity[16] = {
		1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f
	};
	this->setTransform(identity);
}

void Shader::setPositions(int count, GLshort *positions) {
	glVertexAttribPointer(aPosition, 2, GL_SHORT, GL_FALSE, 0, positions);
}