Hi,
I am trying to execute the following example (OpenGL Core profile) and when I try to draw a text it displays the following error at the console:
"An internal OpenGL call failed in RenderTarget.cpp (218) : GL_INVALID_OPERATION,
the specified operation is not allowed in the current state"
The question is:
I have read in other threads that some features are not available for OpenGL core/
Is it posible to use SFML Text using opengl core profile?
Thanks,
Nicolas
#define GLEW_STATIC
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <glm/glm.hpp>
using glm::mat4;
using glm::vec3;
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform2.hpp>
#include <fstream>
#include <sstream>
#include <string>
#include "GLSLProgram.h"
GLuint theProgram;
int main()
{
sf::ContextSettings contextSettings;
contextSettings.depthBits = 32;
contextSettings.stencilBits = 8;
contextSettings.antialiasingLevel = 4;
contextSettings.majorVersion = 0;
contextSettings.minorVersion = 1;
// Create the main window
sf::RenderWindow window(sf::VideoMode(640, 480), "SFML window with OpenGL", sf::Style::Default, contextSettings);
// Make it the active window for OpenGL calls
window.setActive();
GLenum err = glewInit();
if( GLEW_OK != err )
{
fprintf(stderr, "Error initializing GLEW: %s\n", glewGetErrorString(err) );
}
const GLubyte *renderer = glGetString( GL_RENDERER );
const GLubyte *vendor = glGetString( GL_VENDOR );
const GLubyte *version = glGetString( GL_VERSION );
const GLubyte *glslVersion =
glGetString( GL_SHADING_LANGUAGE_VERSION );
GLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
printf("GL Vendor : %s\n", vendor);
printf("GL Renderer : %s\n", renderer);
printf("GL Version (string) : %s\n", version);
printf("GL Version (integer) : %d.%d\n", major, minor);
printf("GLSL Version : %s\n", glslVersion);
// Create some text to draw on top of our OpenGL object
sf::Font font;
if (!font.loadFromFile("resources/sansation.ttf"))
return EXIT_FAILURE;
sf::Text text("SFML / OpenGL demo", font);
text.setColor(sf::Color(255, 255, 255, 170));
text.setPosition(250.f, 250.f);
// Bind the texture
glEnable(GL_TEXTURE_2D);
// Compile and link Shaders
GLSLProgram prog;
if( ! prog.compileShaderFromFile("shaders/basic_affinetransform.vert",GLSLShader::VERTEX) )
{
printf("Vertex shader failed to compile!\n%s",
prog.log().c_str());
exit(1);
}
if( ! prog.compileShaderFromFile("shaders/basic_affinetransform.frag",GLSLShader::FRAGMENT))
{
printf("Fragment shader failed to compile!\n%s",
prog.log().c_str());
exit(1);
}
if( ! prog.link() )
{
printf("Shader program failed to link!\n%s",
prog.log().c_str());
exit(1);
}
float matrix[] = {
1.0f, 0.0f, 0.0f, 0.0f, // first column
0.0f, 1.0f, 0.0f, 0.0f, // second column
0.0f, 0.0f, 1.0f, 0.0f, // third column
0.5f, 0.0f, 0.0f, 1.0f // fourth column
};
int matrix_location = glGetUniformLocation (prog.getHandle(), "matrix");
glUseProgram (prog.getHandle());
glUniformMatrix4fv (matrix_location, 1, GL_FALSE, matrix);
prog.use();
/////////////////// Create the VBO ////////////////////
float positionData[] = {
-0.8f, -0.8f, 0.0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f };
float colorData[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
// Create and populate the buffer objects
GLuint vboHandles[2];
// Create the buffer objects
glGenBuffers(2, vboHandles);
GLuint positionBufferHandle = vboHandles[0];
GLuint colorBufferHandle = vboHandles[1];
// Populate the position buffer
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);
// Populate the color buffer
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);
// Create and set-up the vertex array object
GLuint vaoHandle;
glGenVertexArrays( 1, &vaoHandle );
glBindVertexArray(vaoHandle);
// Enable the vertex attribute arrays
glEnableVertexAttribArray(0); // Vertex position
glEnableVertexAttribArray(1); // Vertex color
// Map index 0 to the position buffer
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
// Map index 1 to the color buffer
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
glBindBuffer(GL_ARRAY_BUFFER, 0);
glClearColor(0.0,0.0,0.0,1.0);
glEnable(GL_DEPTH_TEST);
// Configure the viewport (the same size as the window)
glViewport(0, 0, window.getSize().x, window.getSize().y);
// Create a clock for measuring the time elapsed
sf::Clock clock;
// Start the game loop
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window: exit
if (event.type == sf::Event::Closed) {
window.close();
return EXIT_SUCCESS;
}
// Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) {
window.close();
return EXIT_SUCCESS;
}
// Resize event: adjust the viewport
if (event.type == sf::Event::Resized) {
glViewport(0, 0, event.size.width, event.size.height);
}
}
//// Clear the color and depth buffers
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//matrix[12] += 0.0001f;
//glUniformMatrix4fv (matrix_location, 1, GL_FALSE, matrix);
//glBindVertexArray(vaoHandle);
//glDrawArrays(GL_TRIANGLES, 0, 3 );
// Draw some text on top of our OpenGL object
window.pushGLStates();
window.draw(text);
window.popGLStates();
window.display();
}
return EXIT_SUCCESS;
}
#include "glslprogram.h"
#include <fstream>
using std::ifstream;
using std::ios;
#include <sstream>
using std::ostringstream;
#include <sys/stat.h>
GLSLProgram::GLSLProgram() : handle(0), linked(false) { }
bool GLSLProgram::compileShaderFromFile( const char * fileName,
GLSLShader::GLSLShaderType type )
{
if( ! fileExists(fileName) )
{
logString = "File not found.";
return false;
}
if( handle <= 0 ) {
handle = glCreateProgram();
if( handle == 0) {
logString = "Unable to create shader program.";
return false;
}
}
ifstream inFile( fileName, ios::in );
if( !inFile ) {
return false;
}
ostringstream code;
while( inFile.good() ) {
int c = inFile.get();
if( ! inFile.eof() )
code << (char) c;
}
inFile.close();
return compileShaderFromString(code.str(), type);
}
bool GLSLProgram::compileShaderFromString( const string & source, GLSLShader::GLSLShaderType type )
{
if( handle <= 0 ) {
handle = glCreateProgram();
if( handle == 0) {
logString = "Unable to create shader program.";
return false;
}
}
GLuint shaderHandle = 0;
switch( type ) {
case GLSLShader::VERTEX:
shaderHandle = glCreateShader(GL_VERTEX_SHADER);
break;
case GLSLShader::FRAGMENT:
shaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
break;
case GLSLShader::GEOMETRY:
shaderHandle = glCreateShader(GL_GEOMETRY_SHADER);
break;
case GLSLShader::TESS_CONTROL:
shaderHandle = glCreateShader(GL_TESS_CONTROL_SHADER);
break;
case GLSLShader::TESS_EVALUATION:
shaderHandle = glCreateShader(GL_TESS_EVALUATION_SHADER);
break;
default:
return false;
}
const char * c_code = source.c_str();
glShaderSource( shaderHandle, 1, &c_code, NULL );
// Compile the shader
glCompileShader(shaderHandle );
// Check for errors
int result;
glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &result );
if( GL_FALSE == result ) {
// Compile failed, store log and return false
int length = 0;
logString = "";
glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &length );
if( length > 0 ) {
char * c_log = new char[length];
int written = 0;
glGetShaderInfoLog(shaderHandle, length, &written, c_log);
logString = c_log;
delete [] c_log;
}
return false;
} else {
// Compile succeeded, attach shader and return true
glAttachShader(handle, shaderHandle);
return true;
}
}
bool GLSLProgram::link()
{
if( linked ) return true;
if( handle <= 0 ) return false;
glLinkProgram(handle);
int status = 0;
glGetProgramiv( handle, GL_LINK_STATUS, &status);
if( GL_FALSE == status ) {
// Store log and return false
int length = 0;
logString = "";
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &length );
if( length > 0 ) {
char * c_log = new char[length];
int written = 0;
glGetProgramInfoLog(handle, length, &written, c_log);
logString = c_log;
delete [] c_log;
}
return false;
} else {
linked = true;
return linked;
}
}
void GLSLProgram::use()
{
if( handle <= 0 || (! linked) ) return;
glUseProgram( handle );
}
string GLSLProgram::log()
{
return logString;
}
int GLSLProgram::getHandle()
{
return handle;
}
bool GLSLProgram::isLinked()
{
return linked;
}
void GLSLProgram::bindAttribLocation( GLuint location, const char * name)
{
glBindAttribLocation(handle, location, name);
}
void GLSLProgram::bindFragDataLocation( GLuint location, const char * name )
{
glBindFragDataLocation(handle, location, name);
}
void GLSLProgram::setUniform( const char *name, float x, float y, float z)
{
int loc = getUniformLocation(name);
if( loc >= 0 ) {
glUniform3f(loc,x,y,z);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, const vec3 & v)
{
this->setUniform(name,v.x,v.y,v.z);
}
void GLSLProgram::setUniform( const char *name, const vec4 & v)
{
int loc = getUniformLocation(name);
if( loc >= 0 ) {
glUniform4f(loc,v.x,v.y,v.z,v.w);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, const vec2 & v)
{
int loc = getUniformLocation(name);
if( loc >= 0 ) {
glUniform2f(loc,v.x,v.y);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, const mat4 & m)
{
int loc = getUniformLocation(name);
if( loc >= 0 )
{
glUniformMatrix4fv(loc, 1, GL_FALSE, &m[0][0]);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, const mat3 & m)
{
int loc = getUniformLocation(name);
if( loc >= 0 )
{
glUniformMatrix3fv(loc, 1, GL_FALSE, &m[0][0]);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, float val )
{
int loc = getUniformLocation(name);
if( loc >= 0 )
{
glUniform1f(loc, val);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, int val )
{
int loc = getUniformLocation(name);
if( loc >= 0 )
{
glUniform1i(loc, val);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::setUniform( const char *name, bool val )
{
int loc = getUniformLocation(name);
if( loc >= 0 )
{
glUniform1i(loc, val);
} else {
printf("Uniform: %s not found.\n",name);
}
}
void GLSLProgram::printActiveUniforms() {
GLint nUniforms, size, location, maxLen;
GLchar * name;
GLsizei written;
GLenum type;
glGetProgramiv( handle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
glGetProgramiv( handle, GL_ACTIVE_UNIFORMS, &nUniforms);
name = (GLchar *) malloc( maxLen );
printf(" Location | Name\n");
printf("------------------------------------------------\n");
for( int i = 0; i < nUniforms; ++i ) {
glGetActiveUniform( handle, i, maxLen, &written, &size, &type, name );
location = glGetUniformLocation(handle, name);
printf(" %-8d | %s\n",location, name);
}
free(name);
}
void GLSLProgram::printActiveAttribs() {
GLint written, size, location, maxLength, nAttribs;
GLenum type;
GLchar * name;
glGetProgramiv(handle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
glGetProgramiv(handle, GL_ACTIVE_ATTRIBUTES, &nAttribs);
name = (GLchar *) malloc( maxLength );
printf(" Index | Name\n");
printf("------------------------------------------------\n");
for( int i = 0; i < nAttribs; i++ ) {
glGetActiveAttrib( handle, i, maxLength, &written, &size, &type, name );
location = glGetAttribLocation(handle, name);
printf(" %-5d | %s\n",location, name);
}
free(name);
}
bool GLSLProgram::validate()
{
if( ! isLinked() ) return false;
GLint status;
glValidateProgram( handle );
glGetProgramiv( handle, GL_VALIDATE_STATUS, &status );
if( GL_FALSE == status ) {
// Store log and return false
int length = 0;
logString = "";
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &length );
if( length > 0 ) {
char * c_log = new char[length];
int written = 0;
glGetProgramInfoLog(handle, length, &written, c_log);
logString = c_log;
delete [] c_log;
}
return false;
} else {
return true;
}
}
int GLSLProgram::getUniformLocation(const char * name )
{
return glGetUniformLocation(handle, name);
}
bool GLSLProgram::fileExists( const string & fileName )
{
struct stat info;
int ret = -1;
ret = stat(fileName.c_str(), &info);
return 0 == ret;
}
#ifndef GLSLPROGRAM_H
#define GLSLPROGRAM_H
#include <string>
using std::string;
#include <GL/glew.h>
#include <glm/glm.hpp>
using glm::vec2;
using glm::vec3;
using glm::vec4;
using glm::mat4;
using glm::mat3;
namespace GLSLShader {
enum GLSLShaderType {
VERTEX, FRAGMENT, GEOMETRY,
TESS_CONTROL, TESS_EVALUATION
};
};
class GLSLProgram
{
private:
int handle;
bool linked;
string logString;
int getUniformLocation(const char * name );
bool fileExists( const string & fileName );
public:
GLSLProgram();
bool compileShaderFromFile( const char * fileName, GLSLShader::GLSLShaderType type );
bool compileShaderFromString( const string & source, GLSLShader::GLSLShaderType type );
bool link();
bool validate();
void use();
string log();
int getHandle();
bool isLinked();
void bindAttribLocation( GLuint location, const char * name);
void bindFragDataLocation( GLuint location, const char * name );
void setUniform( const char *name, float x, float y, float z);
void setUniform( const char *name, const vec2 & v);
void setUniform( const char *name, const vec3 & v);
void setUniform( const char *name, const vec4 & v);
void setUniform( const char *name, const mat4 & m);
void setUniform( const char *name, const mat3 & m);
void setUniform( const char *name, float val );
void setUniform( const char *name, int val );
void setUniform( const char *name, bool val );
void printActiveUniforms();
void printActiveAttribs();
};
#endif // GLSLPROGRAM_H