29 #include <SFML/Graphics/PostFX.hpp> 30 #include <SFML/Graphics/RenderWindow.hpp> 31 #include <SFML/Graphics/GraphicsContext.hpp> 57 myTextures (Copy.myTextures),
58 myFragmentShader(Copy.myFragmentShader),
59 myFrameBuffer (Copy.myFrameBuffer)
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();
311 glTexCoord2f(TexCoords.Left, TexCoords.Top); glVertex2f(Screen.
Left, Screen.
Bottom);
312 glTexCoord2f(TexCoords.Right, TexCoords.Top); glVertex2f(Screen.
Right, Screen.
Bottom);
313 glTexCoord2f(TexCoords.Right, TexCoords.Bottom); glVertex2f(Screen.
Right, Screen.
Top);
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));
334 std::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");
412 void 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));
PostFX & operator=(const PostFX &Other)
Assignment operator.
void SetTexture(const std::string &Name, Image *Texture)
Set a texture parameter.
void SetSmooth(bool Smooth)
Enable or disable image smooth filter.
bool LoadFromFile(const std::string &Filename)
Load the effect from a file.
Abstract base class for every object that can be drawn into a render window.
Simple wrapper for sf::Window that allows easy 2D rendering.
const sf::FloatRect & GetRect() const
Get the bounding rectangle of the view.
T Right
Right coordinate of the rectangle.
virtual void Render(RenderTarget &Target) const
/see Drawable::Render
PostFX()
Default constructor.
void SetParameter(const std::string &Name, float X)
Change a parameter of the effect (1 float)
Image is the low-level class for loading and manipulating images.
bool CopyScreen(RenderWindow &Window, const IntRect &SourceRect=IntRect(0, 0, 0, 0))
Create the image from the current contents of the given window.
const View & GetView() const
Get the current view.
PostFX is used to apply a post effect to a window.
unsigned int GetWidth() const
Return the width of the image.
T Bottom
Bottom coordinate of the rectangle.
FloatRect GetTexCoords(const IntRect &Rect) const
Convert a subrect expressed in pixels, into float texture coordinates.
Base class for all render targets (window, image, ...)
unsigned int GetHeight() const
Return the height of the image.
T Top
Top coordinate of the rectangle.
static bool CanUsePostFX()
Tell whether or not the system supports post-effects.
T Left
Left coordinate of the rectangle.
bool LoadFromMemory(const std::string &Effect)
Load the effect from a text in memory.