#include <vector>
#include <SFML/Graphics.hpp>
#include <GL/glew.h>
sf::Vector2i mousepos;
class Light : public sf::Transformable
{
public:
sf::Color color;
sf::Vector3f falloff;
void draw() const
{
glUniform2f(2, getPosition().x, getPosition().y);
glUniform4f(3, color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f);
glUniform3f(4, falloff.x, falloff.y, falloff.z);
}
};
Light* mouseLight;
class LightEngine
{
private:
GLuint m_u32VAO, m_u32VBO, m_u32EBO;
std::vector<Light> m_aoLights;
public:
LightEngine()
{
glGenVertexArrays(1, &m_u32VAO);
glBindVertexArray(m_u32VAO);
// Data for VBO
const GLfloat verts[]
{
-1.0f, 1.0f, 0.0f, 0.0f, // Top left
1.0f, 1.0f, 1.0f, 0.0f, // Top right
1.0f, -1.0f, 1.0f, 1.0f, // Bottom right
-1.0f, -1.0f, 0.0f, 1.0f, // Bottom left
};
glGenBuffers(1, &m_u32VBO);
glBindBuffer(GL_ARRAY_BUFFER, m_u32VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), reinterpret_cast<void*>(2 * sizeof(GLfloat)));
// Data for EBO
const GLuint elements[]
{
0, 1, 2,
2, 3, 0
};
glGenBuffers(1, &m_u32EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_u32EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Create a test light
Light oLight;
oLight.setPosition({512, 384});
oLight.color = sf::Color::White;
oLight.falloff = {0.4f, 3.0f, 20.0f};
m_aoLights.push_back(oLight);
mouseLight = &*m_aoLights.rbegin();
/*
// Multiple lights dont work
Light oLight2;
oLight2.setPosition({100, 100});
oLight2.color = sf::Color::Green;
m_aoLights.push_back(oLight2);
Light oLight3;
oLight3.setPosition({300, 250});
oLight3.color = sf::Color::Red;
m_aoLights.push_back(oLight3);
*/
}
void render(sf::RenderTarget& rt)
{
mouseLight->setPosition(static_cast<sf::Vector2f>(mousepos));
glBindVertexArray(m_u32VAO);
for (const auto& rkoLight : m_aoLights)
{
rkoLight.draw();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
}
glBindVertexArray(0);
}
~LightEngine()
{
glDeleteBuffers(1, &m_u32EBO);
glDeleteBuffers(1, &m_u32VBO);
glDeleteVertexArrays(1, &m_u32VAO);
}
};
int main()
{
sf::ContextSettings oContextSettings;
oContextSettings.antialiasingLevel = 4;
oContextSettings.depthBits = 24;
oContextSettings.majorVersion = 3;
oContextSettings.minorVersion = 3;
sf::RenderWindow oApp{{1024, 768}, "OpenGL Lighting Test", sf::Style::Default, oContextSettings};
glewExperimental = 1;
glewInit();
sf::Shader oShader;
oShader.loadFromFile("shaders/Vertex.vert", "shaders/Fragment.frag");
sf::RenderTexture oRT, oRTNormals;
oRT.create(oApp.getSize().x, oApp.getSize().y);
oRTNormals.create(oApp.getSize().x, oApp.getSize().y);
{
{
sf::Texture oTex;
oTex.loadFromFile("bg1.png");
sf::Sprite oSpr;
oSpr.setTexture(oTex);
oSpr.setPosition({5.0f, 5.0f});
oRT.draw(oSpr);
oTex.loadFromFile("bg1_n.png");
oRTNormals.draw(oSpr);
}
{
sf::Texture oTex;
oTex.loadFromFile("bg2.png");
sf::Sprite oSpr;
oSpr.setTexture(oTex);
oSpr.setPosition({650.0f, 50.0f});
oRT.draw(oSpr);
oTex.loadFromFile("bg2_n.png");
oRTNormals.draw(oSpr);
}
{
sf::Texture oTex;
oTex.loadFromFile("bg3.png");
sf::Sprite oSpr;
oSpr.setTexture(oTex);
oSpr.setPosition({300.0f, 250.0f});
oRT.draw(oSpr);
oTex.loadFromFile("bg3_n.png");
oRTNormals.draw(oSpr);
}
}
oRT.display();
oRTNormals.display();
sf::Sprite oSprite{oRT.getTexture()};
oApp.setActive(true);
LightEngine oEngine;
sf::Clock oClock;
bool bRunning = true;
while (bRunning)
{
sf::Event oEvent;
while (oApp.pollEvent(oEvent))
{
switch (oEvent.type)
{
case sf::Event::Closed:
{
bRunning = false;
break;
}
}
}
mousepos = sf::Mouse::getPosition(oApp);
const auto kfSeconds = oClock.getElapsedTime().asSeconds();
mouseLight->color = {static_cast<sf::Uint8>(255 * std::abs(std::sin(kfSeconds))), static_cast<sf::Uint8>(255 * std::abs(std::cos(kfSeconds))), 255, 255};
oApp.clear();
oApp.pushGLStates();
oApp.resetGLStates();
oApp.draw(oSprite);
oApp.popGLStates();
glUseProgram(oShader.getNativeHandle());
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, oRT.getTexture().getNativeHandle());
glUniform1i(0, 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, oRTNormals.getTexture().getNativeHandle());
glUniform1i(1, 3);
oEngine.render(oApp);
// Cleanup. Reset Texture2 and 3 and unbind any shaders.
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
glActiveTexture(GL_TEXTURE0);
oApp.display();
}
}