Exemplo n.º 1
0
void Sprite::setShaderProgram(ShaderProgram* shader_program)
{
    Drawable::setShaderProgram(shader_program);
    glBindVertexArray(s_VAO);
    glBindBuffer(GL_ARRAY_BUFFER, s_VBO);
    p_position_loc = shaderProgram()->bindVertexAttribute("position", 2, 3*sizeof(float), 0);
    p_texture_coord_loc = shaderProgram()->bindVertexAttribute("point_id", 1, 3*sizeof(float), (void *)(2 * sizeof(float)));
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}
Exemplo n.º 2
0
void initShader_texture ( ) {
    static bool uninitialized = true;
    if (uninitialized) {

        shaders[shader_texture] = shaderProgram(
            "src/shaders/texture_vertex.glsl",
            "src/shaders/texture_fragment.glsl"
        );
        if (shaders[shader_texture] == 0) {
            fprintf(stderr,"Texture Shader Error\n");
            exit(EXIT_FAILURE);
        }
        currentShader(shaders[shader_texture]);

        shaderPositions[shader_texture]    = glGetAttribLocation( shaders[shader_texture],"position");
        shaderColors[shader_texture]       = glGetAttribLocation( shaders[shader_texture],"color");
        CTvTexture                         = glGetAttribLocation( shaders[shader_texture],"texture_coordinate");
        CTtexture                          = glGetUniformLocation(shaders[shader_texture],"texture_map");
        shaderModels[shader_texture]       = glGetUniformLocation(shaders[shader_texture],"model");
        shaderViews[shader_texture]        = glGetUniformLocation(shaders[shader_texture],"view");
        shaderProjections[shader_texture]  = glGetUniformLocation(shaders[shader_texture],"projection");

        glUniformMatrix4fv(shaderModels[shader_texture]     ,1,GL_FALSE,glm::value_ptr(glm::mat4()));
        glUniformMatrix4fv(shaderViews[shader_texture]      ,1,GL_FALSE,glm::value_ptr(glm::mat4()));
        glUniformMatrix4fv(shaderProjections[shader_texture],1,GL_FALSE,glm::value_ptr(glm::mat4()));
        glUniform1i(CTtexture,0);
    }
    else {
        currentShader(0);
        glDeleteProgram(shaders[shader_texture]);
    }
    uninitialized = not uninitialized;
}
Exemplo n.º 3
0
void Rectangle::setShaderProgram(ShaderProgram* shader_program)
{
    Drawable::setShaderProgram(shader_program);
    glBindVertexArray(p_VAO);
    glBindBuffer(GL_ARRAY_BUFFER, p_VBO);
    p_position_loc = shaderProgram()->bindVertexAttribute("position", 2, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}
Exemplo n.º 4
0
void initialize() {
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    GLuint vbo;
    glGenBuffers(1, &vbo);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    std::string vertexShaderSource;
    if (!contentsOfFile("vertex.glsl", vertexShaderSource)) {
        exit(1);
    }

    std::string fragmentShaderSource;
    if (!contentsOfFile("fragment.glsl", fragmentShaderSource)) {
        exit(1);
    }

    Shader vertexShader(GL_VERTEX_SHADER);
    if (!vertexShader.compile(vertexShaderSource)) {
        debugPrint("Failed to compile vertex shader: %s", vertexShader.getCompileStatus().c_str());
        exit(1);
    }

    Shader fragmentShader(GL_FRAGMENT_SHADER);
    if (!fragmentShader.compile(fragmentShaderSource)) {
        debugPrint("Failed to compile fragment shader: %s", fragmentShader.getCompileStatus().c_str());
        exit(1);
    }

    Program shaderProgram(vertexShader, fragmentShader);
    if (!shaderProgram.link()) {
        debugPrint("Failed to link shader program: %s", shaderProgram.getLinkStatus().c_str());
        exit(1);
    }

    GLuint programID = shaderProgram.getGLID();
    glUseProgram(programID);

    GLint posAttrib = glGetAttribLocation(programID, "position");
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0);

    GLint colorAttrib = glGetAttribLocation(programID, "color");
    glEnableVertexAttribArray(colorAttrib);
    glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));

    glEnableVertexAttribArray(posAttrib);

    ball.setLeftPlayer(&leftPlayer);
    ball.setRightPlayer(&rightPlayer);
}
Exemplo n.º 5
0
void Sprite::draw()
{
    sf::Texture::bind(p_texture, sf::Texture::Normalized);
    glBindVertexArray(s_VAO);
    shaderProgram()->setUniform4f("texture_coords",
            static_cast<float>(p_rect.left)/static_cast<float>(p_texture->getSize().x),
            static_cast<float>(p_rect.top)/static_cast<float>(p_texture->getSize().y),
            static_cast<float>(p_rect.width)/static_cast<float>(p_texture->getSize().x),
            static_cast<float>(p_rect.height)/static_cast<float>(p_texture->getSize().y));
    shaderProgram()->setUniform4f("color",
            static_cast<float>(p_color.r)/255.0f,
            static_cast<float>(p_color.g)/255.0f,
            static_cast<float>(p_color.b)/255.0f,
            static_cast<float>(p_color.a)/255.0f);
    glEnableVertexAttribArray(p_position_loc);
    glEnableVertexAttribArray(p_texture_coord_loc);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    sf::Texture::bind(NULL);
}
Exemplo n.º 6
0
void Rectangle::draw()
{
    glBindVertexArray(p_VAO);
    shaderProgram()->setUniform4f("color",
            static_cast<float>(p_color.r)/255.0f,
            static_cast<float>(p_color.g)/255.0f,
            static_cast<float>(p_color.b)/255.0f,
            static_cast<float>(p_color.a)/255.0f);
    glEnableVertexAttribArray(p_position_loc);
    glDrawArrays(GL_TRIANGLES, 0, 6);
}
Exemplo n.º 7
0
void Model::draw(Camera * camera)
{
    shaderProgram()->setUniformMatrix4fv("projection", camera->projectionMatrix());
    shaderProgram()->setUniformMatrix4fv("view", camera->transformationMatrix());
    shaderProgram()->setUniformMatrix4fv("model", transformationMatrix());

    bindTextures();

    shaderProgram()->use();

    if (isWireframeMode())
    {
//          wireframe mode
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    }

    glBindVertexArray ( m_vaoId );

    if (geometry()->isExist("index"))
    {
        GeometryBuffer *indices = geometry()->get("index");
        indices->bind();
        glDrawElements(GL_TRIANGLES, indices->size(), GL_UNSIGNED_INT, 0);

    } else {
        glDrawArrays      ( GL_TRIANGLES, 0, geometry()->get("vertex")->size() );
    }

    glBindVertexArray ( 0 );

    if (isWireframeMode())
    {
//          wireframe mode
        glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
    }

    shaderProgram()->disable();

    unbindTextures();

}
Exemplo n.º 8
0
void Model::bindTextures()
{
    std::string textureName = "texture";
    for (GLuint i = 0; i < textures()->size(); i++)
    {
        glActiveTexture( GL_TEXTURE0 + i );
        Texture * texture = textures()->texture(i);
        if ( texture != nullptr )
        {
            glBindTexture(GL_TEXTURE_2D, texture->getId() );
            shaderProgram()->setUniform1i( textureName + patch::to_string(i), i );
        }
    }
}
Exemplo n.º 9
0
void HUDRenderer::render(const PlayerLogicComponent &playerLogic, int width, int height) {
   ASSERT(width > 0 && height > 0, "Width and height must be positive");

   for (HUDElement &element : elements) {
      element.update(playerLogic);
      textureMaterial->setTexture(element.texture);

      SPtr<ShaderProgram> shaderProgram(xyPlane->getShaderProgram());
      shaderProgram->setUniformValue("uOpacity", element.opacity);
      shaderProgram->setUniformValue("uFill", element.fill);
      shaderProgram->setUniformValue("uTint", element.tint);

      glm::mat4 scale(glm::scale(glm::vec3(element.scale.x, element.scale.y, 1.0f) / 100.0f));
      glm::mat4 ratio(glm::scale(glm::vec3((float)height / width, 1.0f, 1.0f)));
      glm::mat4 translate(glm::translate(glm::vec3((element.position.x / 50.0f) - 1.0f, (element.position.y / 50.0f) - 1.0f, 0.0f)));

      glm::mat4 transform = translate * ratio * scale;
      shaderProgram->setUniformValue("uTransform", transform);

      RenderData renderData;
      xyPlane->draw(renderData);
   }
}
Exemplo n.º 10
0
// The address returned here will only be valid until next time this function is called.
// The program is return bound.
QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
{
    for (int i = 0; i < cachedPrograms.size(); ++i) {
        QGLEngineShaderProg *cachedProg = cachedPrograms[i];
        if (*cachedProg == prog) {
            // Move the program to the top of the list as a poor-man's cache algo
            cachedPrograms.move(i, 0);
            cachedProg->program->bind();
            return cachedProg;
        }
    }

    QScopedPointer<QGLEngineShaderProg> newProg;

    do {
        QByteArray fragSource;
        // Insert the custom stage before the srcPixel shader to work around an ATI driver bug
        // where you cannot forward declare a function that takes a sampler as argument.
        if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
            fragSource.append(prog.customStageSource);
        fragSource.append(qShaderSnippets[prog.mainFragShader]);
        fragSource.append(qShaderSnippets[prog.srcPixelFragShader]);
        if (prog.compositionFragShader)
            fragSource.append(qShaderSnippets[prog.compositionFragShader]);
        if (prog.maskFragShader)
            fragSource.append(qShaderSnippets[prog.maskFragShader]);

        QByteArray vertexSource;
        vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
        vertexSource.append(qShaderSnippets[prog.positionVertexShader]);

        QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram);

        CachedShader shaderCache(fragSource, vertexSource);
        bool inCache = shaderCache.load(shaderProgram.data(), QGLContext::currentContext());

        if (!inCache) {

            QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment));
            QByteArray description;
