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 ::