Exemplo n.º 1
0
Texture SetTexture( char *imagePath)
{
	if (!Glew_Initialized){
		bool res = ReloadGlew();
		Glew_Initialized = true;
	}
	Texture texture = {};
	unsigned long TextureWidth, TextureHeight;

	std::vector<unsigned char> image;
	DataFile file;
	LoadFile(imagePath, &file);
	unsigned char *data = (unsigned char*)file.Data;
	decodePNG(image, TextureWidth, TextureHeight, (unsigned char*)file.Data, file.Length);
	glGenTextures(1, &texture.TextureHandle);

	glBindTexture(GL_TEXTURE_2D, texture.TextureHandle);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(image[0]));

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glGenerateMipmap(GL_TEXTURE_2D);
	GLenum error = glGetError();

	glBindTexture(GL_TEXTURE_2D, 0);

	return texture;
}
Exemplo n.º 2
0
bool PNG_Pico_Loader::decode(ResourceLoadOptions& options)
{
	std::vector<byte> data;
	StreamRead((Stream*) &stream, data);

	if( data.empty() ) return false;

	uint32 width, height;
	std::vector<byte> buffer;
	
	decodePNG(buffer, width, height, &data[0], data.size());

	//flip( buffer, width, height );

	// Build our image with the data. The pixel format returned by picoPNG
	// is always the same, 32bits per pixel, RGBA 8 bits per component.

	Image* image = static_cast<Image*>( res );
	image->setPixelFormat( PixelFormat::R8G8B8A8 );
	image->setWidth( width );
	image->setHeight( height );
	image->setBuffer( buffer );

	return true;
}
Exemplo n.º 3
0
int loadPNG(char* filename, unsigned char** dest, unsigned long* w, unsigned long* h)
{
	CFIMM F;
	F.Open(filename);
	if(!F.Addr())
		return 0;
	int fsize=F.GetSize();
	ppng::varray<unsigned char> out;
	if(decodePNG(out, *w, *h, (const unsigned char*)F.CAddr(), F.GetSize()))
		return 0;
	if(*w&&*h)
		*dest=new unsigned char[*w**h*4];
	for(unsigned int i=0; i<*h; i++)
	{
		int ni=*h-i-1;
		for(unsigned int j=0; j<*w; j++)
		{
			(*dest)[i*4**w+j*4+0]=out[ni*4**w+j*4+2];
			(*dest)[i*4**w+j*4+1]=out[ni*4**w+j*4+1];
			(*dest)[i*4**w+j*4+2]=out[ni*4**w+j*4+0];
			(*dest)[i*4**w+j*4+3]=out[ni*4**w+j*4+3];
		}
	}
	return 1;
}
Exemplo n.º 4
0
        Texture TextureCache::loadPNG(const std::string& filePath) const
        {

            //create empty texture object
            Texture texture = {};
            std::vector<unsigned char> out;
            unsigned long width, height;
            std::vector<unsigned char> in;
            if (Utils::fileIO::readFileToBuffer(filePath, in) == false)
                std::cout << "Failed to Load " + filePath + " into buffer\n";

            int error = decodePNG(out, width, height, &(in[0]), in.size());

            if (error != 0)
                std::cout << "Could not decode PNG: " + std::to_string(error)<< "\n";

            glGenTextures(1, &(texture.id));

            glBindTexture(GL_TEXTURE_2D, texture.id);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(out[0]));
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

            glGenerateMipmap(GL_TEXTURE_2D);

            glBindTexture(GL_TEXTURE_2D, 0);


            texture.width = width;
            texture.height = height;
            return texture;

        }
