Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [solved] OpenGL with SFML (Assumed context issue)  (Read 11942 times)

0 Members and 1 Guest are viewing this topic.

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: OpenGL with SFML (Assumed context issue)
« Reply #15 on: October 13, 2016, 05:39:23 pm »
I'm getting a bit of a problem now with the simplest thing.

If I change the body of my LightEngine::draw function to just
   void draw(sf::RenderTarget& rt, sf::RenderStates states) const
   {
      glBindVertexArray(m_u32VAO);
      glBindVertexArray(0);
   }
 

I get this in the console each frame:
Quote
An internal OpenGL call failed in Shader.cpp(815).
Expression:
   GLEXT_glUseProgramObject(0)
Error description:
   GL_INVALID_OPERATION
   The specified operation is not allowed in the current state.

Could be worth noting that glGetError is still returning 0, even with this error printing to the console and the sprite is rendering correctly.
« Last Edit: October 13, 2016, 05:47:18 pm by Gambit »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: OpenGL with SFML (Assumed context issue)
« Reply #16 on: October 13, 2016, 06:18:59 pm »
Let's summon binary1248, because this one is out of my knowledge ;)
Laurent Gomila - SFML developer

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: OpenGL with SFML (Assumed context issue)
« Reply #17 on: October 13, 2016, 06:29:30 pm »
For reference, this is my main now.

#include <vector>

#include <SFML/Graphics.hpp>
#include <GL/glew.h>

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);
   }
};

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, 1.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)));
      glBindBuffer(GL_ARRAY_BUFFER, 0);

      // 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);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

      glBindVertexArray(0);

      // Create a test light
      Light oLight;
      oLight.setPosition({512, 384});
      oLight.color = sf::Color::Red;
      oLight.falloff = {0.4f, 3.0f, 20.0f};
      m_aoLights.push_back(oLight);
   }

   void render(sf::RenderTarget& rt)
   {
      glBindVertexArray(m_u32VAO);

      for (const auto& rkoLight : m_aoLights)
      {
         //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()};

   LightEngine oEngine;

   bool bRunning = true;
   while (bRunning)
   {
      sf::Event oEvent;
      while (oApp.pollEvent(oEvent))
      {
         switch (oEvent.type)
         {
         case sf::Event::Closed:
         {
            bRunning = false;
            break;
         }
         }
      }

      oApp.clear();

      oApp.pushGLStates();
      oApp.resetGLStates();
      oApp.draw(oSprite);
      oApp.popGLStates();

      sf::Shader::bind(&oShader);

      glActiveTexture(GL_TEXTURE2);
      sf::Texture::bind(&oRT.getTexture());
      glUniform1i(0, 2);

      glActiveTexture(GL_TEXTURE3);
      sf::Texture::bind(&oRTNormals.getTexture());
      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);
      sf::Shader::bind(nullptr);

      oApp.resetGLStates();
      oApp.display();
   }
}
 

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: OpenGL with SFML (Assumed context issue)
« Reply #18 on: October 14, 2016, 07:18:01 am »
I changed

sf::Shader::bind(nullptr);
 

To:

glUseProgram(0);
 

The above error is replaced with this one:
Quote
An internal OpenGL call failed in RenderTarget.cpp(369).
Expression:
   GLEXT_glClientActiveTexture(GLEXT_GL_TEXTURE0)
Error description:
   GL_INVALID_OPERATION
   The specified operation is not allowed in the current state.

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: OpenGL with SFML (Assumed context issue)
« Reply #19 on: October 14, 2016, 09:02:41 am »
Ok I finally got it working.

Result: http://i.imgur.com/wnRIzua.gifv

Code:
(click to show/hide)

It turns out that NOT setting the active texture to 0 before displaying the RenderWindow makes SFML die.

A few caveats to the result, the final result is actually displayed upside-down and multiple lights dont work and I'm not entirely sure how to fix that(Inverting the y uv coordinate fixed this). I tried adding a RenderTexture member to LightEngine, creating and activating it in the constructor, generating, binding and buffering all my data then making the RenderTexture inactive then each draw call active it again, bind the VAO and do the drawing where all lights are drawn with additive blending then at the end create a sprite from the RenderTexture and render it to the RenderTarget passed to the draw call with multiplicative blending  but it didnt work and I'm pretty sure I'm doing something wrong.
« Last Edit: October 14, 2016, 09:09:37 am by Gambit »