SFML logo
  • Main Page
  • Namespaces
  • Classes
  • Files
  • File List

Renderer.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Graphics/Renderer.hpp>
00029 #include <SFML/Graphics/RenderTarget.hpp>
00030 #include <SFML/Graphics/Image.hpp>
00031 #include <SFML/Graphics/Shader.hpp>
00032 #include <SFML/Graphics/GLCheck.hpp>
00033 
00034 
00035 namespace sf
00036 {
00038 Renderer::Renderer(RenderTarget& target) :
00039 myTarget          (target),
00040 myTextureIsValid  (false),
00041 myShaderIsValid   (false),
00042 myBlendModeIsValid(false),
00043 myViewportIsValid (false)
00044 {
00045     myStates = &myStatesStack[0];
00046 }
00047 
00048 
00050 Renderer::~Renderer()
00051 {
00052 }
00053 
00054 
00056 void Renderer::Initialize()
00057 {
00058     // Default render states
00059     GLCheck(glDisable(GL_LIGHTING));
00060     GLCheck(glDisable(GL_DEPTH_TEST));
00061     GLCheck(glEnable(GL_TEXTURE_2D));
00062     GLCheck(glEnable(GL_ALPHA_TEST));
00063     GLCheck(glAlphaFunc(GL_GREATER, 0));
00064 
00065     // Default transform matrices
00066     GLCheck(glMatrixMode(GL_MODELVIEW));
00067     GLCheck(glLoadIdentity());
00068     GLCheck(glMatrixMode(GL_PROJECTION));
00069     GLCheck(glLoadIdentity());
00070 
00071     // Invalidate the cached SFML states
00072     myTextureIsValid   = false;
00073     myShaderIsValid    = false;
00074     myBlendModeIsValid = false;
00075     myViewportIsValid  = false;
00076 }
00077 
00078 
00080 void Renderer::SaveGLStates()
00081 {
00082     // Save render states
00083     GLCheck(glPushAttrib(GL_ALL_ATTRIB_BITS));
00084 
00085     // Save matrices
00086     GLCheck(glMatrixMode(GL_MODELVIEW));
00087     GLCheck(glPushMatrix());
00088     GLCheck(glMatrixMode(GL_PROJECTION));
00089     GLCheck(glPushMatrix());
00090 }
00091 
00092 
00094 void Renderer::RestoreGLStates()
00095 {
00096     // Restore render states
00097     GLCheck(glPopAttrib());
00098 
00099     // Restore matrices
00100     GLCheck(glMatrixMode(GL_PROJECTION));
00101     GLCheck(glPopMatrix());
00102     GLCheck(glMatrixMode(GL_MODELVIEW));
00103     GLCheck(glPopMatrix());
00104 }
00105 
00106 
00108 void Renderer::Clear(const Color& color)
00109 {
00110     GLCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f));
00111     GLCheck(glClear(GL_COLOR_BUFFER_BIT));
00112 }
00113 
00114 
00116 void Renderer::PushStates()
00117 {
00118     myStates++;
00119     *myStates = *(myStates - 1);
00120 }
00121 
00122 
00124 void Renderer::PopStates()
00125 {
00126     myStates--;
00127 }
00128 
00129 
00131 void Renderer::SetModelView(const Matrix3& matrix)
00132 {
00133     myStates->modelView = matrix;
00134 }
00135 
00136 
00138 void Renderer::ApplyModelView(const Matrix3& matrix)
00139 {
00140     myStates->modelView *= matrix;
00141 }
00142 
00143 
00145 void Renderer::SetProjection(const Matrix3& matrix)
00146 {
00147     // Apply it immediately (this one is not critical for performances)
00148     GLCheck(glMatrixMode(GL_PROJECTION));
00149     GLCheck(glLoadMatrixf(matrix.Get4x4Elements()));
00150 }
00151 
00152 
00154 void Renderer::SetColor(const Color& color)
00155 {
00156     myStates->r = color.r / 255.f;
00157     myStates->g = color.g / 255.f;
00158     myStates->b = color.b / 255.f;
00159     myStates->a = color.a / 255.f;
00160 }
00161 
00162 
00164 void Renderer::ApplyColor(const Color& color)
00165 {
00166     myStates->r *= color.r / 255.f;
00167     myStates->g *= color.g / 255.f;
00168     myStates->b *= color.b / 255.f;
00169     myStates->a *= color.a / 255.f;
00170 }
00171 
00172 
00174 void Renderer::SetViewport(const IntRect& viewport)
00175 {
00176     if ((viewport.Left != myViewport.Left) || (viewport.Right  != myViewport.Right)  ||
00177         (viewport.Top  != myViewport.Top)  || (viewport.Bottom != myViewport.Bottom) ||
00178         !myViewportIsValid)
00179     {
00180         // Apply the new viewport -- revert Y axis to match the OpenGL convention
00181         GLCheck(glViewport(viewport.Left, myTarget.GetHeight() - viewport.Bottom, viewport.GetSize().x, viewport.GetSize().y));
00182 
00183         // Store it
00184         myViewport = viewport;
00185         myViewportIsValid = true;
00186     }
00187 }
00188 
00189 
00191 void Renderer::SetBlendMode(Blend::Mode mode)
00192 {
00193     if ((mode != myBlendMode) || !myBlendModeIsValid)
00194     {
00195         // Apply the new blending mode
00196         if (mode == Blend::None)
00197         {
00198             GLCheck(glDisable(GL_BLEND));
00199         }
00200         else
00201         {
00202             GLCheck(glEnable(GL_BLEND));
00203 
00204             switch (mode)
00205             {
00206                 // Alpha blending
00207                 // glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target
00208                 // is a RenderImage -- in this case the alpha value must be written directly to the target buffer
00209                 default :
00210                 case Blend::Alpha :
00211                     if (GLEW_EXT_blend_func_separate)
00212                         GLCheck(glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
00213                     else
00214                         GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
00215                     break;
00216 
00217                 // Additive blending
00218                 case Blend::Add :
00219                     GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE));
00220                     break;
00221 
00222                 // Multiplicative blending
00223                 case Blend::Multiply :
00224                     GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO));
00225                     break;
00226             }
00227         }
00228 
00229         // Store it
00230         myBlendMode = mode;
00231         myBlendModeIsValid = true;
00232     }
00233 }
00234 
00235 
00237 void Renderer::SetTexture(const Image* texture)
00238 {
00239     if ((texture != myTexture) || !myTextureIsValid)
00240     {
00241         // Apply the new texture
00242         if (texture)
00243             texture->Bind();
00244         else
00245             GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
00246 
00247         // Store it
00248         myTexture = texture;
00249         myTextureIsValid = true;
00250     }
00251     else if (texture)
00252     {
00253         // If the texture was already the current one, make sure that
00254         // it is synchronized (in case it was modified since last use)
00255         texture->Use();
00256     }
00257 }
00258 
00259 
00261 void Renderer::SetShader(const Shader* shader)
00262 {
00263     if ((shader != myShader) || !myShaderIsValid)
00264     {
00265         if (Shader::IsAvailable()) // to avoid calling possibly unsupported functions
00266         {
00267             // Apply the new shader
00268             if (shader)
00269                 shader->Bind();
00270             else
00271                 GLCheck(glUseProgramObjectARB(0));
00272 
00273             // Store it
00274             myShader = shader;
00275             myShaderIsValid = true;
00276         }
00277     }
00278     else if (shader)
00279     {
00280         // If the shader was already the current one, make sure that
00281         // it is synchronized (in case it was modified since last use)
00282         shader->Use();
00283     }
00284 }
00285 
00286 
00288 void Renderer::Begin(PrimitiveType type)
00289 {
00290     // Begin rendering
00291     switch (type)
00292     {
00293         case TriangleList :  glBegin(GL_TRIANGLES);      break;
00294         case TriangleStrip : glBegin(GL_TRIANGLE_STRIP); break;
00295         case TriangleFan :   glBegin(GL_TRIANGLE_FAN);   break;
00296         case QuadList :      glBegin(GL_QUADS);          break;
00297         default: break;
00298     }
00299 }
00300 
00301 
00303 void Renderer::End()
00304 {
00305     // End rendering
00306     glEnd();
00307 }
00308 
00309 
00311 void Renderer::AddVertex(float x, float y)
00312 {
00313     ProcessVertex(x, y, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
00314 }
00315 
00316 
00318 void Renderer::AddVertex(float x, float y, float u, float v)
00319 {
00320     ProcessVertex(x, y, u, v, 1.f, 1.f, 1.f, 1.f);
00321 }
00322 
00323 
00325 void Renderer::AddVertex(float x, float y, const Color& color)
00326 {
00327     ProcessVertex(x, y, 0.f, 0.f, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
00328 }
00329 
00330 
00332 void Renderer::AddVertex(float x, float y, float u, float v, const Color& color)
00333 {
00334     ProcessVertex(x, y, u, v, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
00335 }
00336 
00337 
00339 void Renderer::ProcessVertex(float x, float y, float u, float v, float r, float g, float b, float a)
00340 {
00341     // Transform the vertex position by the current model-view matrix
00342     Vector2f position = myStates->modelView.Transform(Vector2f(x, y));
00343 
00344     // Modulate the vertex color with the current global color
00345     r *= myStates->r;
00346     g *= myStates->g;
00347     b *= myStates->b;
00348     a *= myStates->a;
00349 
00350     // Render the vertex
00351     glColor4f(r, g, b, a);
00352     glTexCoord2f(u, v);
00353     glVertex2f(position.x, position.y);
00354 }
00355 
00356 } // namespace sf

 ::  Copyright © 2007-2008 Laurent Gomila, all rights reserved  ::  Documentation generated by doxygen 1.5.2  ::