Exemplo n.º 5
0
HBITMAP LoadFromPNG(LPCSTR pszFilename)
{
    if (pszFilename == NULL)
    {
        return NULL;
    }
    
    //load and decode
    std::vector<unsigned char> buffer, image, palette;
    
    loadFile(buffer, pszFilename);
    
    if (buffer.empty())
    {
        return NULL;
    }
    
    unsigned long w, h;
    int error = decodePNG(image, w, h, &buffer[0],
        static_cast<unsigned long>(buffer.size()));
    
    if (error != 0)
    {
        return NULL;
    }
    
    if (image.size() <= 4)
    {
        return NULL;
    }
    
    BITMAPINFO bmi = { {0} };
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = w;
    bmi.bmiHeader.biHeight = h;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biCompression = BI_RGB;
    
    unsigned char* bits;
    std::vector<unsigned char> bgra;
    
    HBITMAP hDibSection = CreateDIBSection(
        NULL, &bmi, 0, reinterpret_cast<LPVOID*>(&bits), NULL, 0);
    
    for (int i = static_cast<int>(image.size()) - w*4; i >= 0; i -= w*4)
    {
        for (unsigned long j = 0; j < w*4; j += 4)
        {
            bgra.push_back(image[i + j + 2]); // blue
            bgra.push_back(image[i + j + 1]); // green
            bgra.push_back(image[i + j]);     // red
            bgra.push_back(image[i + j + 3]); // alpha
        }
    }
    
    memcpy(bits, &(bgra[0]), bgra.size());
    
    return hDibSection;
}
Exemplo n.º 6
0
	GLTexture ImageLoader::loadPNG(std::string filePath) {
		GLTexture texture = {}; //initializes everything to zero

		std::vector<unsigned char> in;
		std::vector<unsigned char> out;
		unsigned long width, height;

		if (!IOManager::readFileToBuffer(filePath, in)) {
			fatalError("Failed to load PNG file to buffer!");
		}

		int errorCode = decodePNG(out, width, height, &(in[0]), in.size());
		if (errorCode != 0) {
			fatalError("decodePNG failed with error: " + errorCode);
		}

		glGenTextures(1, &(texture.id));
		glBindTexture(GL_TEXTURE_2D, texture.id);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(out[0]));

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

		glGenerateMipmap(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, 0);

		texture.width = width;
		texture.height = height;

		return texture;
	}
