29#include <SFML/Graphics/PostFX.hpp>
30#include <SFML/Graphics/RenderWindow.hpp>
31#include <SFML/Graphics/GraphicsContext.hpp>
47 myFrameBuffer.SetSmooth(
false);
57myTextures (Copy.myTextures),
58myFragmentShader(Copy.myFragmentShader),
59myFrameBuffer (Copy.myFrameBuffer)
62 myFrameBuffer.SetSmooth(
false);
65 if (Copy.myShaderProgram)
79 priv::GraphicsContext Ctx;
81 GLCheck(glDeleteObjectARB(myShaderProgram));
92 std::ifstream File(Filename.c_str());
95 std::cerr <<
"Failed to open effect file \"" << Filename <<
"\"" << std::endl;
100 myFragmentShader = PreprocessEffect(File);
105 return myShaderProgram != 0;
115 std::istringstream Stream(Effect.c_str());
118 myFragmentShader = PreprocessEffect(Stream);
123 return myShaderProgram != 0;
135 GLCheck(glUseProgramObjectARB(myShaderProgram));
138 GLint Location = glGetUniformLocationARB(myShaderProgram, Name.c_str());
140 GLCheck(glUniform1fARB(Location, X));
142 std::cerr <<
"Parameter \"" << Name <<
"\" not found in post-effect" << std::endl;
145 GLCheck(glUseProgramObjectARB(0));
158 GLCheck(glUseProgramObjectARB(myShaderProgram));
161 GLint Location = glGetUniformLocationARB(myShaderProgram, Name.c_str());
163 GLCheck(glUniform2fARB(Location, X, Y));
165 std::cerr <<
"Parameter \"" << Name <<
"\" not found in post-effect" << std::endl;
168 GLCheck(glUseProgramObjectARB(0));
181 GLCheck(glUseProgramObjectARB(myShaderProgram));
184 GLint Location = glGetUniformLocationARB(myShaderProgram, Name.c_str());
186 GLCheck(glUniform3fARB(Location, X, Y, Z));
188 std::cerr <<
"Parameter \"" << Name <<
"\" not found in post-effect" << std::endl;
191 GLCheck(glUseProgramObjectARB(0));
204 GLCheck(glUseProgramObjectARB(myShaderProgram));
207 GLint Location = glGetUniformLocationARB(myShaderProgram, Name.c_str());
209 GLCheck(glUniform4fARB(Location, X, Y, Z, W));
211 std::cerr <<
"Parameter \"" << Name <<
"\" not found in post-effect" << std::endl;
214 GLCheck(glUseProgramObjectARB(0));
226 GLCheck(glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &MaxUnits));
227 if (myTextures.size() >=
static_cast<std::size_t
>(MaxUnits))
229 std::cerr <<
"Impossible to use texture \"" << Name <<
"\" for post-effect : all available texture units are used" << std::endl;
234 int Location = glGetUniformLocationARB(myShaderProgram, Name.c_str());
237 std::cerr <<
"Texture \"" << Name <<
"\" not found in post-effect" << std::endl;
242 myTextures[Name] = Texture ? Texture : &myFrameBuffer;
253 std::swap(myShaderProgram, Temp.myShaderProgram);
254 std::swap(myTextures, Temp.myTextures);
255 std::swap(myFragmentShader, Temp.myFragmentShader);
256 std::swap(myFrameBuffer, Temp.myFrameBuffer);
268 priv::GraphicsContext Ctx;
270 return glewIsSupported(
"GL_ARB_shading_language_100") != 0 &&
271 glewIsSupported(
"GL_ARB_shader_objects") != 0 &&
272 glewIsSupported(
"GL_ARB_vertex_shader") != 0 &&
273 glewIsSupported(
"GL_ARB_fragment_shader") != 0;
283 if (!myShaderProgram)
291 GLCheck(glUseProgramObjectARB(myShaderProgram));
294 TextureTable::const_iterator ItTex = myTextures.begin();
295 for (std::size_t i = 0; i < myTextures.size(); ++i)
297 int Location = glGetUniformLocationARB(myShaderProgram, ItTex->first.c_str());
298 GLCheck(glUniform1iARB(Location,
static_cast<GLint
>(i)));
299 GLCheck(glActiveTextureARB(
static_cast<GLenum
>(GL_TEXTURE0_ARB + i)));
300 ItTex->second->Bind();
305 IntRect FrameBufferRect(0, 0, myFrameBuffer.GetWidth(), myFrameBuffer.GetHeight());
306 FloatRect TexCoords = myFrameBuffer.GetTexCoords(FrameBufferRect);
311 glTexCoord2f(TexCoords.
Left, TexCoords.
Top); glVertex2f(Screen.
Left, Screen.
Bottom);
314 glTexCoord2f(TexCoords.
Left, TexCoords.
Bottom); glVertex2f(Screen.
Left, Screen.
Top);
318 GLCheck(glUseProgramObjectARB(0));
321 for (std::size_t i = 0; i < myTextures.size(); ++i)
323 GLCheck(glActiveTextureARB(
static_cast<GLenum
>(GL_TEXTURE0_ARB + i)));
324 GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
326 GLCheck(glActiveTextureARB(GL_TEXTURE0_ARB));
334std::string PostFX::PreprocessEffect(std::istream& File)
337 std::set<std::string> myTextures;
338 std::string Out =
"";
342 while (std::getline(File, Line) && (Line.substr(0, 6) !=
"effect"))
345 if (!Line.empty() && (Line[Line.size() - 1] ==
'\r'))
346 Line.erase(Line.size() - 1);
353 std::string Type, Name;
354 std::istringstream iss(Line);
355 if (!(iss >> Type >> Name))
357 std::cerr <<
"Post-effect error : invalid declaration (should be \"[type][name]\")" << std::endl
358 <<
"> " << Line << std::endl;
362 if (Type ==
"texture")
365 if (myTextures.find(Name) != myTextures.end())
367 std::cerr <<
"Post-effect error : texture \"" << Name <<
"\" already exists" << std::endl;
371 Out +=
"uniform sampler2D " + Name +
";\n";
372 myTextures.insert(Name);
377 Out +=
"uniform " + Type +
" " + Name +
";\n";
382 Out +=
"void main()\n";
383 while (std::getline(File, Line))
386 for (std::set<std::string>::const_iterator i = myTextures.begin(); i != myTextures.end(); ++i)
388 std::string::size_type Pos = Line.find(*i);
389 if (Pos != std::string::npos)
390 Line.replace(Pos, i->size() + 1,
"texture2D(" + *i +
", ");
394 for (std::string::size_type Pos = Line.find(
"_in"); Pos != std::string::npos; Pos = Line.find(
"_in"))
395 Line.replace(Pos, 3,
"gl_TexCoord[0].xy");
398 for (std::string::size_type Pos = Line.find(
"_out"); Pos != std::string::npos; Pos = Line.find(
"_out"))
399 Line.replace(Pos, 4,
"gl_FragColor");
412void PostFX::CreateProgram()
415 priv::GraphicsContext Ctx;
420 std::cerr <<
"Failed to create a PostFX : your system doesn't support effects" << std::endl;
426 GLCheck(glDeleteObjectARB(myShaderProgram));
429 static const std::string VertexShaderSrc =
432 " gl_TexCoord[0] = gl_MultiTexCoord0;"
433 " gl_Position = ftransform();"
437 myShaderProgram = glCreateProgramObjectARB();
440 GLhandleARB VertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
441 GLhandleARB FragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
444 const char* VertexSrc = VertexShaderSrc.c_str();
445 const char* FragmentSrc = myFragmentShader.c_str();
446 GLCheck(glShaderSourceARB(VertexShader, 1, &VertexSrc, NULL));
447 GLCheck(glShaderSourceARB(FragmentShader, 1, &FragmentSrc, NULL));
448 GLCheck(glCompileShaderARB(VertexShader));
449 GLCheck(glCompileShaderARB(FragmentShader));
453 GLCheck(glGetObjectParameterivARB(VertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &Success));
454 if (Success == GL_FALSE)
456 char CompileLog[1024];
457 GLCheck(glGetInfoLogARB(VertexShader,
sizeof(CompileLog), 0, CompileLog));
458 std::cerr <<
"Failed to compile post-effect :" << std::endl
459 << CompileLog << std::endl;
460 GLCheck(glDeleteObjectARB(VertexShader));
461 GLCheck(glDeleteObjectARB(FragmentShader));
462 GLCheck(glDeleteObjectARB(myShaderProgram));
466 GLCheck(glGetObjectParameterivARB(FragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &Success));
467 if (Success == GL_FALSE)
469 char CompileLog[1024];
470 GLCheck(glGetInfoLogARB(FragmentShader,
sizeof(CompileLog), 0, CompileLog));
471 std::cerr <<
"Failed to compile post-effect :" << std::endl
472 << CompileLog << std::endl;
473 GLCheck(glDeleteObjectARB(VertexShader));
474 GLCheck(glDeleteObjectARB(FragmentShader));
475 GLCheck(glDeleteObjectARB(myShaderProgram));
481 GLCheck(glAttachObjectARB(myShaderProgram, VertexShader));
482 GLCheck(glAttachObjectARB(myShaderProgram, FragmentShader));
485 GLCheck(glDeleteObjectARB(VertexShader));
486 GLCheck(glDeleteObjectARB(FragmentShader));
489 GLCheck(glLinkProgramARB(myShaderProgram));
492 GLCheck(glGetObjectParameterivARB(myShaderProgram, GL_OBJECT_LINK_STATUS_ARB, &Success));
493 if (Success == GL_FALSE)
497 GLCheck(glGetInfoLogARB(myShaderProgram,
sizeof(LinkLog), 0, LinkLog));
498 std::cerr <<
"Failed to link post-effect :" << std::endl
499 << LinkLog << std::endl;
500 GLCheck(glDeleteObjectARB(myShaderProgram));
Drawable(const Vector2f &Position=Vector2f(0, 0), const Vector2f &Scale=Vector2f(1, 1), float Rotation=0.f, const Color &Col=Color(255, 255, 255, 255))
Default constructor.
Image is the low-level class for loading and manipulating images.
bool LoadFromFile(const std::string &Filename)
Load the effect from a file.
PostFX()
Default constructor.
void SetTexture(const std::string &Name, Image *Texture)
Set a texture parameter.
void SetParameter(const std::string &Name, float X)
Change a parameter of the effect (1 float).
bool LoadFromMemory(const std::string &Effect)
Load the effect from a text in memory.
static bool CanUsePostFX()
Tell whether or not the system supports post-effects.
virtual void Render(RenderTarget &Target) const
/see Drawable::Render
PostFX & operator=(const PostFX &Other)
Assignment operator.
T Top
Top coordinate of the rectangle.
T Right
Right coordinate of the rectangle.
T Left
Left coordinate of the rectangle.
T Bottom
Bottom coordinate of the rectangle.
const View & GetView() const
Get the current view.
Simple wrapper for sf::Window that allows easy 2D rendering.
const sf::FloatRect & GetRect() const
Get the bounding rectangle of the view.