void sendDataToGL()
	{
		std::vector<float> lut;
		int lutSize = mTable->GetNumberOfTuples();
		int lutDataSize = lutSize * mTable->GetNumberOfComponents();
		lut.resize(lutDataSize);
		unsigned char* ptr = mTable->GetPointer(0);

		for (int i = 0; i < lut.size(); ++i)
		{
			lut[i] = ((float) *ptr) / 255.0;
			++ptr;
		}

		glBindTexture(GL_TEXTURE_1D, textureId);
		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 );
		report_gl_error();

		glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA,
					 lutSize, 0,
					 GL_RGBA, GL_FLOAT, &(*lut.begin()));
		report_gl_error();
	}
void ShaderCallback::addUniformfArray(vtkShaderProgram *program, std::string name, float value)
{
	//Note: Set uniform will fail if the uniform is not present OR active (used inside the program).
	report_gl_error();

	//CX_LOG_DEBUG() << "Adding uniform called: " << name << " with value " << value;
	if(!program->SetUniform1fv(name.c_str(), 1, &value))
	{
		CX_LOG_ERROR() << "Could not set uniform named " << name;
	}

	report_gl_error();
}
void ShaderCallback::test( unsigned long event, void *cbo)
{
	std::cout << " START TEST" << std::endl;
	if(event == vtkCommand::UpdateShaderEvent)
	{
		std::cout << "--- START UpdateShaderEvent" << std::endl;
		vtkOpenGLHelper *cellBO = reinterpret_cast<vtkOpenGLHelper*>(cbo);
		report_gl_error();

		if(cellBO && cellBO->VAO)
		{
			report_gl_error();

			vtkShaderProgram *program = cellBO->Program;
			vtkOpenGLVertexArrayObject *vao = cellBO->VAO;

			std::cout << "Program is compiled? " << program->GetCompiled() << std::endl;
			std::cout << "Program is bound? " << program->isBound() << std::endl;
			std::cout << "IBO index count " << cellBO->IBO->IndexCount << std::endl;
			report_gl_error();


			GLint color_frag_out_index = glGetFragDataLocation(cellBO->Program->GetHandle(), "color");
			std::cout << "color index " << color_frag_out_index << std::endl;
			glBindFragDataLocation(cellBO->Program->GetHandle(), color_frag_out_index, "color"); //setting output of fragment shader


			std::cout << "ADDING ATTRIBUTE ARRAY" << std::endl;
			/*
			vao->Bind();
			if (!vao->AddAttributeArray(program, vbo.Get(), "vertexMC", 0, sizeof(float)*3, VTK_FLOAT, 3, false))
			{
				vtkGenericWarningMacro(<< "Error setting 'vertexMC' in shader VAO.");
			}
			 */
			vao->Bind();
			//Input color
			int vec_size = 3;
			if (!vao->AddAttributeArray(
						program,		//vtkShaderProgram
						mColorBufferObject.Get(),	//vtkOpenGLBufferObject
						"COLOR_VSIN",	//std::string
						0,				//int (offset)				where to start reading g_color_buffer_data, offset != 0 == discard some of the first values
						sizeof(float)*3,				//size_t (stride)			If stride is 0, the generic vertex attributes are understood to be tightly packed in the array.
						VTK_FLOAT,		//int (elementType)			Specifies the data type of each component in the array
						vec_size,				//int (elementTupleSize)	Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4.
						false			//bool (normalize)
						))
			{
				vtkGenericWarningMacro(<< "Error setting 'COLOR' in shader VAO.");
			}
	virtual void bind(int textureUnitIndex)
	{
		this->updateTexture();
		if (!mAllocated)
		{
			std::cout << "error: called bind() on unallocated lut buffer" << std::endl;
			return;
		}
		glActiveTexture(getGLTextureForLut(textureUnitIndex));
		this->bindDataToGL();
		report_gl_error();
	}
	virtual void updateTexture()
	{
		if (mMTime == mTable->GetMTime())
		{
			return;
		}
		mMTime = mTable->GetMTime();

		glActiveTexture(GL_TEXTURE6);
		this->sendDataToGL();
		report_gl_error();
	}
	/**Activate and bind the volume and lut buffers inside the texture units
	 * GL_TEXTURE<2X> and GL_TEXTURE<2X+1>.
	 * Use during RenderInternal()
	 */
	virtual void bind(int textureUnitIndex)
	{
		this->updateTexture();
		if (!mAllocated)
		{
			std::cout << "error: called bind() on unallocated volume buffer" << std::endl;
			return;
		}
		glActiveTexture(getGLTextureForVolume(textureUnitIndex));
		glBindTexture(GL_TEXTURE_3D, textureId);
		report_gl_error();
	}
/**
 * @brief ShaderCallback::addArrayToAttributeArray
 * In the vertex shader there is an in array of vec3 which will contain texture coordinates per uploaded texture. This function populates this array.
 * @param program The shader program to work with.
 * @param buffer The buffer containing the texture coordinates.
 * @param name The name of the array variable in the vertex shader which will point to the texture coordinates.
 * @param vector_index The place in the
 */
void ShaderCallback::addArrayToAttributeArray(vtkShaderProgram *program, vtkOpenGLBufferObjectPtr buffer, std::string name, int vector_index)
{
	//--------
	//This is information about how the texture coordinates are uploaded.
	int offset = 0;
	int vec_size = 3;
	size_t stride = sizeof(float)*vec_size; //is this correct? was *3;
	int elementType = GL_FLOAT; //VTK_FLOAT
	bool normalize = false;

	//CX_LOG_DEBUG() << "Adding attribute called: " << name << " to vector_index: " << vector_index;
	//--------

	const GLchar *namePtr = static_cast<const GLchar *>(name.c_str());
	GLint start_of_vector_index = glGetAttribLocation(program->GetHandle(), namePtr);
	report_gl_error();


	if(start_of_vector_index != -1)
	{
		GLint position_in_vector_index = start_of_vector_index + vector_index;
		buffer->Bind();

		glEnableVertexAttribArray(position_in_vector_index);

		glVertexAttribPointer(position_in_vector_index,
				      vec_size,
				      elementType,
				      normalize,
				      static_cast<GLsizei>(stride),
				      ((char *)NULL + (offset))
				     );
		report_gl_error();
	}
	else
	{
		CX_LOG_ERROR() << "Error setting attribute " << name << " with vector_index " << vector_index;
	}

}
/**
 * @name	core_check_gl_error
 * @brief	check's for a gl error and reports it to the platform
 * @retval	NONE
 */
void core_check_gl_error() {
	// check the gl error and send it to java to be logged
	int error_code = glGetError();

	if (error_code != 0) {
		LOG("{core} WARNING: OpenGL error %d", error_code);

		//check if we should report the error, return early if not.
		if (error_code == GL_ERROR_OUT_OF_MEMORY) {
			//does not matter if it is already in the hash, report as unrecoverable and respond
			report_gl_error(error_code, &gl_errors_hash, true);
			//use halfsized textures for lower memory footprint
			set_halfsized_textures(true);
		} else {
			//check if error is in the hash, if it is, leave
			gl_error *error = NULL;
			HASH_FIND_INT(gl_errors_hash, &error_code, error);

			if (!error) {
				report_gl_error(error_code, &gl_errors_hash, false);
			}
		}
	}
}
void ShaderCallback::printDebugInfo(vtkOpenGLHelper *OpenGLHelper)
{
	if(!OpenGLHelper)
	{
		return;
	}

	vtkShaderProgram *program = OpenGLHelper->Program;
	std::cout << "Program is compiled? " << program->GetCompiled() << std::endl;
	std::cout << "Program is bound? " << program->isBound() << std::endl;
	std::cout << "IBO index count " << OpenGLHelper->IBO->IndexCount << std::endl;
	std::string vertexshader = program->GetVertexShader()->GetSource();
	std::cout << "Vertexshader:\n " << vertexshader << std::endl;
	std::string fragmentshader = program->GetFragmentShader()->GetSource();
	std::cout << "Fragmentshader:\n " << fragmentshader << std::endl;
	report_gl_error();
}
void ShaderCallback::Execute(vtkObject *, unsigned long eventId, void *cbo)
{
	report_gl_error();

	vtkOpenGLHelper *OpenGLHelper = reinterpret_cast<vtkOpenGLHelper*>(cbo);

	if(!OpenGLHelper || !OpenGLHelper->VAO || !OpenGLHelper->Program)
	{
		return;
	}


	if(eventId == vtkCommand::UpdateShaderEvent)
	{
		report_gl_error();


		int textures_to_add = this->getNumberOfUploadedTextures();

		//Bind fragmentshader output variable
		// (glsl: vec4)
		if(textures_to_add != 0)
		{
			this->bindFSOutputVariable(OpenGLHelper->Program);
		}

		report_gl_error();

		//Bind VAO (Vertext Array Object - aka saved input to the vertex shader)
		OpenGLHelper->VAO->Bind();
		report_gl_error();

		for(int i=0; i< textures_to_add; ++i)
		{
			ShaderItemPtr shaderItem = mShaderItems.at(i);
			//	texture coordinates (glsl: vec3)
			vtkOpenGLBufferObjectPtr texture_coordinates = shaderItem->mTextureCoordinates;

			if(texture_coordinates)
			{
				if(!texture_coordinates->Bind())
				{
					CX_LOG_WARNING() << "Could not bind texture coordinates";
				}

				this->addArrayToAttributeArray(OpenGLHelper->Program, texture_coordinates, VS_In_Vec3_TextureCoordinate, i);
			}
			else
			{
				CX_LOG_WARNING() << "NO TEXTURE COORDINATES!";
			}

			report_gl_error();

			//	3D texture pointer (glsl: sampler3D)
			vtkTextureObjectPtr texture = shaderItem->mTexture;

			if(texture)
			{
				texture->Activate();
				this->addUniformiArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_3DTexture_Volume, i), texture->GetTextureUnit());
			}
			else
			{
				CX_LOG_WARNING() << "NO 3D TEXTURE!";
			}

			report_gl_error();

			//	1D texture pointer (glsl: sampler1D)
			vtkTextureObjectPtr lut = shaderItem->mLUT;

			if(lut)
			{
				lut->Activate();
				this->addUniformiArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_1DTexture_LUT, i), lut->GetTextureUnit());
			}
			else
			{
				CX_LOG_WARNING() << "NO 1D TEXTURE!";
			}

			report_gl_error();

			this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_Window,i), shaderItem->mWindow);
			this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_Level,i), shaderItem->mLevel);
			this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_LLR,i), shaderItem->mLLR);
			this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_Alpha,i), shaderItem->mAlpha);
		}
	}

	report_gl_error();

}
	virtual void updateTexture()
	{
		if (mMTime == mTexture->GetMTime())
		{
			return;
		}
		mMTime = mTexture->GetMTime();
		//vtkgl::ActiveTexture(getGLTextureForVolume(textureUnitIndex)); //TODO is this OK?
		GLenum size,internalType;
		boost::uint32_t dimx = mTexture ->GetDimensions( )[0];
		boost::uint32_t dimy = mTexture ->GetDimensions( )[1];
		boost::uint32_t dimz = mTexture ->GetDimensions( )[2];
		mMemorySize = dimx * dimy * dimz;

		glEnable( GL_TEXTURE_3D );
		glBindTexture(GL_TEXTURE_3D, textureId);
		report_gl_error();
		glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP );
		glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP );
		glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP );
		glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		switch (mTexture->GetScalarType())
		{
		case VTK_UNSIGNED_CHAR:
		{
			size = GL_UNSIGNED_BYTE;
			internalType = GL_LUMINANCE;
		}
			break; //8UI_EXT; break;
		case VTK_UNSIGNED_SHORT:
		{
			size = GL_UNSIGNED_SHORT;
			internalType = GL_LUMINANCE16;
			mMemorySize *= 2;
		}
			break; //16UI_EXT; break;
		default:
			size = 0;
			internalType = 0;
			std::cout << "Bit size not supported!" << std::endl;
			QString dataType(mTexture->GetScalarTypeAsString());
			CX_LOG_ERROR() << QString("Attempt to update 3D GL texture from type %1 failed. Only unsigned types supported").arg(dataType);
			break;
		}

		if (mTexture->GetNumberOfScalarComponents()==1)
		{
			void* data = mTexture->GetPointData()->GetScalars()->GetVoidPointer(0);
			glTexImage3D(GL_TEXTURE_3D, 0, internalType, dimx, dimy, dimz, 0, GL_LUMINANCE, size, data);
		}
		else if (mTexture->GetNumberOfScalarComponents()==3)
		{
			internalType = GL_RGB;
			void* data = mTexture->GetPointData()->GetScalars()->GetVoidPointer(0);
			glTexImage3D(GL_TEXTURE_3D, 0, internalType, dimx, dimy, dimz, 0, GL_RGB, size, data);
			mMemorySize *= 3;
		}
		else
		{
			std::cout << "unsupported number of image components" << std::endl;
		}

		glDisable(GL_TEXTURE_3D);

		report_gl_error();
	}