Exemplo n.º 7
0
s32 pngLoadFromFile(const char *filename,pngData *out)
{
	pngDecSource source;

	memset(&source,0,sizeof(pngDecSource));

	source.stream = PNGDEC_FILE;
	source.file_name = __get_addr32(filename);
	source.enable = PNGDEC_DISABLE;

	return decodePNG(&source,out);
}
Exemplo n.º 8
0
s32 pngLoadFromBuffer(const void *buffer,u32 size,pngData *out)
{
	pngDecSource source;

	memset(&source,0,sizeof(pngDecSource));

	source.stream = PNGDEC_BUFFER;
	source.stream_ptr = __get_addr32(buffer);
	source.stream_size = size;
	source.enable = PNGDEC_DISABLE;

	return decodePNG(&source,out);
}
GLTexture ImageLoader::loadPNG(std::string filePath)
{
	//Luodaan GLTexture ja alustetaan kaikki nollaan
	GLTexture texture = {};

	//Syöttödata decodePNG:lle
	std::vector<unsigned char> in;
	//Ulostulo decodePNG:ltä, joka on pikselidata tekstuurille
	std::vector<unsigned char> out;

	unsigned long width, height;

	//Luetaan kuva tiedoston sisältö bufferiin
	if (IOManager::readFileToBuffer(filePath, in) == false)
	{
		fatalError("Failed to load PNG file to buffer!");
	}

	//Dekoodataan .png formaatti pikselitaulukoksi
	int errorCode = decodePNG(out, width, height, &(in[0]), in.size());
	if (errorCode != 0)
	{
		fatalError("decodePNG failed with error: " + std::to_string(errorCode));
	}

	//Generoidaan openGL tekstuuri objekti
	glGenTextures(1, &(texture.id));

	//Bindataan tekstuuri objekti
	glBindTexture(GL_TEXTURE_2D, texture.id);
	//Ladataan pikselit tekstuuriin
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(out[0]));

	//Asetetaan tekstuuri parametrit
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

	//Generoidaan mipmapit
	glGenerateMipmap(GL_TEXTURE_2D);

	//Unbindataan tekstuuri
	glBindTexture(GL_TEXTURE_2D, 0);

	texture.width = width;
	texture.height = height;

	//Palautetaan kopio tekstuuridatasta
	return texture;
}
Exemplo n.º 10
0
GLTexture ImageLoader::loadPNG(std::string filePath) {
	// Create a GLTexture and initialize all its fields to 0
	GLTexture texture = {};

	// This is the input data to decodePNG, which we load from a file.
	std::vector<unsigned char> in;
	// This is the output data from decodePNG, which is the pixel data for our texture.
	std::vector<unsigned char> out;

	unsigned long width, height;

	// Read in the image file contents into a buffer.
	if (IOManager::readFileToBuffer(filePath, in) == false)
	{
		fatalError("Failed to load PNG file to buffer!");
	}

	// Decode the .png format into an array of pixels.
	int errorCode = decodePNG(out, width, height, &(in[0]), in.size());
	if (errorCode != 0)
	{
		fatalError("decodePNG failed with error: " + std::to_string(errorCode));
	}

	// Generate the OpenGL texture object.
	glGenTextures(1, &(texture.id));

	// Bind the texture object.
	glBindTexture(GL_TEXTURE_2D, texture.id);
	// Upload the pixels to the texture.
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(out[0]));

	// Set some texture parameters.
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	// Generate the mipmaps.
	glGenerateMipmap(GL_TEXTURE_2D);

	// Unbind the texture.
	glBindTexture(GL_TEXTURE_2D, 0);

	texture.width = width;
	texture.height = height;

	// Return a copy of the texture data.
	return texture;
}
Exemplo n.º 11
0
Texture Loader::loadPNG(const std::string& filePath)
{
	Texture texture;

	std::vector<unsigned char> in;
	std::vector<unsigned char> out;

	unsigned long width, height;

	if (loadFile(filePath, in) == false) {
		printf("Failed to load file to buffer");
	}

	printf("Loading texture...\n");

	int errorCode = decodePNG(out, width, height, in.data(), in.size());

	if (errorCode != 0) {
		printf("decodePNG failed with error: %s", std::to_string(errorCode));
	}

	glGenTextures(1, &(texture.id));

	glBindTexture(GL_TEXTURE_2D, texture.id);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, out.data());

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

	glGenerateMipmap(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, 0);

	texture.width = width;
	texture.height = height;
	texture.filePath = filePath;

	printf("Texture %s loaded\n", filePath.c_str());

	return texture;
}
Exemplo n.º 12
0
GLTexture ImageLoader::loadPNG(std::string filePath) {
	GLTexture texture = {}; // initialize everything to zero
	std::vector<unsigned char> in;
	std::vector<unsigned char> out;

	unsigned long width,height;

	if (IOManager::readFileToBuffer(filePath,in) == false) {
		Errors::fatalError("Failed to load PNG file "+filePath+" to buffer.",nullptr);
	}



	int errorCode = decodePNG(out,width,height,&(in[0]),in.size());

	texture.width = width;
	texture.height = height;

	if(errorCode != 0) { // for a non-zero error code
		Errors::fatalError("picopng's decodePNG failed with error code "+ std::to_string(errorCode), nullptr);
	}


	glGenTextures(1,&(texture.id));

	glBindTexture(GL_TEXTURE_2D, texture.id);

	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,&(out[0]));

	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

	glGenerateMipmap(GL_TEXTURE_2D);

	//Unbind the texture
	glBindTexture(GL_TEXTURE_2D, texture.id);

	return texture;
}
Exemplo n.º 13
0
	GLTexture ImageLoader::loadPNG(const std::string& filePath)
	{
		GLTexture texture = {};

		std::vector<unsigned char> in;
		std::vector<unsigned char> out;
		unsigned long w, h;

		if (!IOManager::readFileToBuffer(filePath, in))
		{
			fatalError("Failed to load PNG file to buffer!");
		}
		int errorCode = decodePNG(out, w, h, &(in[0]), in.size());
		if (errorCode != 0)
		{
			fatalError("decodePNG failed with error: " + std::to_string(errorCode));
		}

		glGenTextures(1, &texture.id);

		glBindTexture(GL_TEXTURE_2D, texture.id);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &out[0]);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

		glGenerateMipmap(GL_TEXTURE_2D);


		glBindTexture(GL_TEXTURE_2D, 0);

		texture.w = w;
		texture.h = h;

		return texture;
	}