#if defined(QT_DEBUG)
            // Name the shader for easier debugging
            description.append("Fragment shader: main=");
            description.append(snippetNameStr(prog.mainFragShader));
            description.append(", srcPixel=");
            description.append(snippetNameStr(prog.srcPixelFragShader));
            if (prog.compositionFragShader) {
                description.append(", composition=");
                description.append(snippetNameStr(prog.compositionFragShader));
            }
            if (prog.maskFragShader) {
                description.append(", mask=");
                description.append(snippetNameStr(prog.maskFragShader));
            }
            fragShader->setObjectName(QString::fromLatin1(description));
#endif
            if (!fragShader->compileSourceCode(fragSource)) {
                qWarning() << "Warning:" << description << "failed to compile!";
                break;
            }

            QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex));
#if defined(QT_DEBUG)
            // Name the shader for easier debugging
            description.clear();
            description.append("Vertex shader: main=");
            description.append(snippetNameStr(prog.mainVertexShader));
            description.append(", position=");
            description.append(snippetNameStr(prog.positionVertexShader));
            vertexShader->setObjectName(QString::fromLatin1(description));
#endif
            if (!vertexShader->compileSourceCode(vertexSource)) {
                qWarning() << "Warning:" << description << "failed to compile!";
                break;
            }

            shaders.append(vertexShader.data());
            shaders.append(fragShader.data());
            shaderProgram->addShader(vertexShader.take());
            shaderProgram->addShader(fragShader.take());

            // We have to bind the vertex attribute names before the program is linked:
            shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
            if (prog.useTextureCoords)
                shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
            if (prog.useOpacityAttribute)
                shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
            if (prog.usePmvMatrixAttribute) {
                shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
                shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
                shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
            }
        }

        newProg.reset(new QGLEngineShaderProg(prog));
        newProg->program = shaderProgram.take();

        newProg->program->link();
        if (newProg->program->isLinked()) {
            if (!inCache)
                shaderCache.store(newProg->program, QGLContext::currentContext());
        } else {
            QLatin1String none("none");
            QLatin1String br("\n");
            QString error;
            error = QLatin1String("Shader program failed to link,");
#if defined(QT_DEBUG)
            error += QLatin1String("\n  Shaders Used:\n");
            for (int i = 0; i < newProg->program->shaders().count(); ++i) {
                QGLShader *shader = newProg->program->shaders().at(i);
                error += QLatin1String("    ") + shader->objectName() + QLatin1String(": \n")
                         + QLatin1String(shader->sourceCode()) + br;
            }
#endif
            error += QLatin1String("  Error Log:\n")
                     + QLatin1String("    ") + newProg->program->log();
            qWarning() << error;
            break;
        }

        newProg->program->bind();

        if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) {
            GLuint location = newProg->program->uniformLocation("maskTexture");
            newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT);
        }

        if (cachedPrograms.count() > 30) {
            // The cache is full, so delete the last 5 programs in the list.
            // These programs will be least used, as a program us bumped to
            // the top of the list when it's used.
            for (int i = 0; i < 5; ++i) {
                delete cachedPrograms.last();
                cachedPrograms.removeLast();
            }
        }

        cachedPrograms.insert(0, newProg.data());
    } while (false);

    return newProg.take();
}
Exemplo n.º 11
0
int main() {
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	GLFWwindow* window = glfwCreateWindow(800, 600, "Learn OpenGL", nullptr, nullptr);
	if (window == nullptr) {
		std::cerr << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);

	glewExperimental = GL_TRUE;
	if (glewInit() != GLEW_OK) {
		std::cerr << "Failed to initialize GLEW" << std::endl;
		return -1;
	}

	// Set up OpenGL to draw a triangle
	glViewport(0, 0, 800, 600);

	Shader shaderProgram("shaders/transform.vs", "shaders/textured.frag");

	GLfloat vertices[] = {
		 0.5f,  0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  1.0f, 1.0f, // top right
		 0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  1.0f, 0.0f, // bottom right
		-0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f,  0.0f, 0.0f, // bottom left
		-0.5f,  0.5f, 0.0f,  1.0f, 1.0f, 0.0f,  0.0f, 1.0f  // top left
	};
	GLuint indices[] = {
		0, 1, 3, // First triangle
		1, 2, 3  // Second triangle
	};

	GLuint VBO;
	glGenBuffers(1, &VBO);
	GLuint EBO;
	glGenBuffers(1, &EBO);

	GLuint VAO;
	glGenVertexArrays(1, &VAO);

	glBindVertexArray(VAO);
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
		glEnableVertexAttribArray(0);
		
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
		glEnableVertexAttribArray(1);

		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
		glEnableVertexAttribArray(2);
	glBindVertexArray(0);

	Texture texture1("textures/container.jpg");
	Texture texture2("textures/awesomeface.png");

	glfwSetKeyCallback(window, key_callback);
	while(!glfwWindowShouldClose(window)) {
		glfwPollEvents();

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		GLuint transformLoc = shaderProgram.UniformLocation("transform");

		shaderProgram.Use();

		glUniform1f(shaderProgram.UniformLocation("faceVisibility"), g_visibility);

		// Bind textures using texture units
		glActiveTexture(GL_TEXTURE0);
		texture1.Bind();
		glUniform1i(shaderProgram.UniformLocation("ourTexture1"), 0);

		glActiveTexture(GL_TEXTURE1);
		texture2.Bind();
		glUniform1i(shaderProgram.UniformLocation("ourTexture2"), 1);


		glBindVertexArray(VAO);
		glm::mat4 trans;
		trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
		trans = glm::rotate(trans, glm::radians((GLfloat)glfwGetTime() * 50.0f), glm::vec3(0.0, 0.0, 1.0));
		glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		glm::mat4 trans2;
		GLfloat scaleValue = sin((GLfloat)glfwGetTime());
		trans2 = glm::translate(trans2, glm::vec3(-0.5f, 0.5f, 0.0f));
		trans2 = glm::scale(trans2, glm::vec3(scaleValue, scaleValue, scaleValue));
		glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans2));
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		glBindVertexArray(0);

		glfwSwapBuffers(window);
	}

	glfwTerminate();

	return 0;
}
Exemplo n.º 12
0
int main()
{
	DEBUGLOG->setAutoPrint(true);

	//////////////////////////////////////////////////////////////////////////////
	/////////////////////// INIT //////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////

	// create window and opengl context
	auto window = generateWindow(800,800);

	//////////////////////////////////////////////////////////////////////////////
	/////////////////////////////// RENDERING  ///////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////
	
	/////////////////////     Scene / View Settings     //////////////////////////
	glm::mat4 model = glm::mat4(1.0f);
	glm::vec4 eye(0.0f, 0.0f, 3.0f, 1.0f);
	glm::vec4 center(0.0f,0.0f,0.0f,1.0f);
	glm::mat4 view = glm::lookAt(glm::vec3(eye), glm::vec3(center), glm::vec3(0,1,0));

	// glm::mat4 perspective = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, -1.0f, 6.0f);
	/// perspective projection is experimental; yields weird warping effects due to vertex interpolation of uv-coordinates
	glm::mat4 perspective = glm::perspective(glm::radians(65.f), getRatio(window), 0.1f, 10.f);

	// create object
	// Sphere grid;
	Grid grid(10,10,0.1f,0.1f,true);
	// Volume grid;

	// load grass texture
	s_texHandle = TextureTools::loadTexture(RESOURCES_PATH +  std::string( "/grass.png"));
	glBindTexture(GL_TEXTURE_2D, s_texHandle);

	/////////////////////// 	Renderpass     ///////////////////////////
	DEBUGLOG->log("Shader Compilation: volume uvw coords"); DEBUGLOG->indent();
	ShaderProgram shaderProgram("/modelSpace/GBuffer.vert", "/modelSpace/GBuffer.frag"); DEBUGLOG->outdent();
	shaderProgram.update("model", model);
	shaderProgram.update("view", view);
	shaderProgram.update("projection", perspective);
	shaderProgram.update("color", glm::vec4(1.0f,0.0f,0.0f,1.0f));

	DEBUGLOG->log("FrameBufferObject Creation: volume uvw coords"); DEBUGLOG->indent();
	FrameBufferObject fbo(getResolution(window).x, getResolution(window).y);
	FrameBufferObject::s_internalFormat  = GL_RGBA32F; // to allow arbitrary values in G-Buffer
	fbo.addColorAttachments(4); DEBUGLOG->outdent();   // G-Buffer
	FrameBufferObject::s_internalFormat  = GL_RGBA;	   // restore default

	RenderPass renderPass(&shaderProgram, &fbo);
	renderPass.addEnable(GL_DEPTH_TEST);
	renderPass.addClearBit(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	renderPass.addRenderable(&grid);

	ShaderProgram compShader("/screenSpace/fullscreen.vert", "/screenSpace/finalCompositing.frag");
	// ShaderProgram compShader("/screenSpace/fullscreen.vert", "/screenSpace/simpleAlphaTexture.frag");

	Quad quad;
	RenderPass compositing(&compShader, 0);
	compositing.addClearBit(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	compositing.addRenderable(&quad);

	// Geometry test shader
	ShaderProgram geomShader("/modelSpace/geometry.vert", "/modelSpace/simpleLighting.frag", "/geometry/simpleGeom.geom");
	RenderPass geom(&geomShader, 0);
	geom.addClearBit(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	geom.addRenderable(&grid);
	geom.addEnable(GL_DEPTH_TEST);
	geom.addEnable(GL_ALPHA_TEST);
	geom.addEnable(GL_BLEND);

	glAlphaFunc(GL_GREATER, 0);

	geomShader.update("projection", perspective);


	//////////////////////////////////////////////////////////////////////////////
	///////////////////////    GUI / USER INPUT   ////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////

	// Setup ImGui binding
    ImGui_ImplGlfwGL3_Init(window, true);

	Turntable turntable;
	double old_x;
    double old_y;
	glfwGetCursorPos(window, &old_x, &old_y);
	
	auto cursorPosCB = [&](double x, double y)
	{
		ImGuiIO& io = ImGui::GetIO();
		if ( io.WantCaptureMouse )
		{ return; } // ImGUI is handling this

		double d_x = x - old_x;
		double d_y = y - old_y;

		if ( turntable.getDragActive() )
		{
			turntable.dragBy(d_x, d_y, view);
		}

		old_x = x;
		old_y = y;
	};

	auto mouseButtonCB = [&](int b, int a, int m)
	{
		if (b == GLFW_MOUSE_BUTTON_LEFT && a == GLFW_PRESS)
		{
			turntable.setDragActive(true);
		}
		if (b == GLFW_MOUSE_BUTTON_LEFT && a == GLFW_RELEASE)
		{
			turntable.setDragActive(false);
		}

		ImGui_ImplGlfwGL3_MouseButtonCallback(window, b, a, m);
	};

	auto keyboardCB = [&](int k, int s, int a, int m)
	{
		if (a == GLFW_RELEASE) {return;} 
		switch (k)
		{
			case GLFW_KEY_W:
				eye += glm::inverse(view)    * glm::vec4(0.0f,0.0f,-0.1f,0.0f);
				center += glm::inverse(view) * glm::vec4(0.0f,0.0f,-0.1f,0.0f);
				break;
			case GLFW_KEY_A:
				eye += glm::inverse(view)	 * glm::vec4(-0.1f,0.0f,0.0f,0.0f);
				center += glm::inverse(view) * glm::vec4(-0.1f,0.0f,0.0f,0.0f);
				break;
			case GLFW_KEY_S:
				eye += glm::inverse(view)    * glm::vec4(0.0f,0.0f,0.1f,0.0f);
				center += glm::inverse(view) * glm::vec4(0.0f,0.0f,0.1f,0.0f);
				break;
			case GLFW_KEY_D:
				eye += glm::inverse(view)    * glm::vec4(0.1f,0.0f,0.0f,0.0f);
				center += glm::inverse(view) * glm::vec4(0.1f,0.0f,0.0f,0.0f);
				break;
			default:
				break;
		}
		ImGui_ImplGlfwGL3_KeyCallback(window,k,s,a,m);
	};

	setCursorPosCallback(window, cursorPosCB);
	setMouseButtonCallback(window, mouseButtonCB);
	setKeyCallback(window, keyboardCB);

	//////////////////////////////////////////////////////////////////////////////
	//////////////////////////////// RENDER LOOP /////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////

	double elapsedTime = 0.0;
	render(window, [&](double dt)
	{
		elapsedTime += dt;
		std::string window_header = "Volume Renderer - " + std::to_string( 1.0 / dt ) + " FPS";
		glfwSetWindowTitle(window, window_header.c_str() );

		////////////////////////////////     GUI      ////////////////////////////////
        ImGuiIO& io = ImGui::GetIO();
		ImGui_ImplGlfwGL3_NewFrame(); // tell ImGui a new frame is being rendered
		
		ImGui::PushItemWidth(-100);
		if (ImGui::CollapsingHeader("Geometry Shader Settings"))
    	{
    		ImGui::ColorEdit4( "color", glm::value_ptr( s_color)); // color mixed at max distance
	        ImGui::SliderFloat("strength", &s_strength, 0.0f, 2.0f); // influence of color shift
        }
        
		ImGui::Checkbox("auto-rotate", &s_isRotating); // enable/disable rotating volume
		ImGui::PopItemWidth();
        //////////////////////////////////////////////////////////////////////////////

		///////////////////////////// MATRIX UPDATING ///////////////////////////////
		if (s_isRotating) // update view matrix
		{
			model = glm::rotate(glm::mat4(1.0f), (float) dt, glm::vec3(0.0f, 1.0f, 0.0f) ) * model;
		}

		view = glm::lookAt(glm::vec3(eye), glm::vec3(center), glm::vec3(0.0f, 1.0f, 0.0f));
		//////////////////////////////////////////////////////////////////////////////
				
		////////////////////////  SHADER / UNIFORM UPDATING //////////////////////////
		// update view related uniforms
		shaderProgram.update(   "view", view);
		shaderProgram.update(   "model", turntable.getRotationMatrix() * model);

		geomShader.update(   "view", view);
		geomShader.update(   "model", turntable.getRotationMatrix() * model);
		compShader.update(   "vLightPos", view * turntable.getRotationMatrix() * s_lightPos);

		updateVectorTexture(elapsedTime);

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, s_vectorTexture);

	//	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // this is altered by ImGui::Render(), so reset it every frame
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, s_texHandle);
		geomShader.update("tex", 1);
		geomShader.update("blendColor", 2.0);
		geomShader.update("color", s_color);
		geomShader.update("strength", s_strength);
		//////////////////////////////////////////////////////////////////////////////
		
		////////////////////////////////  RENDERING //// /////////////////////////////
		// glActiveTexture(GL_TEXTURE0);
		// glBindTexture(GL_TEXTURE_2D, fbo.getColorAttachmentTextureHandle(GL_COLOR_ATTACHMENT0)); // color
		// glActiveTexture(GL_TEXTURE1);
		// glBindTexture(GL_TEXTURE_2D, fbo.getColorAttachmeHntTextureHandle(GL_COLOR_ATTACHMENT1)); // normal
		// glActiveTexture(GL_TEXTURE2);
		// glBindTexture(GL_TEXTURE_2D, fbo.getColorAttachmentTextureHandle(GL_COLOR_ATTACHMENT2)); // position
		// glActiveTexture(GL_TEXTURE0);

		// compShader.update("colorMap",    0);
		// compShader.update("normalMap",   1);
		// compShader.update("positionMap", 2);

		// renderPass.render();
		// compositing.render();

		geom.render();

		ImGui::Render();
		glDisable(GL_BLEND);
		glBlendFunc(GL_ONE, GL_ZERO); // this is altered by ImGui::Render(), so reset it every frame
		//////////////////////////////////////////////////////////////////////////////

	});

	destroyWindow(window);

	return 0;
}