Exemplo n.º 14
0
	GLTexture Texture::LoadPNG(const std::string& filePath)
	{
		GLTexture texture = {};

		std::vector<unsigned char> output;
		std::vector<unsigned char> input;

		unsigned long width, height;

		if (IOInterface::FileToBuffer(filePath, input) == false)
		{
			PrintError("Failed to load PNG file to buffer: %s", SDL_GetError());
		}

		int errorCode = decodePNG(output, width, height, &(input[0]), input.size());
		if (errorCode != 0)
		{
			PrintError("DecodePNG failed with error: %s", SDL_GetError());
		}

		glGenTextures(1, &(texture.TextureID));
		glBindTexture(GL_TEXTURE_2D, texture.TextureID);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(output[0]));

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

		glGenerateMipmap(GL_TEXTURE_2D);

		glBindTexture(GL_TEXTURE_2D, 0);

		texture.width = width;
		texture.height = height;

		return texture;
	}
Exemplo n.º 15
0
ModifiableTexture::ModifiableTexture(std::string filename) {
	GdtResource res = GdtResource(filename);
	if(!res.isValid()) {
		mTextureID = -1;
		return;
	}

	std::vector<unsigned char> decodedData;
	unsigned long width;
	unsigned long height;
	int decodeStatus = decodePNG(decodedData, width, height, (const unsigned char *) res.getBytes(), res.getLength());

	mWidth = width;
	mHeight = height;

	gdt_log(LOG_NORMAL, TAG, "Decoded PNG with status %d and got data of size %d.", decodeStatus, decodedData.size());

	unsigned char *data = &decodedData[0];

	gdt_log(LOG_NORMAL, TAG, "(1)");

	mData = (pixel *) calloc(width*height, sizeof(pixel));

	gdt_log(LOG_NORMAL, TAG, "(2)");

	memcpy(mData, data, width*height*sizeof(pixel));

	gdt_log(LOG_NORMAL, TAG, "(3)");

	uploadAndCreateTexture();

	gdt_log(LOG_NORMAL, TAG, "(4)");

	sTextures.push_back(this);

	gdt_log(LOG_NORMAL, TAG, "(5)");
}
Exemplo n.º 16
0
CoreEngine::GLTexture CoreEngine::ImageLoader::loadPNG(const std::string& filePath) {
	GLTexture texture = {}; //init everything to zero

	std::vector<unsigned char> in;
	std::vector<unsigned char> out;
	unsigned long width, height;

	if (!IOManager::readFileToBuffer(filePath, in)) {
		fatalError("Failed to load PNG file to buffer");
	}

	int errorCode = decodePNG(out, width, height, &in[0], in.size());
	if (errorCode) {
		fatalError("Decode PNG failed with error: " + std::to_string(errorCode));
	}

	//generate the pointer to the id of the texture
	glGenTextures(1, &texture.id);

	glBindTexture(GL_TEXTURE_2D, texture.id);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &out[0]);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

	glGenerateMipmap(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, 0);

	texture.width = width;
	texture.height = height;

	return texture;
}
Exemplo n.º 17
0
//--------------------------------------------------
int Texture::loadPNGFile(string pngName, bool nearest)
{

	ErrorLog *log = ErrorLog::getInstance();
	stringstream logStream;

	logStream << "Load PNG Texture " << pngName.c_str() << endl;
	log->reportError(logStream.str());

	string filename;
	filename = "./Daten/Textures/";
	filename.append(pngName);
	filename.append(".png");

	//load and decode
	std::vector<unsigned char> buffer, image;
	if (getPNGFile(buffer, filename) == -1)
	{
		logStream.str("");
		logStream << "error, png file " << pngName.c_str() << " not found!" << std::endl;
		log->reportError(logStream.str());
		return -1;
	}
	unsigned long w, h;
	int error = decodePNG(image, w, h, buffer.empty() ? 0 : &buffer[0], (unsigned long)buffer.size());

	//if there's an error, display it
	if (error != 0)
	{
		logStream.str("");
		logStream << "error!: " << error << std::endl;
		log->reportError(logStream.str());
		return -1;
	}

	//the pixels are now in the vector "image", use it as texture, draw it, ...

	//if(image.size() > 4) std::cout << "width: " << w << " height: " << h << " first pixel: " << std::hex << int(image[0]) << int(image[1]) << int(image[2]) << int(image[3]) << std::endl;

	unsigned int texture;

	glGenTextures(1, &texture);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	if (nearest)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	}
	else
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	}

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]);	//copy the image into the texture

	return texture;

}
Exemplo n.º 18
0
/** main */
int main()
{
    // GLFW and GLEW initialization
    glfwInit();

    // Core profile
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    // Window creation
    pWindow = glfwCreateWindow(1280, 720, "PerVoxelRaycaster", NULL, NULL);
    if (!pWindow)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    glfwMakeContextCurrent(pWindow);
    ogl_LoadFunctions();
    glfwSetCursorPosCallback(pWindow, cursorCallback);
    glfwSetMouseButtonCallback(pWindow, buttonsCallback);
    glfwSetScrollCallback(pWindow, scrollCallback);

    // OpenGL initialization
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.0f, 0.0f, 0.0f, 1);

    // Setup shader

    // ### CHOOSE FROM ONE OF THESE THREE SHADERS ###
    //shader.loadShaders("Raycaster.vert", "SimpleRaycaster.frag");
    //shader.loadShaders("Raycaster.vert", "SimplePerVoxelRaycaster.frag");
    shader.loadShaders("Raycaster.vert", "PerVoxelRaycaster.frag");

    shader.setVertexBuffer(cube::vertices, sizeof(cube::vertices), "positionAttribute");
    uniformModelHandle= shader.getUniformHandle("uniformModel");
    uniformViewHandle= shader.getUniformHandle("uniformView");
    uniformProjectionHandle = shader.getUniformHandle("uniformProjection");
    uniformCameraPositionHandle= shader.getUniformHandle("uniformCameraPosition");
    uniformVolumeHandle= shader.getUniformHandle("uniformVolume");
    uniformTransferfunctionHandle= shader.getUniformHandle("uniformTransferfunction");
    shader.use();

    // Initialize camera
    camera.init(glm::vec3(0.5f), glm::radians(-135.0f), glm::radians(80.0f), 2, 0.5f, 5);

    // Other initializations
    prevCursorX = cursorX;
    prevCursorY = cursorY;

    // Read volume
    const GLuint volumeX = 256;
    const GLuint volumeY = 256;
    const GLuint volumeZ = 256;

    GLuint voxelCount = volumeX * volumeY * volumeZ;
    GLubyte* volumeData = new GLubyte[voxelCount];
    std::ifstream rawDataFile(std::string(RESOURCES_PATH) + "/bonsai.raw", std::ios::in|std::ios::binary);
    rawDataFile.read((GLchar*)volumeData, static_cast<GLuint>(voxelCount) * sizeof(GLubyte));

    // Create volume 3D texture
    glGenTextures(1, &uniformVolume);
    glBindTexture(GL_TEXTURE_3D, uniformVolume);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, volumeX, volumeY, volumeZ, 0, GL_RED, GL_UNSIGNED_BYTE, volumeData);
    glBindTexture(GL_TEXTURE_3D, 0);
    delete[] volumeData;

    // Set volume in shader
    shader.setUniformTexture(uniformVolumeHandle, uniformVolume, GL_TEXTURE_3D);

    // Read transfer function
    std::vector<GLubyte> transferfunction;
    unsigned long transferfunctionX;
    unsigned long transferfunctionY;

    std::ifstream in(std::string(std::string(RESOURCES_PATH) + "/Transferfunction.png").c_str(), std::ios::in|std::ios::binary);
    in.seekg(0, std::ios::end);
    std::streamsize size = in.tellg();
    in.seekg(0, std::ios::beg);
    std::vector<GLchar> buffer(static_cast<GLuint>(size));
    in.read(&(buffer[0]), static_cast<size_t>(size));
    in.close();
    decodePNG(transferfunction, transferfunctionX, transferfunctionY, reinterpret_cast<GLubyte*>(&(buffer[0])), static_cast<size_t>(size), GL_FALSE);

    // Create transfer function 1D texture
    glGenTextures(1, &uniformTransferfunction);
    glBindTexture(GL_TEXTURE_1D, uniformTransferfunction);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, transferfunctionX, 0, GL_RGBA, GL_UNSIGNED_BYTE, &transferfunction[0]);
    glBindTexture(GL_TEXTURE_1D, 0);

    // Set transfer function in shader
    shader.setUniformTexture(uniformTransferfunctionHandle, uniformTransferfunction, GL_TEXTURE_1D);

    // Loop
    while(!glfwWindowShouldClose(pWindow))
    {
        // Clear buffers
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

        // Get window resolution
        GLint width, height;
        glfwGetWindowSize(pWindow, &width, &height);

        // Give OpenGL the window resolution
        if(width != prevWidth || height != prevHeight)
        {
            glViewport(0, 0, width, height);
            prevWidth = width;
            prevHeight = height;
        }

        // Calc time per frame
        GLfloat currentTime = (GLfloat)glfwGetTime();
        deltaTime = currentTime - prevTime;
        prevTime = currentTime;

        std::cout << 1.0f / deltaTime << std::endl;

        // Calculate cursor movement
        cursorDeltaX = cursorX - prevCursorX;
        cursorDeltaY = cursorY - prevCursorY;
        prevCursorX = cursorX;
        prevCursorY = cursorY;

        // Model matrix
        uniformModel = glm::mat4(1.0f);

        // View matrix
        if(buttonPressed)
        {
            camera.setAlpha(camera.getAlpha() + 0.005f * cursorDeltaX);
            camera.setBeta(camera.getBeta() - 0.005f * cursorDeltaY);
        }
        uniformView = camera.getViewMatrix();

        // Projection matrix
        uniformProjection = glm::perspective(glm::radians(30.f), ((GLfloat)width/(GLfloat)height), 0.1f, 100.f);

        // Set updated uniforms in shader
        shader.setUniformValue(uniformModelHandle, uniformModel);
        shader.setUniformValue(uniformViewHandle, uniformView);
        shader.setUniformValue(uniformProjectionHandle, uniformProjection);
        shader.setUniformValue(uniformCameraPositionHandle, camera.getPosition());

        // Draw cube
        shader.draw(GL_TRIANGLES);

        // GLFW updates
        glfwSwapBuffers(pWindow);
        glfwPollEvents();
    }

    // Clean up
    glfwDestroyWindow(pWindow);
    glfwTerminate();

    return 0;
}