diff --git a/CSFML/build/VC2008/csfml-graphics.def b/CSFML/build/VC2008/csfml-graphics.def index a8beac5e8..ac594420e 100644 --- a/CSFML/build/VC2008/csfml-graphics.def +++ b/CSFML/build/VC2008/csfml-graphics.def @@ -179,7 +179,8 @@ EXPORTS sfRenderImage_SetView sfRenderImage_GetView sfRenderImage_GetDefaultView - sfRenderImage_PreserveOpenGLStates + sfRenderImage_GetViewport + sfRenderImage_ConvertCoords sfRenderImage_GetImage sfRenderImage_CanUseRenderImage sfRenderWindow_Create @@ -214,8 +215,8 @@ EXPORTS sfRenderWindow_SetView sfRenderWindow_GetView sfRenderWindow_GetDefaultView + sfRenderWindow_GetViewport sfRenderWindow_ConvertCoords - sfRenderWindow_PreserveOpenGLStates sfView_Create sfView_CreateFromRect sfView_Destroy diff --git a/CSFML/include/SFML/Graphics/RenderImage.h b/CSFML/include/SFML/Graphics/RenderImage.h index ced58a7bc..ffbbda1cc 100644 --- a/CSFML/include/SFML/Graphics/RenderImage.h +++ b/CSFML/include/SFML/Graphics/RenderImage.h @@ -134,18 +134,28 @@ CSFML_API const sfView* sfRenderImage_GetView(sfRenderImage* renderImage); CSFML_API sfView* sfRenderImage_GetDefaultView(sfRenderImage* renderImage); //////////////////////////////////////////////////////////// -/// Tell SFML to preserve external OpenGL states, at the expense of -/// more CPU charge. Use this function if you don't want SFML -/// to mess up your own OpenGL states (if any). -/// Don't enable state preservation if not needed, as it will allow -/// SFML to do internal optimizations and improve performances. -/// This parameter is false by default +/// Get the viewport of a view applied to this target /// -/// \param renderImage : Target renderimage -/// \param preserve : True to preserve OpenGL states, false to let SFML optimize +/// \param renderImage : Renderimage object +/// \param view : Target view +/// +/// \return Viewport rectangle, expressed in pixels in the current target /// //////////////////////////////////////////////////////////// -CSFML_API void sfRenderImage_PreserveOpenGLStates(sfRenderImage* renderImage, sfBool preserve); +CSFML_API sfIntRect sfRenderImage_GetViewport(sfRenderImage* renderImage, sfView* view); + +//////////////////////////////////////////////////////////// +/// Convert a point in image coordinates into view coordinates +/// +/// \param renderImage : Renderimage object +/// \param windowX : X coordinate of the point to convert, relative to the image +/// \param windowY : Y coordinate of the point to convert, relative to the image +/// \param viewX : Pointer to fill with the X coordinate of the converted point +/// \param viewY : Pointer to fill with the Y coordinate of the converted point +/// \param targetView : Target view to convert the point to (pass NULL to use the current view) +/// +//////////////////////////////////////////////////////////// +CSFML_API void sfRenderImage_ConvertCoords(sfRenderImage* renderImage, unsigned int windowX, unsigned int windowY, float* viewX, float* viewY, sfView* targetView); //////////////////////////////////////////////////////////// /// Get the target image diff --git a/CSFML/include/SFML/Graphics/RenderWindow.h b/CSFML/include/SFML/Graphics/RenderWindow.h index 328e1b3db..2124a7e9c 100644 --- a/CSFML/include/SFML/Graphics/RenderWindow.h +++ b/CSFML/include/SFML/Graphics/RenderWindow.h @@ -320,6 +320,17 @@ CSFML_API const sfView* sfRenderWindow_GetView(sfRenderWindow* renderWindow); //////////////////////////////////////////////////////////// CSFML_API sfView* sfRenderWindow_GetDefaultView(sfRenderWindow* renderWindow); +//////////////////////////////////////////////////////////// +/// Get the viewport of a view applied to this target +/// +/// \param renderWindow : Renderwindow +/// \param view : Target view +/// +/// \return Viewport rectangle, expressed in pixels in the current target +/// +//////////////////////////////////////////////////////////// +CSFML_API sfIntRect sfRenderWindow_GetViewport(sfRenderWindow* renderWindow, sfView* view); + //////////////////////////////////////////////////////////// /// Convert a point in window coordinates into view coordinates /// @@ -333,19 +344,5 @@ CSFML_API sfView* sfRenderWindow_GetDefaultView(sfRenderWindow* renderWindow); //////////////////////////////////////////////////////////// CSFML_API void sfRenderWindow_ConvertCoords(sfRenderWindow* renderWindow, unsigned int windowX, unsigned int windowY, float* viewX, float* viewY, sfView* targetView); -//////////////////////////////////////////////////////////// -/// Tell SFML to preserve external OpenGL states, at the expense of -/// more CPU charge. Use this function if you don't want SFML -/// to mess up your own OpenGL states (if any). -/// Don't enable state preservation if not needed, as it will allow -/// SFML to do internal optimizations and improve performances. -/// This parameter is false by default -/// -/// \param renderWindow : Target Renderwindow -/// \param preserve : True to preserve OpenGL states, false to let SFML optimize -/// -//////////////////////////////////////////////////////////// -CSFML_API void sfRenderWindow_PreserveOpenGLStates(sfRenderWindow* renderWindow, sfBool preserve); - #endif // SFML_RENDERWINDOW_H diff --git a/CSFML/src/SFML/Graphics/RenderImage.cpp b/CSFML/src/SFML/Graphics/RenderImage.cpp index 033d920d3..49e12f87a 100644 --- a/CSFML/src/SFML/Graphics/RenderImage.cpp +++ b/CSFML/src/SFML/Graphics/RenderImage.cpp @@ -157,16 +157,39 @@ sfView* sfRenderImage_GetDefaultView(sfRenderImage* renderImage) //////////////////////////////////////////////////////////// -/// Tell SFML to preserve external OpenGL states, at the expense of -/// more CPU charge. Use this function if you don't want SFML -/// to mess up your own OpenGL states (if any). -/// Don't enable state preservation if not needed, as it will allow -/// SFML to do internal optimizations and improve performances. -/// This parameter is false by default +/// Get the viewport of a view applied to this target //////////////////////////////////////////////////////////// -void sfRenderImage_PreserveOpenGLStates(sfRenderImage* renderImage, sfBool preserve) +sfIntRect sfRenderImage_GetViewport(sfRenderImage* renderImage, sfView* view) { - CSFML_CALL(renderImage, PreserveOpenGLStates(preserve == sfTrue)); + sfIntRect rect = {0, 0, 0, 0}; + CSFML_CHECK_RETURN(view, rect); + CSFML_CHECK_RETURN(renderImage, rect); + + sf::IntRect SFMLrect = renderImage->This.GetViewport(*view->This); + rect.Left = SFMLrect.Left; + rect.Top = SFMLrect.Top; + rect.Right = SFMLrect.Right; + rect.Bottom = SFMLrect.Bottom; + + return rect; +} + + +//////////////////////////////////////////////////////////// +/// Convert a point in image coordinates into view coordinates +//////////////////////////////////////////////////////////// +void sfRenderImage_ConvertCoords(sfRenderImage* renderImage, unsigned int imageX, unsigned int imageY, float* viewX, float* viewY, sfView* targetView) +{ + CSFML_CHECK(renderImage); + + sf::Vector2f point; + if (targetView) + point = renderImage->This.ConvertCoords(imageX, imageY, *targetView->This); + else + point = renderImage->This.ConvertCoords(imageX, imageY); + + if (viewX) *viewX = point.x; + if (viewY) *viewY = point.y; } diff --git a/CSFML/src/SFML/Graphics/RenderWindow.cpp b/CSFML/src/SFML/Graphics/RenderWindow.cpp index 3eebcb943..e80393e29 100644 --- a/CSFML/src/SFML/Graphics/RenderWindow.cpp +++ b/CSFML/src/SFML/Graphics/RenderWindow.cpp @@ -38,98 +38,98 @@ //////////////////////////////////////////////////////////// /// Construct a new renderwindow //////////////////////////////////////////////////////////// -sfRenderWindow* sfRenderWindow_Create(sfVideoMode Mode, const char* Title, unsigned long Style, sfContextSettings Params) +sfRenderWindow* sfRenderWindow_Create(sfVideoMode mode, const char* title, unsigned long style, sfContextSettings params) { // Convert video mode - sf::VideoMode VideoMode(Mode.Width, Mode.Height, Mode.BitsPerPixel); + sf::VideoMode videoMode(mode.Width, mode.Height, mode.BitsPerPixel); // Create the window - sfRenderWindow* RenderWindow = new sfRenderWindow; - sf::ContextSettings Settings(Params.DepthBits, Params.StencilBits, Params.AntialiasingLevel); - RenderWindow->This.Create(VideoMode, Title, Style, Settings); - RenderWindow->Input.This = &RenderWindow->This.GetInput(); - RenderWindow->DefaultView = new sfView(const_cast(&RenderWindow->This.GetDefaultView())); - RenderWindow->CurrentView = RenderWindow->DefaultView; + sfRenderWindow* renderWindow = new sfRenderWindow; + sf::ContextSettings settings(params.DepthBits, params.StencilBits, params.AntialiasingLevel); + renderWindow->This.Create(videoMode, title, style, settings); + renderWindow->Input.This = &renderWindow->This.GetInput(); + renderWindow->DefaultView = new sfView(const_cast(&renderWindow->This.GetDefaultView())); + renderWindow->CurrentView = renderWindow->DefaultView; - return RenderWindow; + return renderWindow; } //////////////////////////////////////////////////////////// /// Construct a renderwindow from an existing control //////////////////////////////////////////////////////////// -sfRenderWindow* sfRenderWindow_CreateFromHandle(sfWindowHandle Handle, sfContextSettings Params) +sfRenderWindow* sfRenderWindow_CreateFromHandle(sfWindowHandle handle, sfContextSettings params) { - sfRenderWindow* RenderWindow = new sfRenderWindow; - sf::ContextSettings Settings(Params.DepthBits, Params.StencilBits, Params.AntialiasingLevel); - RenderWindow->This.Create(Handle, Settings); - RenderWindow->Input.This = &RenderWindow->This.GetInput(); - RenderWindow->DefaultView = new sfView(const_cast(&RenderWindow->This.GetDefaultView())); - RenderWindow->CurrentView = RenderWindow->DefaultView; + sfRenderWindow* renderWindow = new sfRenderWindow; + sf::ContextSettings settings(params.DepthBits, params.StencilBits, params.AntialiasingLevel); + renderWindow->This.Create(handle, settings); + renderWindow->Input.This = &renderWindow->This.GetInput(); + renderWindow->DefaultView = new sfView(const_cast(&renderWindow->This.GetDefaultView())); + renderWindow->CurrentView = renderWindow->DefaultView; - return RenderWindow; + return renderWindow; } //////////////////////////////////////////////////////////// /// Destroy an existing renderwindow //////////////////////////////////////////////////////////// -void sfRenderWindow_Destroy(sfRenderWindow* RenderWindow) +void sfRenderWindow_Destroy(sfRenderWindow* renderWindow) { - delete RenderWindow->DefaultView; - delete RenderWindow; + delete renderWindow->DefaultView; + delete renderWindow; } //////////////////////////////////////////////////////////// /// Close a renderwindow (but doesn't destroy the internal data) //////////////////////////////////////////////////////////// -void sfRenderWindow_Close(sfRenderWindow* RenderWindow) +void sfRenderWindow_Close(sfRenderWindow* renderWindow) { - CSFML_CALL(RenderWindow, Close()); + CSFML_CALL(renderWindow, Close()); } //////////////////////////////////////////////////////////// /// Tell whether or not a renderwindow is opened //////////////////////////////////////////////////////////// -sfBool sfRenderWindow_IsOpened(sfRenderWindow* RenderWindow) +sfBool sfRenderWindow_IsOpened(sfRenderWindow* renderWindow) { - CSFML_CALL_RETURN(RenderWindow, IsOpened(), sfFalse); + CSFML_CALL_RETURN(renderWindow, IsOpened(), sfFalse); } //////////////////////////////////////////////////////////// /// Get the width of the rendering region of a window //////////////////////////////////////////////////////////// -unsigned int sfRenderWindow_GetWidth(sfRenderWindow* RenderWindow) +unsigned int sfRenderWindow_GetWidth(sfRenderWindow* renderWindow) { - CSFML_CALL_RETURN(RenderWindow, GetWidth(), 0); + CSFML_CALL_RETURN(renderWindow, GetWidth(), 0); } //////////////////////////////////////////////////////////// /// Get the height of the rendering region of a window //////////////////////////////////////////////////////////// -unsigned int sfRenderWindow_GetHeight(sfRenderWindow* RenderWindow) +unsigned int sfRenderWindow_GetHeight(sfRenderWindow* renderWindow) { - CSFML_CALL_RETURN(RenderWindow, GetHeight(), 0); + CSFML_CALL_RETURN(renderWindow, GetHeight(), 0); } //////////////////////////////////////////////////////////// /// Get the creation settings of a window //////////////////////////////////////////////////////////// -sfContextSettings sfRenderWindow_GetSettings(sfRenderWindow* RenderWindow) +sfContextSettings sfRenderWindow_GetSettings(sfRenderWindow* renderWindow) { - sfContextSettings Settings = {0, 0, 0}; - CSFML_CHECK_RETURN(RenderWindow, Settings); + sfContextSettings settings = {0, 0, 0}; + CSFML_CHECK_RETURN(renderWindow, settings); - const sf::ContextSettings& Params = RenderWindow->This.GetSettings(); - Settings.DepthBits = Params.DepthBits; - Settings.StencilBits = Params.StencilBits; - Settings.AntialiasingLevel = Params.AntialiasingLevel; + const sf::ContextSettings& params = renderWindow->This.GetSettings(); + settings.DepthBits = params.DepthBits; + settings.StencilBits = params.StencilBits; + settings.AntialiasingLevel = params.AntialiasingLevel; - return Settings; + return settings; } @@ -137,68 +137,68 @@ sfContextSettings sfRenderWindow_GetSettings(sfRenderWindow* RenderWindow) //////////////////////////////////////////////////////////// /// Get the event on top of events stack of a window, if any, and pop it //////////////////////////////////////////////////////////// -sfBool sfRenderWindow_GetEvent(sfRenderWindow* RenderWindow, sfEvent* Event) +sfBool sfRenderWindow_GetEvent(sfRenderWindow* renderWindow, sfEvent* event) { - CSFML_CHECK_RETURN(RenderWindow, sfFalse); - CSFML_CHECK_RETURN(Event, sfFalse); + CSFML_CHECK_RETURN(renderWindow, sfFalse); + CSFML_CHECK_RETURN(event, sfFalse); // Get the event sf::Event SFMLEvent; - sfBool Ret = RenderWindow->This.GetEvent(SFMLEvent); + sfBool ret = renderWindow->This.GetEvent(SFMLEvent); // No event, return - if (!Ret) + if (!ret) return sfFalse; // Convert its type - Event->Type = static_cast(SFMLEvent.Type); + event->Type = static_cast(SFMLEvent.Type); // Fill its fields - switch (Event->Type) + switch (event->Type) { case sfEvtResized : - Event->Size.Width = SFMLEvent.Size.Width; - Event->Size.Height = SFMLEvent.Size.Height; + event->Size.Width = SFMLEvent.Size.Width; + event->Size.Height = SFMLEvent.Size.Height; break; case sfEvtTextEntered : - Event->Text.Unicode = SFMLEvent.Text.Unicode; + event->Text.Unicode = SFMLEvent.Text.Unicode; break; case sfEvtKeyReleased : case sfEvtKeyPressed : - Event->Key.Code = static_cast(SFMLEvent.Key.Code); - Event->Key.Alt = SFMLEvent.Key.Alt ? sfTrue : sfFalse; - Event->Key.Control = SFMLEvent.Key.Control ? sfTrue : sfFalse; - Event->Key.Shift = SFMLEvent.Key.Shift ? sfTrue : sfFalse; + event->Key.Code = static_cast(SFMLEvent.Key.Code); + event->Key.Alt = SFMLEvent.Key.Alt ? sfTrue : sfFalse; + event->Key.Control = SFMLEvent.Key.Control ? sfTrue : sfFalse; + event->Key.Shift = SFMLEvent.Key.Shift ? sfTrue : sfFalse; break; case sfEvtMouseWheelMoved : - Event->MouseWheel.Delta = SFMLEvent.MouseWheel.Delta; + event->MouseWheel.Delta = SFMLEvent.MouseWheel.Delta; break; case sfEvtMouseButtonPressed : case sfEvtMouseButtonReleased : - Event->MouseButton.Button = static_cast(SFMLEvent.MouseButton.Button); - Event->MouseButton.X = SFMLEvent.MouseButton.X; - Event->MouseButton.Y = SFMLEvent.MouseButton.Y; + event->MouseButton.Button = static_cast(SFMLEvent.MouseButton.Button); + event->MouseButton.X = SFMLEvent.MouseButton.X; + event->MouseButton.Y = SFMLEvent.MouseButton.Y; break; case sfEvtMouseMoved : - Event->MouseMove.X = SFMLEvent.MouseMove.X; - Event->MouseMove.Y = SFMLEvent.MouseMove.Y; + event->MouseMove.X = SFMLEvent.MouseMove.X; + event->MouseMove.Y = SFMLEvent.MouseMove.Y; break; case sfEvtJoyButtonPressed : case sfEvtJoyButtonReleased : - Event->JoyButton.JoystickId = SFMLEvent.JoyButton.JoystickId; - Event->JoyButton.Button = SFMLEvent.JoyButton.Button; + event->JoyButton.JoystickId = SFMLEvent.JoyButton.JoystickId; + event->JoyButton.Button = SFMLEvent.JoyButton.Button; break; case sfEvtJoyMoved : - Event->JoyMove.JoystickId = SFMLEvent.JoyMove.JoystickId; - Event->JoyMove.Axis = static_cast(SFMLEvent.JoyMove.Axis); - Event->JoyMove.Position = SFMLEvent.JoyMove.Position; + event->JoyMove.JoystickId = SFMLEvent.JoyMove.JoystickId; + event->JoyMove.Axis = static_cast(SFMLEvent.JoyMove.Axis); + event->JoyMove.Position = SFMLEvent.JoyMove.Position; break; default : @@ -212,27 +212,27 @@ sfBool sfRenderWindow_GetEvent(sfRenderWindow* RenderWindow, sfEvent* Event) //////////////////////////////////////////////////////////// /// Enable / disable vertical synchronization on a window //////////////////////////////////////////////////////////// -void sfRenderWindow_UseVerticalSync(sfRenderWindow* RenderWindow, sfBool Enabled) +void sfRenderWindow_UseVerticalSync(sfRenderWindow* renderWindow, sfBool enabled) { - CSFML_CALL(RenderWindow, UseVerticalSync(Enabled == sfTrue)); + CSFML_CALL(renderWindow, UseVerticalSync(enabled == sfTrue)); } //////////////////////////////////////////////////////////// /// Show or hide the mouse cursor on a window //////////////////////////////////////////////////////////// -void sfRenderWindow_ShowMouseCursor(sfRenderWindow* RenderWindow, sfBool Show) +void sfRenderWindow_ShowMouseCursor(sfRenderWindow* renderWindow, sfBool show) { - CSFML_CALL(RenderWindow, ShowMouseCursor(Show == sfTrue)); + CSFML_CALL(renderWindow, ShowMouseCursor(show == sfTrue)); } //////////////////////////////////////////////////////////// /// Change the position of the mouse cursor on a window //////////////////////////////////////////////////////////// -void sfRenderWindow_SetCursorPosition(sfRenderWindow* RenderWindow, unsigned int Left, unsigned int Top) +void sfRenderWindow_SetCursorPosition(sfRenderWindow* renderWindow, unsigned int left, unsigned int top) { - CSFML_CALL(RenderWindow, SetCursorPosition(Left, Top)); + CSFML_CALL(renderWindow, SetCursorPosition(left, top)); } @@ -240,27 +240,27 @@ void sfRenderWindow_SetCursorPosition(sfRenderWindow* RenderWindow, unsigned int /// Change the position of a window on screen. /// Only works for top-level windows //////////////////////////////////////////////////////////// -void sfRenderWindow_SetPosition(sfRenderWindow* RenderWindow, int Left, int Top) +void sfRenderWindow_SetPosition(sfRenderWindow* renderWindow, int left, int top) { - CSFML_CALL(RenderWindow, SetPosition(Left, Top)); + CSFML_CALL(renderWindow, SetPosition(left, top)); } //////////////////////////////////////////////////////////// /// Change the size of the rendering region of a window //////////////////////////////////////////////////////////// -void sfRenderWindow_SetSize(sfRenderWindow* RenderWindow, unsigned int Width, unsigned int Height) +void sfRenderWindow_SetSize(sfRenderWindow* renderWindow, unsigned int width, unsigned int height) { - CSFML_CALL(RenderWindow, SetSize(Width, Height)) + CSFML_CALL(renderWindow, SetSize(width, height)) } //////////////////////////////////////////////////////////// /// Show or hide a window //////////////////////////////////////////////////////////// -void sfRenderWindow_Show(sfRenderWindow* RenderWindow, sfBool State) +void sfRenderWindow_Show(sfRenderWindow* renderWindow, sfBool show) { - CSFML_CALL(RenderWindow, Show(State == sfTrue)); + CSFML_CALL(renderWindow, Show(show == sfTrue)); } @@ -268,65 +268,65 @@ void sfRenderWindow_Show(sfRenderWindow* RenderWindow, sfBool State) /// Enable or disable automatic key-repeat for keydown events. /// Automatic key-repeat is enabled by default //////////////////////////////////////////////////////////// -void sfRenderWindow_EnableKeyRepeat(sfRenderWindow* RenderWindow, sfBool Enabled) +void sfRenderWindow_EnableKeyRepeat(sfRenderWindow* renderWindow, sfBool enabled) { - CSFML_CALL(RenderWindow, EnableKeyRepeat(Enabled == sfTrue)); + CSFML_CALL(renderWindow, EnableKeyRepeat(enabled == sfTrue)); } //////////////////////////////////////////////////////////// /// Change the window's icon //////////////////////////////////////////////////////////// -void sfRenderWindow_SetIcon(sfRenderWindow* RenderWindow, unsigned int Width, unsigned int Height, sfUint8* Pixels) +void sfRenderWindow_SetIcon(sfRenderWindow* renderWindow, unsigned int width, unsigned int height, sfUint8* pixels) { - CSFML_CALL(RenderWindow, SetIcon(Width, Height, Pixels)) + CSFML_CALL(renderWindow, SetIcon(width, height, pixels)) } //////////////////////////////////////////////////////////// /// Set a window as the current target for rendering //////////////////////////////////////////////////////////// -sfBool sfRenderWindow_SetActive(sfRenderWindow* RenderWindow, sfBool Active) +sfBool sfRenderWindow_SetActive(sfRenderWindow* renderWindow, sfBool active) { - CSFML_CALL_RETURN(RenderWindow, SetActive(Active == sfTrue), sfFalse) + CSFML_CALL_RETURN(renderWindow, SetActive(active == sfTrue), sfFalse) } //////////////////////////////////////////////////////////// /// Display a window on screen //////////////////////////////////////////////////////////// -void sfRenderWindow_Display(sfRenderWindow* RenderWindow) +void sfRenderWindow_Display(sfRenderWindow* renderWindow) { - CSFML_CALL(RenderWindow, Display()); + CSFML_CALL(renderWindow, Display()); } //////////////////////////////////////////////////////////// /// Get the input manager of a window //////////////////////////////////////////////////////////// -sfInput* sfRenderWindow_GetInput(sfRenderWindow* RenderWindow) +sfInput* sfRenderWindow_GetInput(sfRenderWindow* renderWindow) { - CSFML_CHECK_RETURN(RenderWindow, NULL); + CSFML_CHECK_RETURN(renderWindow, NULL); - return &RenderWindow->Input; + return &renderWindow->Input; } //////////////////////////////////////////////////////////// /// Limit the framerate to a maximum fixed frequency for a window //////////////////////////////////////////////////////////// -void sfRenderWindow_SetFramerateLimit(sfRenderWindow* RenderWindow, unsigned int Limit) +void sfRenderWindow_SetFramerateLimit(sfRenderWindow* renderWindow, unsigned int limit) { - CSFML_CALL(RenderWindow, SetFramerateLimit(Limit)); + CSFML_CALL(renderWindow, SetFramerateLimit(limit)); } //////////////////////////////////////////////////////////// /// Get time elapsed since last frame of a window //////////////////////////////////////////////////////////// -float sfRenderWindow_GetFrameTime(sfRenderWindow* RenderWindow) +float sfRenderWindow_GetFrameTime(sfRenderWindow* renderWindow) { - CSFML_CALL_RETURN(RenderWindow, GetFrameTime(), 0.f); + CSFML_CALL_RETURN(renderWindow, GetFrameTime(), 0.f); } @@ -334,121 +334,126 @@ float sfRenderWindow_GetFrameTime(sfRenderWindow* RenderWindow) /// Change the joystick threshold, ie. the value below which /// no move event will be generated //////////////////////////////////////////////////////////// -void sfRenderWindow_SetJoystickThreshold(sfRenderWindow* RenderWindow, float Threshold) +void sfRenderWindow_SetJoystickThreshold(sfRenderWindow* renderWindow, float threshold) { - CSFML_CALL(RenderWindow, SetJoystickThreshold(Threshold)); + CSFML_CALL(renderWindow, SetJoystickThreshold(threshold)); } //////////////////////////////////////////////////////////// /// Draw something on a renderwindow //////////////////////////////////////////////////////////// -void sfRenderWindow_DrawPostFX(sfRenderWindow* RenderWindow, sfPostFX* PostFX) +void sfRenderWindow_DrawPostFX(sfRenderWindow* renderWindow, sfPostFX* postFX) { - CSFML_CHECK(PostFX); - CSFML_CALL(RenderWindow, Draw(PostFX->This)); + CSFML_CHECK(postFX); + CSFML_CALL(renderWindow, Draw(postFX->This)); } -void sfRenderWindow_DrawShape(sfRenderWindow* RenderWindow, sfShape* Shape) +void sfRenderWindow_DrawShape(sfRenderWindow* renderWindow, sfShape* shape) { - CSFML_CHECK(Shape); - CSFML_CALL(RenderWindow, Draw(Shape->This)); + CSFML_CHECK(shape); + CSFML_CALL(renderWindow, Draw(shape->This)); } -void sfRenderWindow_DrawSprite(sfRenderWindow* RenderWindow, sfSprite* Sprite) +void sfRenderWindow_DrawSprite(sfRenderWindow* renderWindow, sfSprite* sprite) { - CSFML_CHECK(Sprite); - CSFML_CALL(RenderWindow, Draw(Sprite->This)); + CSFML_CHECK(sprite); + CSFML_CALL(renderWindow, Draw(sprite->This)); } -void sfRenderWindow_DrawString(sfRenderWindow* RenderWindow, sfString* String) +void sfRenderWindow_DrawString(sfRenderWindow* renderWindow, sfString* string) { - CSFML_CHECK(String); - CSFML_CALL(RenderWindow, Draw(String->This)); + CSFML_CHECK(string); + CSFML_CALL(renderWindow, Draw(string->This)); } //////////////////////////////////////////////////////////// /// Save the content of a renderwindow to an image //////////////////////////////////////////////////////////// -sfImage* sfRenderWindow_Capture(sfRenderWindow* RenderWindow) +sfImage* sfRenderWindow_Capture(sfRenderWindow* renderWindow) { - CSFML_CHECK_RETURN(RenderWindow, NULL); + CSFML_CHECK_RETURN(renderWindow, NULL); - sfImage* Image = new sfImage; - *Image->This = RenderWindow->This.Capture(); + sfImage* image = new sfImage; + *image->This = renderWindow->This.Capture(); - return Image; + return image; } //////////////////////////////////////////////////////////// /// Clear the screen with the given color //////////////////////////////////////////////////////////// -void sfRenderWindow_Clear(sfRenderWindow* RenderWindow, sfColor Color) +void sfRenderWindow_Clear(sfRenderWindow* renderWindow, sfColor color) { - sf::Color SFMLColor(Color.r, Color.g, Color.b, Color.a); + sf::Color SFMLColor(color.r, color.g, color.b, color.a); - CSFML_CALL(RenderWindow, Clear(SFMLColor)); + CSFML_CALL(renderWindow, Clear(SFMLColor)); } //////////////////////////////////////////////////////////// /// Change the current active view of a renderwindow //////////////////////////////////////////////////////////// -void sfRenderWindow_SetView(sfRenderWindow* RenderWindow, sfView* View) +void sfRenderWindow_SetView(sfRenderWindow* renderWindow, sfView* view) { - CSFML_CHECK(View); - CSFML_CALL(RenderWindow, SetView(*View->This)); - RenderWindow->CurrentView = View; + CSFML_CHECK(view); + CSFML_CALL(renderWindow, SetView(*view->This)); + renderWindow->CurrentView = view; } //////////////////////////////////////////////////////////// /// Get the current active view of a renderwindow //////////////////////////////////////////////////////////// -const sfView* sfRenderWindow_GetView(sfRenderWindow* RenderWindow) +const sfView* sfRenderWindow_GetView(sfRenderWindow* renderWindow) { - CSFML_CHECK_RETURN(RenderWindow, NULL); + CSFML_CHECK_RETURN(renderWindow, NULL); - return RenderWindow->CurrentView; + return renderWindow->CurrentView; } //////////////////////////////////////////////////////////// /// Get the default view of a renderwindow //////////////////////////////////////////////////////////// -sfView* sfRenderWindow_GetDefaultView(sfRenderWindow* RenderWindow) +sfView* sfRenderWindow_GetDefaultView(sfRenderWindow* renderWindow) { - CSFML_CHECK_RETURN(RenderWindow, NULL); + CSFML_CHECK_RETURN(renderWindow, NULL); - return RenderWindow->DefaultView; + return renderWindow->DefaultView; +} + + +//////////////////////////////////////////////////////////// +/// Get the viewport of a view applied to this target +//////////////////////////////////////////////////////////// +sfIntRect sfRenderWindow_GetViewport(sfRenderWindow* renderWindow, sfView* view) +{ + sfIntRect rect = {0, 0, 0, 0}; + CSFML_CHECK_RETURN(view, rect); + CSFML_CHECK_RETURN(renderWindow, rect); + + sf::IntRect SFMLrect = renderWindow->This.GetViewport(*view->This); + rect.Left = SFMLrect.Left; + rect.Top = SFMLrect.Top; + rect.Right = SFMLrect.Right; + rect.Bottom = SFMLrect.Bottom; + + return rect; } //////////////////////////////////////////////////////////// /// Convert a point in window coordinates into view coordinates //////////////////////////////////////////////////////////// -void sfRenderWindow_ConvertCoords(sfRenderWindow* RenderWindow, unsigned int WindowX, unsigned int WindowY, float* ViewX, float* ViewY, sfView* TargetView) +void sfRenderWindow_ConvertCoords(sfRenderWindow* renderWindow, unsigned int windowX, unsigned int windowY, float* viewX, float* viewY, sfView* targetView) { - CSFML_CHECK(RenderWindow); + CSFML_CHECK(renderWindow); - sf::Vector2f Point; - if (TargetView) - Point = RenderWindow->This.ConvertCoords(WindowX, WindowY, *TargetView->This); + sf::Vector2f point; + if (targetView) + point = renderWindow->This.ConvertCoords(windowX, windowY, *targetView->This); else - Point = RenderWindow->This.ConvertCoords(WindowX, WindowY); + point = renderWindow->This.ConvertCoords(windowX, windowY); - if (ViewX) *ViewX = Point.x; - if (ViewY) *ViewY = Point.y; -} - - -//////////////////////////////////////////////////////////// -/// Tell SFML to preserve external OpenGL states, at the expense of -/// more CPU charge. Use this function if you don't want SFML -/// to mess up your own OpenGL states (if any). -/// Don't enable state preservation if not needed, as it will allow -/// SFML to do internal optimizations and improve performances. -/// This parameter is false by default -//////////////////////////////////////////////////////////// -void sfRenderWindow_PreserveOpenGLStates(sfRenderWindow* RenderWindow, sfBool Preserve) -{ - CSFML_CALL(RenderWindow, PreserveOpenGLStates(Preserve == sfTrue)); + if (viewX) *viewX = point.x; + if (viewY) *viewY = point.y; } diff --git a/build/codeblocks/sfml-graphics.cbp b/build/codeblocks/sfml-graphics.cbp index 0674595a7..6600104dc 100644 --- a/build/codeblocks/sfml-graphics.cbp +++ b/build/codeblocks/sfml-graphics.cbp @@ -128,12 +128,15 @@ + + + @@ -147,6 +150,14 @@ + + + + + + + + @@ -159,6 +170,7 @@ + diff --git a/build/vc2005/sfml-audio.vcproj b/build/vc2005/sfml-audio.vcproj index 7e3bb55d6..9ccb65e55 100644 --- a/build/vc2005/sfml-audio.vcproj +++ b/build/vc2005/sfml-audio.vcproj @@ -351,14 +351,6 @@ RelativePath="..\..\src\SFML\Audio\AudioDevice.hpp" > - - - - diff --git a/build/vc2005/sfml-graphics.vcproj b/build/vc2005/sfml-graphics.vcproj index 10a240c9f..6945b204f 100644 --- a/build/vc2005/sfml-graphics.vcproj +++ b/build/vc2005/sfml-graphics.vcproj @@ -362,18 +362,6 @@ - - - - - - @@ -3298,6 +3286,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3306,14 +3426,6 @@ RelativePath="..\..\include\SFML\Graphics\Color.hpp" > - - - - @@ -3418,34 +3530,6 @@ RelativePath="..\..\include\SFML\Graphics\Rect.inl" > - - - - - - - - - - - - - - @@ -3462,30 +3546,6 @@ RelativePath="..\..\include\SFML\Graphics\RenderWindow.hpp" > - - - - - - - - - - - - diff --git a/build/vc2008/sfml-graphics.vcproj b/build/vc2008/sfml-graphics.vcproj index 85bf30bd5..eef12d719 100644 --- a/build/vc2008/sfml-graphics.vcproj +++ b/build/vc2008/sfml-graphics.vcproj @@ -324,6 +324,7 @@ WarningLevel="4" DebugInformationFormat="0" DisableSpecificWarnings="4996" + EnablePREfast="false" /> + + + + + + + + + + + + + + + + + + + + + + + @@ -3296,6 +3344,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3304,14 +3440,6 @@ RelativePath="..\..\include\SFML\Graphics\Color.hpp" > - - - - @@ -3400,14 +3528,6 @@ RelativePath="..\..\include\SFML\Graphics\Matrix3.inl" > - - - - @@ -3416,34 +3536,6 @@ RelativePath="..\..\include\SFML\Graphics\Rect.inl" > - - - - - - - - - - - - - - @@ -3460,30 +3552,6 @@ RelativePath="..\..\include\SFML\Graphics\RenderWindow.hpp" > - - - - - - - - - - - - diff --git a/dotnet/samples/opengl/OpenGL.cs b/dotnet/samples/opengl/OpenGL.cs index 8448039e5..85ae76b5f 100644 --- a/dotnet/samples/opengl/OpenGL.cs +++ b/dotnet/samples/opengl/OpenGL.cs @@ -15,7 +15,6 @@ namespace sample_opengl { // Create main window RenderWindow window = new RenderWindow(new VideoMode(800, 600), "SFML.Net OpenGL"); - window.PreserveOpenGLStates(true); // Setup event handlers window.Closed += new EventHandler(OnClosed); diff --git a/dotnet/src/Graphics/RenderImage.cs b/dotnet/src/Graphics/RenderImage.cs index 61063d3b4..d134bde2d 100644 --- a/dotnet/src/Graphics/RenderImage.cs +++ b/dotnet/src/Graphics/RenderImage.cs @@ -104,18 +104,48 @@ namespace SFML //////////////////////////////////////////////////////////// /// - /// Tell SFML to preserve external OpenGL states, at the expense of - /// more CPU charge. Use this function if you don't want SFML - /// to mess up your own OpenGL states (if any). - /// Don't enable state preservation if not needed, as it will allow - /// SFML to do internal optimizations and improve performances. - /// This parameter is false by default + /// Get the viewport of a view applied to this target /// - /// True to preserve OpenGL states, false to let SFML optimize + /// Target view + /// Viewport rectangle, expressed in pixels in the current target //////////////////////////////////////////////////////////// - public void PreserveOpenGLStates(bool preserve) + public IntRect GetViewport(View view) { - sfRenderImage_PreserveOpenGLStates(This, preserve); + return sfRenderImage_GetViewport(This, view.This); + } + + //////////////////////////////////////////////////////////// + /// + /// Convert a point in target coordinates into view coordinates + /// This version uses the current view of the window + /// + /// X coordinate of the point to convert, relative to the target + /// Y coordinate of the point to convert, relative to the target + /// Converted point + /// + //////////////////////////////////////////////////////////// + public Vector2 ConvertCoords(uint x, uint y) + { + return ConvertCoords(x, y, CurrentView); + } + + //////////////////////////////////////////////////////////// + /// + /// Convert a point in target coordinates into view coordinates + /// This version uses the given view + /// + /// X coordinate of the point to convert, relative to the target + /// Y coordinate of the point to convert, relative to the target + /// Target view to convert the point to + /// Converted point + /// + //////////////////////////////////////////////////////////// + public Vector2 ConvertCoords(uint x, uint y, View view) + { + Vector2 point; + sfRenderImage_ConvertCoords(This, x, y, out point.X, out point.Y, view.This); + + return point; } //////////////////////////////////////////////////////////// @@ -237,7 +267,10 @@ namespace SFML static extern IntPtr sfRenderImage_GetDefaultView(IntPtr This); [DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity] - static extern void sfRenderImage_PreserveOpenGLStates(IntPtr This, bool Preserve); + static extern IntRect sfRenderImage_GetViewport(IntPtr This, IntPtr TargetView); + + [DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity] + static extern void sfRenderImage_ConvertCoords(IntPtr This, uint WindowX, uint WindowY, out float ViewX, out float ViewY, IntPtr TargetView); [DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity] static extern void sfRenderImage_DrawPostFX(IntPtr This, IntPtr PostFx); diff --git a/dotnet/src/Graphics/RenderTarget.cs b/dotnet/src/Graphics/RenderTarget.cs index b18aeb80a..bd675e052 100644 --- a/dotnet/src/Graphics/RenderTarget.cs +++ b/dotnet/src/Graphics/RenderTarget.cs @@ -44,16 +44,37 @@ namespace SFML //////////////////////////////////////////////////////////// /// - /// Tell SFML to preserve external OpenGL states, at the expense of - /// more CPU charge. Use this function if you don't want SFML - /// to mess up your own OpenGL states (if any). - /// Don't enable state preservation if not needed, as it will allow - /// SFML to do internal optimizations and improve performances. - /// This parameter is false by default + /// Get the viewport of a view applied to this target /// - /// True to preserve OpenGL states, false to let SFML optimize + /// Target view + /// Viewport rectangle, expressed in pixels in the current target //////////////////////////////////////////////////////////// - void PreserveOpenGLStates(bool preserve); + IntRect GetViewport(View view); + + //////////////////////////////////////////////////////////// + /// + /// Convert a point in target coordinates into view coordinates + /// This version uses the current view of the window + /// + /// X coordinate of the point to convert, relative to the target + /// Y coordinate of the point to convert, relative to the target + /// Converted point + /// + //////////////////////////////////////////////////////////// + Vector2 ConvertCoords(uint x, uint y); + + //////////////////////////////////////////////////////////// + /// + /// Convert a point in target coordinates into view coordinates + /// This version uses the given view + /// + /// X coordinate of the point to convert, relative to the target + /// Y coordinate of the point to convert, relative to the target + /// Target view to convert the point to + /// Converted point + /// + //////////////////////////////////////////////////////////// + Vector2 ConvertCoords(uint x, uint y, View view); //////////////////////////////////////////////////////////// /// diff --git a/dotnet/src/Graphics/RenderWindow.cs b/dotnet/src/Graphics/RenderWindow.cs index aec175024..f56a85147 100644 --- a/dotnet/src/Graphics/RenderWindow.cs +++ b/dotnet/src/Graphics/RenderWindow.cs @@ -317,49 +317,48 @@ namespace SFML //////////////////////////////////////////////////////////// /// - /// Convert a point in window coordinates into view coordinates - /// using the current view of the window + /// Get the viewport of a view applied to this target /// - /// X coordinate of the point to convert, relative to the window - /// Y coordinate of the point to convert, relative to the window - /// Converted point + /// Target view + /// Viewport rectangle, expressed in pixels in the current target //////////////////////////////////////////////////////////// - public Vector2 ConvertCoords(uint windowX, uint windowY) + public IntRect GetViewport(View view) { - return ConvertCoords(windowX, windowY, myCurrentView); + return sfRenderWindow_GetViewport(This, view.This); } //////////////////////////////////////////////////////////// /// - /// Convert a point in window coordinates into view coordinates + /// Convert a point in target coordinates into view coordinates + /// This version uses the current view of the window /// - /// X coordinate of the point to convert, relative to the window - /// Y coordinate of the point to convert, relative to the window - /// Target view to convert the point to + /// X coordinate of the point to convert, relative to the target + /// Y coordinate of the point to convert, relative to the target /// Converted point + /// //////////////////////////////////////////////////////////// - public Vector2 ConvertCoords(uint windowX, uint windowY, View targetView) + public Vector2 ConvertCoords(uint x, uint y) { - Vector2 Point; - sfRenderWindow_ConvertCoords(This, windowX, windowY, out Point.X, out Point.Y, targetView.This); - - return Point; + return ConvertCoords(x, y, CurrentView); } //////////////////////////////////////////////////////////// /// - /// Tell SFML to preserve external OpenGL states, at the expense of - /// more CPU charge. Use this function if you don't want SFML - /// to mess up your own OpenGL states (if any). - /// Don't enable state preservation if not needed, as it will allow - /// SFML to do internal optimizations and improve performances. - /// This parameter is false by default + /// Convert a point in target coordinates into view coordinates + /// This version uses the given view /// - /// True to preserve OpenGL states, false to let SFML optimize + /// X coordinate of the point to convert, relative to the target + /// Y coordinate of the point to convert, relative to the target + /// Target view to convert the point to + /// Converted point + /// //////////////////////////////////////////////////////////// - public void PreserveOpenGLStates(bool preserve) + public Vector2 ConvertCoords(uint x, uint y, View view) { - sfRenderWindow_PreserveOpenGLStates(This, preserve); + Vector2 point; + sfRenderWindow_ConvertCoords(This, x, y, out point.X, out point.Y, view.This); + + return point; } //////////////////////////////////////////////////////////// @@ -544,10 +543,10 @@ namespace SFML static extern IntPtr sfRenderWindow_GetDefaultView(IntPtr This); [DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity] - static extern void sfRenderWindow_ConvertCoords(IntPtr This, uint WindowX, uint WindowY, out float ViewX, out float ViewY, IntPtr TargetView); + static extern IntRect sfRenderWindow_GetViewport(IntPtr This, IntPtr TargetView); [DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity] - static extern void sfRenderWindow_PreserveOpenGLStates(IntPtr This, bool Preserve); + static extern void sfRenderWindow_ConvertCoords(IntPtr This, uint WindowX, uint WindowY, out float ViewX, out float ViewY, IntPtr TargetView); [DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity] static extern void sfRenderWindow_DrawPostFX(IntPtr This, IntPtr PostFx); diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp index 84ec60f9f..1d7deaef8 100644 --- a/include/SFML/Config.hpp +++ b/include/SFML/Config.hpp @@ -25,6 +25,7 @@ #ifndef SFML_CONFIG_HPP #define SFML_CONFIG_HPP + //////////////////////////////////////////////////////////// // Identify the operating system //////////////////////////////////////////////////////////// @@ -62,6 +63,23 @@ #endif +//////////////////////////////////////////////////////////// +// Identify the endianess +//////////////////////////////////////////////////////////// +#if defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || (defined(__MIPS__) && defined(__MISPEB__)) || \ + defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || defined(__sparc__) || defined(__hppa__) + + // Big endian + #define SFML_ENDIAN_BIG + +#else + + // Little endian + #define SFML_ENDIAN_LITTLE + +#endif + + //////////////////////////////////////////////////////////// // Define a portable debug macro //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics.hpp b/include/SFML/Graphics.hpp index 4074f6e30..47c371e7c 100644 --- a/include/SFML/Graphics.hpp +++ b/include/SFML/Graphics.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/include/SFML/Graphics/Drawable.hpp b/include/SFML/Graphics/Drawable.hpp index 5076eda7b..b8f7b8796 100644 --- a/include/SFML/Graphics/Drawable.hpp +++ b/include/SFML/Graphics/Drawable.hpp @@ -35,6 +35,7 @@ namespace sf { +class RenderQueue; class RenderTarget; //////////////////////////////////////////////////////////// @@ -325,20 +326,22 @@ private : friend class RenderTarget; //////////////////////////////////////////////////////////// - /// Draw the object into the specified window + /// Draw the object into the specified render target /// /// \param target : Target into which render the object + /// \param queue : Render queue to add the rendering commands to /// //////////////////////////////////////////////////////////// - void Draw(RenderTarget& target) const; + void Draw(RenderTarget& target, RenderQueue& queue) const; //////////////////////////////////////////////////////////// /// Render the specific geometry of the object /// /// \param target : Target into which render the object + /// \param queue : Render queue to add the rendering commands to /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target) const = 0; + virtual void Render(RenderTarget& target, RenderQueue& queue) const = 0; //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp index 6853378a6..86121d6c4 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -303,16 +303,6 @@ private : //////////////////////////////////////////////////////////// void EnsureArrayUpdate(); - //////////////////////////////////////////////////////////// - /// Notify the image that an external source has modified - /// its content. - /// For internal use only (see RenderImage class). - /// - /// \param source : RenderImage that will update the image - /// - //////////////////////////////////////////////////////////// - void ExternalUpdate(RenderImage& source); - //////////////////////////////////////////////////////////// /// Reset the image attributes /// @@ -337,7 +327,6 @@ private : std::vector myPixels; ///< Pixels of the image bool myNeedTextureUpdate; ///< Status of synchronization between pixels in central memory and the internal texture un video memory bool myNeedArrayUpdate; ///< Status of synchronization between pixels in central memory and the internal texture un video memory - RenderImage* myUpdateSource; ///< If not null, the image will use it as a source to update its texture bool myPixelsFlipped; ///< To work around the inconsistency in Y orientation }; diff --git a/include/SFML/Graphics/PostFX.hpp b/include/SFML/Graphics/PostFX.hpp index 349f96561..0fe8f4f49 100644 --- a/include/SFML/Graphics/PostFX.hpp +++ b/include/SFML/Graphics/PostFX.hpp @@ -153,7 +153,7 @@ protected : /// /see Drawable::Render /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target) const; + virtual void Render(RenderTarget& target, RenderQueue& queue) const; private : diff --git a/include/SFML/Graphics/RenderImage.hpp b/include/SFML/Graphics/RenderImage.hpp index 1c8b3b733..6ea0f2df6 100644 --- a/include/SFML/Graphics/RenderImage.hpp +++ b/include/SFML/Graphics/RenderImage.hpp @@ -65,7 +65,7 @@ public : /// /// \param width : Width of the render image /// \param height : Height of the render image - /// \param depthBuffer : Do you want a depth buffer attached? (false by default) + /// \param depthBuffer : Do you want this render image to have a depth buffer? /// /// \return True if creation has been successful /// @@ -83,6 +83,12 @@ public : //////////////////////////////////////////////////////////// bool SetActive(bool active = true); + //////////////////////////////////////////////////////////// + /// Update the contents of the target image + /// + //////////////////////////////////////////////////////////// + void Display(); + //////////////////////////////////////////////////////////// /// Get the width of the rendering region of the image /// @@ -117,26 +123,12 @@ public : private : - friend class Image; - //////////////////////////////////////////////////////////// /// /see RenderTarget::Activate /// //////////////////////////////////////////////////////////// virtual bool Activate(bool active); - //////////////////////////////////////////////////////////// - /// Update the pixels of the target image. - /// This function is called automatically by the image when it - /// needs to update its pixels, and is only meant for internal use. - /// - /// \param target : Target image to update - /// - /// \return True if the new pixels are flipped vertically - /// - //////////////////////////////////////////////////////////// - bool UpdateImage(Image& target); - //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderQueue.hpp b/include/SFML/Graphics/RenderQueue.hpp new file mode 100644 index 000000000..049a64039 --- /dev/null +++ b/include/SFML/Graphics/RenderQueue.hpp @@ -0,0 +1,381 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERQUEUE_HPP +#define SFML_RENDERQUEUE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class Batch; + class GeometryRenderer; +} + +//////////////////////////////////////////////////////////// +/// \brief Implements a queue of rendering commands +/// +//////////////////////////////////////////////////////////// +class RenderQueue : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + RenderQueue(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~RenderQueue(); + + //////////////////////////////////////////////////////////// + /// \brief Save the current render states + /// + /// \see PopStates + /// + //////////////////////////////////////////////////////////// + void PushStates(); + + //////////////////////////////////////////////////////////// + /// \brief Restore the previously saved render states + /// + /// \see PushStates + /// + //////////////////////////////////////////////////////////// + void PopStates(); + + //////////////////////////////////////////////////////////// + /// \brief Set a new model-view matrix + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param matrix New model-view matrix + /// + /// \see ApplyModelView + /// + //////////////////////////////////////////////////////////// + void SetModelView(const Matrix3& matrix); + + //////////////////////////////////////////////////////////// + /// \brief Combine a new model-view matrix with the current one + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param matrix Model-view matrix to combine + /// + /// \see SetModelView + /// + //////////////////////////////////////////////////////////// + void ApplyModelView(const Matrix3& matrix); + + //////////////////////////////////////////////////////////// + /// \brief Set a new projection matrix + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param matrix New projection matrix + /// + /// \see ApplyProjection + /// + //////////////////////////////////////////////////////////// + void SetProjection(const Matrix3& matrix); + + //////////////////////////////////////////////////////////// + /// \brief Combine a new projection matrix with the current one + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param matrix Model-view matrix to combine + /// + /// \see SetProjection + /// + //////////////////////////////////////////////////////////// + void ApplyProjection(const Matrix3& matrix); + + //////////////////////////////////////////////////////////// + /// \brief Set the current global color + /// + /// This color will be modulated with each vertex's color. + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param color New global color + /// + /// \see ApplyColor + /// + //////////////////////////////////////////////////////////// + void SetColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Modulate the current global color with a new one + /// + /// This color will be modulated with each vertex's color. + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param color Color to modulate + /// + /// \see SetColor + /// + //////////////////////////////////////////////////////////// + void ApplyColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Set the current viewport + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param viewport New viewport to apply + /// + //////////////////////////////////////////////////////////// + void SetViewport(const IntRect& viewport); + + //////////////////////////////////////////////////////////// + /// \brief Set the current alpha-blending mode + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param mode New blending mode + /// + //////////////////////////////////////////////////////////// + void SetBlendMode(Blend::Mode mode); + + //////////////////////////////////////////////////////////// + /// \brief Set the current texture + /// + /// Note: any call to this function after a call to BeginBatch + /// will be ignored, and delayed until BeginBatch is called again. + /// + /// \param texture New texture + /// + //////////////////////////////////////////////////////////// + void SetTexture(const Image* texture); + + //////////////////////////////////////////////////////////// + /// \brief Begin a new geometry batch + /// + /// This function starts storing geometry and associates it + /// to the current render states (viewport, color, blending, transform). + /// Note: There's no EndBatch, a batch ends as soon as BeginBatch + /// is called again. + /// + //////////////////////////////////////////////////////////// + void BeginBatch(); + + //////////////////////////////////////////////////////////// + /// \brief Add a new vertex (position only) + /// + /// This function adds a new vertex to the current batch. + /// This is equivalent to calling AddVertex(x, y, 0, 0, Color::White). + /// + /// \param x X coordinate of the vertex + /// \param y Y coordinate of the vertex + /// + //////////////////////////////////////////////////////////// + void AddVertex(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Add a new vertex (position + texture coordinates) + /// + /// This function adds a new vertex to the current batch. + /// This is equivalent to calling AddVertex(x, y, u, v, Color::White). + /// + /// \param x X coordinate of the vertex + /// \param y Y coordinate of the vertex + /// \param u X texture coordinate of the vertex + /// \param v Y texture coordinate of the vertex + /// + //////////////////////////////////////////////////////////// + void AddVertex(float x, float y, float u, float v); + + //////////////////////////////////////////////////////////// + /// \brief Add a new vertex (position + color) + /// + /// This function adds a new vertex to the current batch. + /// This is equivalent to calling AddVertex(x, y, 0, 0, color). + /// + /// \param x X coordinate of the vertex + /// \param y Y coordinate of the vertex + /// \param color Color of the vertex + /// + //////////////////////////////////////////////////////////// + void AddVertex(float x, float y, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Add a new vertex (position + texture coordinates + color) + /// + /// This function adds a new vertex to the current batch. + /// + /// \param x X coordinate of the vertex + /// \param y Y coordinate of the vertex + /// \param u X texture coordinate of the vertex + /// \param v Y texture coordinate of the vertex + /// \param color Color of the vertex + /// + //////////////////////////////////////////////////////////// + void AddVertex(float x, float y, float u, float v, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Add a new triangle to be rendered + /// + /// This function adds a new triangle, using indices of previously + /// added vertices. Note that the index base is set to 0 + /// everytime a new batch is started (BeginBatch). + /// + /// Example: + /// \begincode + /// queue.BeginBatch(); + /// queue.AddVertex(...); + /// queue.AddVertex(...); + /// queue.AddVertex(...); + /// queue.AddTriangle(0, 1, 2); + /// \endcode + /// + /// \param index0 Index of the first vertex of the triangle + /// \param index1 Index of the second vertex of the triangle + /// \param index2 Index of the third vertex of the triangle + /// + //////////////////////////////////////////////////////////// + void AddTriangle(unsigned int index0, unsigned int index1, unsigned int index2); + + //////////////////////////////////////////////////////////// + /// \brief Render the content of the whole queue + /// + /// After everything has been rendered, the render queue is + /// automatically cleared. + /// + /// \see Clear + /// + //////////////////////////////////////////////////////////// + void Render(); + + //////////////////////////////////////////////////////////// + /// \brief Clear the whole queue without rendering it + /// + //////////////////////////////////////////////////////////// + void Clear(); + +private : + + //////////////////////////////////////////////////////////// + // Structure holding the render states that can be stacked + //////////////////////////////////////////////////////////// + struct RenderStates + { + RenderStates() : color(255, 255, 255, 255) {} + + Matrix3 modelView; ///< Model-view matrix + Matrix3 projection; ///< Projection matrix + Color color; ///< Vertex color + }; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::vector BatchArray; + typedef std::vector VertexArray; + typedef std::vector IndexArray; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + RenderStates myStatesStack[16]; ///< Stack of render states + RenderStates* myCurrentStates; ///< Current set of render states + Matrix3 myCurrentTransform; ///< Current combined projection-model-view matrix + const Image* myCurrentTexture; ///< Current texture + Blend::Mode myCurrentBlendMode; ///< Current blending mode + IntRect myCurrentViewport; ///< Current target viewport + Vector2f myCurrentViewportSize; ///< Size of the current viewport (for vertex calculations) + unsigned int myBaseIndex; ///< Base vertex index for the current batch + priv::GeometryRenderer* myRenderer; ///< Optimized geometry renderer + priv::Batch* myCurrentBatch; ///< Current geometry block + BatchArray myBatches; ///< Blocks of geometry to render + VertexArray myVertices; ///< Geometry to be rendered + IndexArray myIndices; ///< Indices defining the triangles to be rendered + std::size_t myCurrentVertexCount; ///< Current number of vertices in the vertex array + std::size_t myCurrentIndexCount; ///< Current number of indices in the index array +}; + +} // namespace sf + + +#endif // SFML_RENDERQUEUE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderQueue +/// +/// The RenderQueue class allows to delay the actual rendering +/// by storing the sequence of render states and geometry. +/// +/// Delaying rendering is crucial in order to implement batching +/// (grouping all the geometry using the same states, and sending +/// it to the graphics card with only one call), which allow +/// huge improvements in performances. +/// +/// Usage example: +/// \begincode +/// void MyDrawable::Render(sf::RenderTarget& target) +/// { +/// RenderQueue& queue = target.GetRenderQueue(); +/// +/// queue.SetTexture(myImage); +/// queue.BeginBatch(); +/// { +/// queue.AddVertex(...); +/// queue.AddVertex(...); +/// queue.AddVertex(...); +/// +/// queue.AddTriangle(0, 1, 2); +/// } +/// } +/// \endcode +/// +/// Note that this class is meant for internal use only +/// (it is used by render targets), unless you want to +/// inherit from sf::Drawable. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderTarget.hpp b/include/SFML/Graphics/RenderTarget.hpp index 4c7c16fed..e799c1333 100644 --- a/include/SFML/Graphics/RenderTarget.hpp +++ b/include/SFML/Graphics/RenderTarget.hpp @@ -29,8 +29,9 @@ // Headers //////////////////////////////////////////////////////////// #include -#include #include +#include +#include namespace sf @@ -66,6 +67,22 @@ public : //////////////////////////////////////////////////////////// virtual void Draw(const Drawable& object); + //////////////////////////////////////////////////////////// + /// Make sure that what has been drawn so far is rendered + /// + /// Use this function if you use OpenGL rendering commands, + /// and you want to make sure that things will appear on top + /// of all the SFML objects that have been drawn so far. + /// This is needed because SFML doesn't use immediate rendering, + /// it first accumulates drawables into a queue and + /// trigger the actual rendering afterwards. + /// + /// You don't need to call this function if you're not + /// dealing with OpenGL directly. + /// + //////////////////////////////////////////////////////////// + void Flush(); + //////////////////////////////////////////////////////////// /// Get the width of the rendering region of the target /// @@ -107,17 +124,39 @@ public : View& GetDefaultView(); //////////////////////////////////////////////////////////// - /// Tell SFML to preserve external OpenGL states, at the expense of - /// more CPU charge. Use this function if you don't want SFML - /// to mess up your own OpenGL states (if any). - /// Don't enable state preservation if not needed, as it will allow - /// SFML to do internal optimizations and improve performances. - /// This parameter is false by default + /// Get the viewport of a view applied to this target /// - /// \param preserve : True to preserve OpenGL states, false to let SFML optimize + /// \param view Target view + /// + /// \return Viewport rectangle, expressed in pixels in the current target /// //////////////////////////////////////////////////////////// - void PreserveOpenGLStates(bool preserve); + IntRect GetViewport(const View& view) const; + + //////////////////////////////////////////////////////////// + /// Convert a point in target coordinates into view coordinates + /// This version uses the current view of the window + /// + /// \param x : X coordinate of the point to convert, relative to the target + /// \param y : Y coordinate of the point to convert, relative to the target + /// + /// \return Converted point + /// + //////////////////////////////////////////////////////////// + sf::Vector2f ConvertCoords(unsigned int x, unsigned int y) const; + + //////////////////////////////////////////////////////////// + /// Convert a point in target coordinates into view coordinates + /// This version uses the given view + /// + /// \param x : X coordinate of the point to convert, relative to the target + /// \param y : Y coordinate of the point to convert, relative to the target + /// \param view : Target view to convert the point to + /// + /// \return Converted point + /// + //////////////////////////////////////////////////////////// + sf::Vector2f ConvertCoords(unsigned int x, unsigned int y, const View& view) const; protected : @@ -145,19 +184,12 @@ private : //////////////////////////////////////////////////////////// virtual bool Activate(bool active) = 0; - //////////////////////////////////////////////////////////// - /// Set the OpenGL render states needed for the SFML rendering - /// - //////////////////////////////////////////////////////////// - void SetRenderStates(); - //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - View myDefaultView; ///< Default view - const View* myCurrentView; ///< Current active view - bool myPreserveStates; ///< Should we preserve external OpenGL states ? - bool myIsDrawing; ///< True when Draw is called from inside, to allow some renderstates optimizations + RenderQueue myRenderQueue; ///< Rendering queue storing render commands + View myDefaultView; ///< Default view + const View* myCurrentView; ///< Current active view }; } // namespace sf diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index 394720534..da1a65bb5 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -94,39 +94,6 @@ public : //////////////////////////////////////////////////////////// virtual unsigned int GetHeight() const; - //////////////////////////////////////////////////////////// - /// Save the content of the window to an image - /// - /// \return Image instance containing the contents of the screen - /// - //////////////////////////////////////////////////////////// - Image Capture() const; - - //////////////////////////////////////////////////////////// - /// Convert a point in window coordinates into view coordinates - /// This version uses the current view of the window - /// - /// \param x : X coordinate of the point to convert, relative to the window - /// \param y : Y coordinate of the point to convert, relative to the window - /// - /// \return Converted point - /// - //////////////////////////////////////////////////////////// - sf::Vector2f ConvertCoords(unsigned int x, unsigned int y) const; - - //////////////////////////////////////////////////////////// - /// Convert a point in window coordinates into view coordinates - /// This version uses the given view - /// - /// \param x : X coordinate of the point to convert, relative to the window - /// \param y : Y coordinate of the point to convert, relative to the window - /// \param view : Target view to convert the point to - /// - /// \return Converted point - /// - //////////////////////////////////////////////////////////// - sf::Vector2f ConvertCoords(unsigned int x, unsigned int y, const View& view) const; - private : //////////////////////////////////////////////////////////// @@ -135,6 +102,12 @@ private : //////////////////////////////////////////////////////////// virtual void OnCreate(); + //////////////////////////////////////////////////////////// + /// /see Window::OnDisplay + /// + //////////////////////////////////////////////////////////// + virtual void OnDisplay(); + //////////////////////////////////////////////////////////// /// /see RenderTarget::Activate /// diff --git a/include/SFML/Graphics/Shape.hpp b/include/SFML/Graphics/Shape.hpp index ff31c86ac..589e168e3 100644 --- a/include/SFML/Graphics/Shape.hpp +++ b/include/SFML/Graphics/Shape.hpp @@ -259,7 +259,7 @@ protected : /// /see Drawable::Render /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target) const; + virtual void Render(RenderTarget& target, RenderQueue& queue) const; private : diff --git a/include/SFML/Graphics/Sprite.hpp b/include/SFML/Graphics/Sprite.hpp index ee771e941..ec7262eb4 100644 --- a/include/SFML/Graphics/Sprite.hpp +++ b/include/SFML/Graphics/Sprite.hpp @@ -158,7 +158,7 @@ protected : /// /see Drawable::Render /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target) const; + virtual void Render(RenderTarget& target, RenderQueue& queue) const; private : diff --git a/include/SFML/Graphics/String.hpp b/include/SFML/Graphics/String.hpp index 6c930817d..10bc63e81 100644 --- a/include/SFML/Graphics/String.hpp +++ b/include/SFML/Graphics/String.hpp @@ -164,7 +164,7 @@ protected : /// /see Drawable::Render /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target) const; + virtual void Render(RenderTarget& target, RenderQueue& queue) const; private : diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 425aaa1ae..6188cc3a5 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -290,6 +290,12 @@ private : //////////////////////////////////////////////////////////// virtual void OnCreate(); + //////////////////////////////////////////////////////////// + /// Called before the window has been displayed + /// + //////////////////////////////////////////////////////////// + virtual void OnDisplay(); + //////////////////////////////////////////////////////////// /// /see WindowListener::OnEvent /// diff --git a/samples/opengl/OpenGL.cpp b/samples/opengl/OpenGL.cpp index 5e6f8c05d..b397db8a4 100644 --- a/samples/opengl/OpenGL.cpp +++ b/samples/opengl/OpenGL.cpp @@ -15,9 +15,11 @@ //////////////////////////////////////////////////////////// int main() { - // Create main window + // Create the main window and activate it sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL"); - window.PreserveOpenGLStates(true); + + // Activate it as the target for OpenGL calls + window.SetActive(); // Create a sprite for the background sf::Image backgroundImage; @@ -75,13 +77,23 @@ int main() // Adjust the viewport when the window is resized if (event.Type == sf::Event::Resized) + { + window.SetActive(); glViewport(0, 0, event.Size.Width, event.Size.Height); - } + } + } - // Draw background + // Draw the background window.Draw(background); - // Clear depth buffer + // Flush the window, to make sure that our OpenGL cube + // will be rendered on top of the background sprite + window.Flush(); + + // Activate the window + window.SetActive(); + + // Clear the depth buffer glClear(GL_DEPTH_BUFFER_BIT); // We get the position of the mouse cursor, so that we can move the box accordingly diff --git a/samples/window/Window.cpp b/samples/window/Window.cpp index aacd81719..70d4f9d75 100644 --- a/samples/window/Window.cpp +++ b/samples/window/Window.cpp @@ -17,6 +17,9 @@ int main() // Create the main window sf::Window window(sf::VideoMode(640, 480, 32), "SFML Window"); + // Activate it as the target for OpenGL calls + window.SetActive(); + // Create a clock for measuring the time elapsed sf::Clock clock; @@ -53,11 +56,6 @@ int main() glViewport(0, 0, event.Size.Width, event.Size.Height); } - // Set the active window before using OpenGL commands - // It's useless here because the active window is always the same, - // but don't forget it if you use multiple windows - window.SetActive(); - // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/src/SFML/Graphics/Batch.cpp b/src/SFML/Graphics/Batch.cpp new file mode 100644 index 000000000..2b2b5f4f0 --- /dev/null +++ b/src/SFML/Graphics/Batch.cpp @@ -0,0 +1,123 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +Batch::Batch(const Image* texture, Blend::Mode blendMode, const IntRect& viewport) : +myTexture (texture), +myBlendMode(blendMode), +myViewport (viewport), +myStart (0), +myCount (0) +{ +} + + +//////////////////////////////////////////////////////////// +bool Batch::Matches(const Image* texture, Blend::Mode blendMode, const IntRect& viewport) const +{ + return myTexture == texture && + myBlendMode == blendMode && + myViewport.Left == viewport.Left && + myViewport.Top == viewport.Top && + myViewport.Right == viewport.Right && + myViewport.Bottom == viewport.Bottom; +} + + +//////////////////////////////////////////////////////////// +void Batch::Begin(std::size_t index) +{ + myStart = index; +} + + +//////////////////////////////////////////////////////////// +void Batch::End(std::size_t index) +{ + myCount = index - myStart; +} + + +//////////////////////////////////////////////////////////// +std::size_t Batch::GetStartIndex() const +{ + return myStart; +} + + +//////////////////////////////////////////////////////////// +std::size_t Batch::GetIndexCount() const +{ + return myCount; +} + + +//////////////////////////////////////////////////////////// +void Batch::ApplyStates() const +{ + // Set the viewport + GLCheck(glViewport(myViewport.Left, myViewport.Top, myViewport.GetSize().x, myViewport.GetSize().y)); + + // Set the blending mode + if (myBlendMode == Blend::None) + { + GLCheck(glDisable(GL_BLEND)); + } + else + { + GLCheck(glEnable(GL_BLEND)); + + // @todo the resulting alpha may not be correct, which matters when target is a RenderImage. + // find a fix for this (glBlendFuncSeparate -- but not supported by every graphics card) + switch (myBlendMode) + { + default : + case Blend::Alpha : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); break; + case Blend::Add : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); break; + case Blend::Multiply : GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO)); break; + } + } + + // Bind the texture + if (myTexture) + myTexture->Bind(); + else + GLCheck(glDisable(GL_TEXTURE_2D)); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/Batch.hpp b/src/SFML/Graphics/Batch.hpp new file mode 100644 index 000000000..fbd375199 --- /dev/null +++ b/src/SFML/Graphics/Batch.hpp @@ -0,0 +1,125 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_BATCH_HPP +#define SFML_BATCH_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class Image; + +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Batch of geometry / render states to render +/// +//////////////////////////////////////////////////////////// +class Batch +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Construct the batch with its render states + /// + /// \param texture Texture to use + /// \param blendMode Blending mode + /// \param viewport Target viewport + /// + //////////////////////////////////////////////////////////// + Batch(const Image* texture = NULL, Blend::Mode blendMode = Blend::Alpha, const IntRect& viewport = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Check if the batch matches a set of render states + /// + /// \param texture Texture to use + /// \param blendMode Blending mode + /// \param viewport Target viewport + /// + //////////////////////////////////////////////////////////// + bool Matches(const Image* texture, Blend::Mode blendMode, const IntRect& viewport) const; + + //////////////////////////////////////////////////////////// + /// \brief Setup the start index of the batch + /// + /// \param index Start index + /// + //////////////////////////////////////////////////////////// + void Begin(std::size_t index); + + //////////////////////////////////////////////////////////// + /// \brief Setup the end index of the batch + /// + /// \param index End index + /// + //////////////////////////////////////////////////////////// + void End(std::size_t index); + + //////////////////////////////////////////////////////////// + /// \brief Return the start index of the batch + /// + /// \return Start index + /// + //////////////////////////////////////////////////////////// + std::size_t GetStartIndex() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the number of indices to render with this batch + /// + /// \return Index count + /// + //////////////////////////////////////////////////////////// + std::size_t GetIndexCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Apply the render states of the batch + /// + //////////////////////////////////////////////////////////// + void ApplyStates() const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const Image* myTexture; ///< Texture used by the batch + Blend::Mode myBlendMode; ///< Blending mode used by the batch + IntRect myViewport; ///< Target viewport for the batch + std::size_t myStart; ///< Index of the first index to render with this batch + std::size_t myCount; ///< Number of indices to render with this batch +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_BATCH_HPP diff --git a/src/SFML/Graphics/Drawable.cpp b/src/SFML/Graphics/Drawable.cpp index 02ae9bd5a..7ea56722a 100644 --- a/src/SFML/Graphics/Drawable.cpp +++ b/src/SFML/Graphics/Drawable.cpp @@ -26,8 +26,8 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include +#include +#include #include @@ -358,44 +358,21 @@ const Matrix3& Drawable::GetInverseMatrix() const //////////////////////////////////////////////////////////// -/// Draw the object into the specified window +/// Draw the object into the specified render target //////////////////////////////////////////////////////////// -void Drawable::Draw(RenderTarget& target) const +void Drawable::Draw(RenderTarget& target, RenderQueue& queue) const { - // Save the current modelview matrix and set the new one - GLCheck(glMatrixMode(GL_MODELVIEW)); - GLCheck(glPushMatrix()); - GLCheck(glMultMatrixf(GetMatrix().Get4x4Elements())); + // Set the current model-view matrix + queue.ApplyModelView(GetMatrix()); - // Setup alpha-blending - if (myBlendMode == Blend::None) - { - GLCheck(glDisable(GL_BLEND)); - } - else - { - GLCheck(glEnable(GL_BLEND)); + // Set the current global color + queue.ApplyColor(myColor); - // @todo the resulting alpha may not be correct, which matters when target is a RenderImage. - // find a fix for this (glBlendFuncSeparate -- but not supported by every graphics card) - switch (myBlendMode) - { - case Blend::Alpha : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); break; - case Blend::Add : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); break; - case Blend::Multiply : GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO)); break; - default : break; - } - } - - // Set color - GLCheck(glColor4ub(myColor.r, myColor.g, myColor.b, myColor.a)); + // Set the current alpha-blending mode + queue.SetBlendMode(myBlendMode); // Let the derived class render the object geometry - Render(target); - - // Restore the previous modelview matrix - GLCheck(glMatrixMode(GL_MODELVIEW)); - GLCheck(glPopMatrix()); + Render(target, queue); } } // namespace sf diff --git a/src/SFML/Graphics/FontLoader.cpp b/src/SFML/Graphics/FontLoader.cpp index 7d8f96989..3e03e07db 100644 --- a/src/SFML/Graphics/FontLoader.cpp +++ b/src/SFML/Graphics/FontLoader.cpp @@ -214,6 +214,11 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const glyphs.insert(std::make_pair(bitmapGlyph, charset[i])); } + // Leave a small margin around characters, so that filtering doesn't + // pollute them with pixels from neighbours + unsigned int offset = 1; + unsigned int margin = offset + 1; + // Copy the rendered glyphs into the texture unsigned int maxHeight = 0; std::map coords; @@ -225,31 +230,31 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const FT_Bitmap& bitmap = bitmapGlyph->bitmap; // Make sure we don't go over the texture width - if (left + bitmap.width + 1 >= texWidth) + if (left + bitmap.width + margin >= texWidth) left = 0; // Compute the top coordinate top = tops[left]; - for (int x = 0; x < bitmap.width + 1; ++x) + for (unsigned int x = 0; x < bitmap.width + margin; ++x) top = std::max(top, tops[left + x]); - top++; + top += margin; // Make sure we don't go over the texture height -- resize it if we need more space - if (top + bitmap.rows + 1 >= texHeight) + if (top + bitmap.rows + margin >= texHeight) { texHeight *= 2; glyphsBuffer.resize(texWidth * texHeight * 4); } // Store the character's position and size - curGlyph.Rectangle.Left = bitmapGlyph->left; - curGlyph.Rectangle.Top = -bitmapGlyph->top; - curGlyph.Rectangle.Right = curGlyph.Rectangle.Left + bitmap.width; - curGlyph.Rectangle.Bottom = bitmap.rows - bitmapGlyph->top; + curGlyph.Rectangle.Left = bitmapGlyph->left - offset; + curGlyph.Rectangle.Top = -bitmapGlyph->top - offset; + curGlyph.Rectangle.Right = (curGlyph.Rectangle.Left + bitmap.width + offset) / 1; + curGlyph.Rectangle.Bottom = bitmap.rows - bitmapGlyph->top + offset; curGlyph.Advance = bitmapGlyph->root.advance.x >> 16; // Texture size may change, so let the texture coordinates be calculated later - coords[i->second] = IntRect(left + 1, top + 1, left + bitmap.width + 1, top + bitmap.rows + 1); + coords[i->second] = IntRect(left + offset, top + offset, left + bitmap.width + offset + margin, top + bitmap.rows + offset + margin); // Draw the glyph into our bitmap font const Uint8* pixels = bitmap.buffer; @@ -257,19 +262,19 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const { for (int x = 0; x < bitmap.width; ++x) { - std::size_t index = x + left + 1 + (y + top + 1) * texWidth; + std::size_t index = x + left + margin + (y + top + margin) * texWidth; glyphsBuffer[index * 4 + 0] = 255; glyphsBuffer[index * 4 + 1] = 255; glyphsBuffer[index * 4 + 2] = 255; - glyphsBuffer[index * 4 + 3] = pixels[x]; + glyphsBuffer[index * 4 + 3] = pixels[x] * pixels[x] / 255; } pixels += bitmap.pitch; } // Update the rendering coordinates - for (int x = 0; x < bitmap.width + 1; ++x) + for (unsigned int x = 0; x < bitmap.width + margin; ++x) tops[left + x] = top + bitmap.rows; - left += bitmap.width + 1; + left += bitmap.width + margin; if (top + bitmap.rows > maxHeight) maxHeight = top + bitmap.rows; @@ -278,7 +283,7 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const } // Create the font's texture - texHeight = maxHeight + 1; + texHeight = maxHeight + margin; glyphsBuffer.resize(texWidth * texHeight * 4); font.myTexture.LoadFromPixels(texWidth, texHeight, &glyphsBuffer[0]); diff --git a/src/SFML/Graphics/GeometryRenderer.cpp b/src/SFML/Graphics/GeometryRenderer.cpp new file mode 100644 index 000000000..13bdf485c --- /dev/null +++ b/src/SFML/Graphics/GeometryRenderer.cpp @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +GeometryRenderer* GeometryRenderer::New() +{ + // Choose the best implementation according to the graphics card's capabilities + if (priv::GeometryRendererVBO::IsSupported()) + { + // Use Vertex Buffer Objects + return new priv::GeometryRendererVBO; + } + else if (priv::GeometryRendererVA::IsSupported()) + { + // Use Vertex Arrays + return new priv::GeometryRendererVA; + } + else + { + // Use Immediate Mode + return new priv::GeometryRendererIM; + } +} + + +//////////////////////////////////////////////////////////// +GeometryRenderer::~GeometryRenderer() +{ + // Nothing to do +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/GeometryRenderer.hpp b/src/SFML/Graphics/GeometryRenderer.hpp new file mode 100644 index 000000000..63df0b8e8 --- /dev/null +++ b/src/SFML/Graphics/GeometryRenderer.hpp @@ -0,0 +1,106 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GEOMETRYRENDERER_HPP +#define SFML_GEOMETRYRENDERER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for optimized geometry renderers +/// +//////////////////////////////////////////////////////////// +class GeometryRenderer : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Construct a new GeometryRenderer + /// + /// This function selects the best specialization available, + /// according to the capabilities of the system. + /// + /// \return New instance of GeometryRenderer; cannot be NULL + /// + //////////////////////////////////////////////////////////// + static GeometryRenderer* New(); + +public : + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~GeometryRenderer(); + + //////////////////////////////////////////////////////////// + /// \brief Prepare the geometry for rendering + /// + /// This function is called once before all the triangles + /// are rendered. + /// + /// \param vertices Pointer to the vertex array + /// \param verticesCount Number of vertices to render + /// \param indices Pointer to the index array + /// \param indicesCount Number of indices to render + /// + //////////////////////////////////////////////////////////// + virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Stop rendering geometry + /// + /// This function is called once after all the triangles + /// have been rendered. + /// + //////////////////////////////////////////////////////////// + virtual void End() = 0; + + //////////////////////////////////////////////////////////// + /// \brief Render a chunk of triangles + /// + /// The primitives are rendered as a list of triangles (no strip or fan). + /// + /// \param start Index in the indices array of the first index to be rendered + /// \param count Number of indices to be rendered + /// + //////////////////////////////////////////////////////////// + virtual void RenderTriangles(std::size_t start, std::size_t count) = 0; +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GEOMETRYRENDERER_HPP diff --git a/src/SFML/Graphics/GeometryRendererIM.cpp b/src/SFML/Graphics/GeometryRendererIM.cpp new file mode 100644 index 000000000..bb5460156 --- /dev/null +++ b/src/SFML/Graphics/GeometryRendererIM.cpp @@ -0,0 +1,95 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +bool GeometryRendererIM::IsSupported() +{ + // Immediate mode is always supported + return true; +} + + +//////////////////////////////////////////////////////////// +GeometryRendererIM::GeometryRendererIM() : +myVertices(NULL), +myIndices (NULL) +{ + +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererIM::Begin(const float* vertices, std::size_t, const unsigned int* indices, std::size_t) +{ + // Store the geometry informations for later rendering + myVertices = vertices; + myIndices = indices; +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererIM::End() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererIM::RenderTriangles(std::size_t start, std::size_t count) +{ + // Caculate the bounds of the geometry range to render + const unsigned int* begin = myIndices + start; + const unsigned int* end = begin + count; + + // Begin rendering + glBegin(GL_TRIANGLES); + + // Send the vertices one by one + for (const unsigned int* index = begin; index != end; index++) + { + const float* vertex = myVertices + *index * 8; + + glColor4f(vertex[2], vertex[3], vertex[4], vertex[5]); + glTexCoord2f(vertex[6], vertex[7]); + glVertex2f(vertex[0], vertex[1]); + } + + // End rendering + glEnd(); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/GeometryRendererIM.hpp b/src/SFML/Graphics/GeometryRendererIM.hpp new file mode 100644 index 000000000..5e2a8ee0c --- /dev/null +++ b/src/SFML/Graphics/GeometryRendererIM.hpp @@ -0,0 +1,108 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GEOMETRYRENDERERIM_HPP +#define SFML_GEOMETRYRENDERERIM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Geometry renderer using immediate mode +/// +//////////////////////////////////////////////////////////// +class GeometryRendererIM : public GeometryRenderer +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Check if this implementation is supported by the system + /// + /// \return True if the immediate mode renderer is supported + /// + //////////////////////////////////////////////////////////// + static bool IsSupported(); + +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + GeometryRendererIM(); + + //////////////////////////////////////////////////////////// + /// \brief Prepare the geometry for rendering + /// + /// This function is called once before all the triangles + /// are rendered. + /// + /// \param vertices Pointer to the vertex array + /// \param verticesCount Number of vertices to render + /// \param indices Pointer to the index array + /// \param indicesCount Number of indices to render + /// + //////////////////////////////////////////////////////////// + virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount); + + //////////////////////////////////////////////////////////// + /// \brief Stop rendering geometry + /// + /// This function is called once after all the triangles + /// have been rendered. + /// + //////////////////////////////////////////////////////////// + virtual void End(); + + //////////////////////////////////////////////////////////// + /// \brief Render a chunk of triangles + /// + /// The primitives are rendered as a list of triangles (no strip or fan). + /// + /// \param start Index in the indices array of the first index to be rendered + /// \param count Number of indices to be rendered + /// + //////////////////////////////////////////////////////////// + virtual void RenderTriangles(std::size_t start, std::size_t count); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const float* myVertices; ///< Pointer to the vertices to render + const unsigned int* myIndices; ///< Pointer to the indices to render +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GEOMETRYRENDERERIM_HPP diff --git a/src/SFML/Graphics/GeometryRendererVA.cpp b/src/SFML/Graphics/GeometryRendererVA.cpp new file mode 100644 index 000000000..50a5ec3d9 --- /dev/null +++ b/src/SFML/Graphics/GeometryRendererVA.cpp @@ -0,0 +1,99 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +bool GeometryRendererVA::IsSupported() +{ + EnsureGlewInit(); + + return glewIsSupported("GL_EXT_vertex_array") != 0; +} + + +//////////////////////////////////////////////////////////// +GeometryRendererVA::GeometryRendererVA() : +myIndices(NULL) +{ + EnsureGlewInit(); + + myCanLock = glewIsSupported("GL_EXT_compiled_vertex_array") != 0; +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererVA::Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t) +{ + static const GLsizei stride = 8 * sizeof(float); + + // Setup positions + GLCheck(glEnableClientState(GL_VERTEX_ARRAY)); + GLCheck(glVertexPointer(2, GL_FLOAT, stride, vertices)); + + // Setup colors + GLCheck(glEnableClientState(GL_COLOR_ARRAY)); + GLCheck(glColorPointer(4, GL_FLOAT, stride, vertices + 2)); + + // Setup texture coordinates + GLCheck(glClientActiveTextureARB(GL_TEXTURE0_ARB)); + GLCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + GLCheck(glTexCoordPointer(2, GL_FLOAT, stride, vertices + 6)); + + // Lock (compile) the vertex array if supported + if (myCanLock) + GLCheck(glLockArraysEXT(0, verticesCount / 8)); + + // Store indices for later use + myIndices = indices; +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererVA::End() +{ + // Unlock the vertex array if it was locked + if (myCanLock) + GLCheck(glUnlockArraysEXT()); +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererVA::RenderTriangles(std::size_t start, std::size_t count) +{ + GLCheck(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, myIndices + start)); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/GeometryRendererVA.hpp b/src/SFML/Graphics/GeometryRendererVA.hpp new file mode 100644 index 000000000..f4f050024 --- /dev/null +++ b/src/SFML/Graphics/GeometryRendererVA.hpp @@ -0,0 +1,108 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GEOMETRYRENDERERVA_HPP +#define SFML_GEOMETRYRENDERERVA_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Geometry renderer using vertex arrays +/// +//////////////////////////////////////////////////////////// +class GeometryRendererVA : public GeometryRenderer +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Check if this implementation is supported by the system + /// + /// \return True if the vertex array renderer is supported + /// + //////////////////////////////////////////////////////////// + static bool IsSupported(); + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + GeometryRendererVA(); + +public : + + //////////////////////////////////////////////////////////// + /// \brief Prepare the geometry for rendering + /// + /// This function is called once before all the triangles + /// are rendered. + /// + /// \param vertices Pointer to the vertex array + /// \param verticesCount Number of vertices to render + /// \param indices Pointer to the index array + /// \param indicesCount Number of indices to render + /// + //////////////////////////////////////////////////////////// + virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount); + + //////////////////////////////////////////////////////////// + /// \brief Stop rendering geometry + /// + /// This function is called once after all the triangles + /// have been rendered. + /// + //////////////////////////////////////////////////////////// + virtual void End(); + + //////////////////////////////////////////////////////////// + /// \brief Render a chunk of triangles + /// + /// The primitives are rendered as a list of triangles (no strip or fan). + /// + /// \param start Index in the indices array of the first index to be rendered + /// \param count Number of indices to be rendered + /// + //////////////////////////////////////////////////////////// + virtual void RenderTriangles(std::size_t start, std::size_t count); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + bool myCanLock; ///< Is geometry locking supported? + const unsigned int* myIndices; ///< Pointer to the indices to render +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GEOMETRYRENDERERVA_HPP diff --git a/src/SFML/Graphics/GeometryRendererVBO.cpp b/src/SFML/Graphics/GeometryRendererVBO.cpp new file mode 100644 index 000000000..a1058db15 --- /dev/null +++ b/src/SFML/Graphics/GeometryRendererVBO.cpp @@ -0,0 +1,127 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +bool GeometryRendererVBO::IsSupported() +{ + EnsureGlewInit(); + + return glewIsSupported("GL_ARB_vertex_buffer_object") != 0; +} + + +//////////////////////////////////////////////////////////// +GeometryRendererVBO::GeometryRendererVBO() : +myVertexBufferSize(0), +myIndexBufferSize (0) +{ + EnsureGlewInit(); + + // Create the buffers + GLCheck(glGenBuffersARB(1, &myVertexBuffer)); + GLCheck(glGenBuffersARB(1, &myIndexBuffer)); +} + + +//////////////////////////////////////////////////////////// +GeometryRendererVBO::~GeometryRendererVBO() +{ + // Free the buffers + GLCheck(glDeleteBuffersARB(1, &myVertexBuffer)); + GLCheck(glDeleteBuffersARB(1, &myIndexBuffer)); +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererVBO::Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount) +{ + // Update the vertex buffer data (make it grow if it is not large enough) + GLCheck(glBindBufferARB(GL_ARRAY_BUFFER_ARB, myVertexBuffer)); + if (verticesCount > myVertexBufferSize) + { + GLCheck(glBufferDataARB(GL_ARRAY_BUFFER_ARB, verticesCount * sizeof(float), vertices, GL_DYNAMIC_DRAW_ARB)); + myVertexBufferSize = verticesCount; + } + else + { + GLCheck(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, verticesCount * sizeof(float), vertices)); + } + + // Update the index buffer data (make it grow if it is not large enough) + GLCheck(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, myIndexBuffer)); + if (indicesCount > myIndexBufferSize) + { + GLCheck(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indicesCount * sizeof(unsigned int), indices, GL_DYNAMIC_DRAW_ARB)); + myIndexBufferSize = indicesCount; + } + else + { + GLCheck(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, indicesCount * sizeof(unsigned int), indices)); + } + + static const GLsizei stride = 8 * sizeof(float); + static const float* pointer = NULL; + + // Setup positions + GLCheck(glEnableClientState(GL_VERTEX_ARRAY)); + GLCheck(glVertexPointer(2, GL_FLOAT, stride, pointer)); + + // Setup colors + GLCheck(glEnableClientState(GL_COLOR_ARRAY)); + GLCheck(glColorPointer(4, GL_FLOAT, stride, pointer + 2)); + + // Setup texture coordinates + GLCheck(glClientActiveTextureARB(GL_TEXTURE0_ARB)); + GLCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + GLCheck(glTexCoordPointer(2, GL_FLOAT, stride, pointer + 6)); +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererVBO::End() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +void GeometryRendererVBO::RenderTriangles(std::size_t start, std::size_t count) +{ + static const unsigned int* pointer = NULL; + GLCheck(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, pointer + start)); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/GeometryRendererVBO.hpp b/src/SFML/Graphics/GeometryRendererVBO.hpp new file mode 100644 index 000000000..9bdd2a10e --- /dev/null +++ b/src/SFML/Graphics/GeometryRendererVBO.hpp @@ -0,0 +1,117 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GEOMETRYRENDERERVBO_HPP +#define SFML_GEOMETRYRENDERERVBO_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Geometry renderer using vertex buffer objects +/// +//////////////////////////////////////////////////////////// +class GeometryRendererVBO : public GeometryRenderer +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Check if this implementation is supported by the system + /// + /// \return True if the vertex buffer objects renderer is supported + /// + //////////////////////////////////////////////////////////// + static bool IsSupported(); + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + GeometryRendererVBO(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~GeometryRendererVBO(); + +public : + + //////////////////////////////////////////////////////////// + /// \brief Prepare the geometry for rendering + /// + /// This function is called once before all the triangles + /// are rendered. + /// + /// \param vertices Pointer to the vertex array + /// \param verticesCount Number of vertices to render + /// \param indices Pointer to the index array + /// \param indicesCount Number of indices to render + /// + //////////////////////////////////////////////////////////// + virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount); + + //////////////////////////////////////////////////////////// + /// \brief Stop rendering geometry + /// + /// This function is called once after all the triangles + /// have been rendered. + /// + //////////////////////////////////////////////////////////// + virtual void End(); + + //////////////////////////////////////////////////////////// + /// \brief Render a chunk of triangles + /// + /// The primitives are rendered as a list of triangles (no strip or fan). + /// + /// \param start Index in the indices array of the first index to be rendered + /// \param count Number of indices to be rendered + /// + //////////////////////////////////////////////////////////// + virtual void RenderTriangles(std::size_t start, std::size_t count); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + GLuint myVertexBuffer; + GLuint myIndexBuffer; + std::size_t myVertexBufferSize; + std::size_t myIndexBufferSize; +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GEOMETRYRENDERERVBO_HPP diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index 49cde69a3..87980779d 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -50,7 +50,6 @@ myTexture (0), myIsSmooth (true), myNeedTextureUpdate(false), myNeedArrayUpdate (false), -myUpdateSource (NULL), myPixelsFlipped (false) { @@ -71,7 +70,6 @@ myIsSmooth (copy.myIsSmooth), myPixels (copy.myPixels), myNeedTextureUpdate(false), myNeedArrayUpdate (false), -myUpdateSource (copy.myUpdateSource), myPixelsFlipped (copy.myPixelsFlipped) { CreateTexture(); @@ -90,7 +88,6 @@ myTexture (0), myIsSmooth (true), myNeedTextureUpdate(false), myNeedArrayUpdate (false), -myUpdateSource (NULL), myPixelsFlipped (false) { Create(width, height, color); @@ -109,7 +106,6 @@ myTexture (0), myIsSmooth (true), myNeedTextureUpdate(false), myNeedArrayUpdate (false), -myUpdateSource (NULL), myPixelsFlipped (false) { LoadFromPixels(width, height, data); @@ -387,6 +383,9 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect) myWidth = srcRect.GetSize().x; myHeight = srcRect.GetSize().y; + // Make sure that pending drawables are rendered on the target window + window.Flush(); + // We can then create the texture if (window.SetActive() && CreateTexture()) { @@ -402,6 +401,8 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect) myNeedArrayUpdate = true; myPixelsFlipped = true; + window.SetActive(false); + return true; } else @@ -553,12 +554,13 @@ FloatRect Image::GetTexCoords(const IntRect& rect) const { float width = static_cast(myTextureWidth); float height = static_cast(myTextureHeight); + float offset = myIsSmooth ? 0.5f : 0.0f; FloatRect coords; - coords.Left = rect.Left / width; - coords.Top = rect.Top / height; - coords.Right = rect.Right / width; - coords.Bottom = rect.Bottom / height; + coords.Left = (rect.Left + offset) / width; + coords.Top = (rect.Top + offset) / height; + coords.Right = (rect.Right - offset) / width; + coords.Bottom = (rect.Bottom - offset) / height; if (myPixelsFlipped) std::swap(coords.Top, coords.Bottom); @@ -607,7 +609,6 @@ Image& Image::operator =(const Image& other) std::swap(myIsSmooth, temp.myIsSmooth); std::swap(myNeedArrayUpdate, temp.myNeedArrayUpdate); std::swap(myNeedTextureUpdate, temp.myNeedTextureUpdate); - std::swap(myUpdateSource, temp.myUpdateSource); std::swap(myPixelsFlipped, temp.myPixelsFlipped); myPixels.swap(temp.myPixels); @@ -678,24 +679,15 @@ void Image::EnsureTextureUpdate() { if (myNeedTextureUpdate) { - if (myTexture) + if (myTexture && !myPixels.empty()) { GLint previous; GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - if (myUpdateSource) - { - // External update - myPixelsFlipped = myUpdateSource->UpdateImage(*this); - myUpdateSource = NULL; - } - else if (!myPixels.empty()) - { - // Update the texture with the pixels array in RAM - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0])); - myPixelsFlipped = false; - } + // Update the texture with the pixels array in RAM + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0])); + myPixelsFlipped = false; GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); } @@ -769,19 +761,6 @@ void Image::EnsureArrayUpdate() } -//////////////////////////////////////////////////////////// -/// Notify the image that an external source has modified -/// its content. -/// For internal use only (see RenderImage class). -//////////////////////////////////////////////////////////// -void Image::ExternalUpdate(RenderImage& source) -{ - myNeedTextureUpdate = true; - myNeedArrayUpdate = true; - myUpdateSource = &source; -} - - //////////////////////////////////////////////////////////// /// Reset the image attributes //////////////////////////////////////////////////////////// @@ -797,7 +776,6 @@ void Image::Reset() myIsSmooth = true; myNeedTextureUpdate = false; myNeedArrayUpdate = false; - myUpdateSource = NULL; myPixelsFlipped = false; myPixels.clear(); } diff --git a/src/SFML/Graphics/PostFX.cpp b/src/SFML/Graphics/PostFX.cpp index 8317ce5e9..cb2151cd4 100644 --- a/src/SFML/Graphics/PostFX.cpp +++ b/src/SFML/Graphics/PostFX.cpp @@ -275,7 +275,7 @@ bool PostFX::CanUsePostFX() //////////////////////////////////////////////////////////// /// /see Drawable::Render //////////////////////////////////////////////////////////// -void PostFX::Render(RenderTarget& target) const +void PostFX::Render(RenderTarget& target, RenderQueue&) const { // Check that we have a valid program if (!myShaderProgram) @@ -283,7 +283,9 @@ void PostFX::Render(RenderTarget& target) const // Copy the current framebuffer pixels to our frame buffer texture // The ugly cast is temporary until PostFx are rewritten :) - myFrameBuffer.CopyScreen((RenderWindow&)target); + RenderWindow& window = static_cast(target); + myFrameBuffer.CopyScreen(window); + window.SetActive(); // Enable program GLCheck(glUseProgramObjectARB(myShaderProgram)); diff --git a/src/SFML/Graphics/RenderImage.cpp b/src/SFML/Graphics/RenderImage.cpp index 4839ec1f5..2d99614cc 100644 --- a/src/SFML/Graphics/RenderImage.cpp +++ b/src/SFML/Graphics/RenderImage.cpp @@ -105,18 +105,24 @@ bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuff //////////////////////////////////////////////////////////// bool RenderImage::SetActive(bool active) { - if (myRenderImage && myRenderImage->Activate(active)) - { - // After the RenderImage has been modified, we have to notify - // the underlying image that its pixels have changed - if (!active) - myImage.ExternalUpdate(*this); + return myRenderImage && myRenderImage->Activate(active); +} - return true; - } - else + +//////////////////////////////////////////////////////////// +/// Update the contents of the target +//////////////////////////////////////////////////////////// +void RenderImage::Display() +{ + // Render everything that has been drawn so far + Flush(); + + // Update the target image + if (myRenderImage) { - return false; + bool pixelsFlipped = myRenderImage->UpdateTexture(myImage.myTexture); + myImage.myPixelsFlipped = pixelsFlipped; + myImage.myNeedArrayUpdate = true; } } @@ -158,17 +164,6 @@ bool RenderImage::CanUseRenderImage() } -//////////////////////////////////////////////////////////// -/// Update the pixels of the target image. -/// This function is called automatically by the image when it -/// needs to update its pixels, and is only meant for internal use. -//////////////////////////////////////////////////////////// -bool RenderImage::UpdateImage(Image& target) -{ - return myRenderImage && myRenderImage->UpdateTexture(target.myTexture); -} - - //////////////////////////////////////////////////////////// /// Activate / deactivate the render image for rendering //////////////////////////////////////////////////////////// diff --git a/src/SFML/Graphics/RenderQueue.cpp b/src/SFML/Graphics/RenderQueue.cpp new file mode 100644 index 000000000..5161c9458 --- /dev/null +++ b/src/SFML/Graphics/RenderQueue.cpp @@ -0,0 +1,328 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +//////////////////////////////////////////////////////////// +// Private data +//////////////////////////////////////////////////////////// +namespace +{ + // Fast float to int conversion + inline sf::Int32 Round(double value) + { + value += 6755399441055744.0; + + #if defined(SFML_ENDIAN_LITTLE) + return (reinterpret_cast(&value))[0]; + #else + return (reinterpret_cast(&value))[1]; + #endif + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +RenderQueue::RenderQueue() : +myCurrentTexture (NULL), +myCurrentBlendMode (Blend::Alpha), +myBaseIndex (0), +myRenderer (priv::GeometryRenderer::New()), +myCurrentBatch (NULL), +myVertices (512), +myIndices (512), +myCurrentVertexCount(0), +myCurrentIndexCount (0) +{ + myCurrentStates = &myStatesStack[0]; +} + + +//////////////////////////////////////////////////////////// +RenderQueue::~RenderQueue() +{ + // Destroy the geometry renderer + delete myRenderer; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::PushStates() +{ + myCurrentStates++; + *myCurrentStates = *(myCurrentStates - 1); +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::PopStates() +{ + myCurrentStates--; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::SetModelView(const Matrix3& matrix) +{ + myCurrentStates->modelView = matrix; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::ApplyModelView(const Matrix3& matrix) +{ + myCurrentStates->modelView *= matrix; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::SetProjection(const Matrix3& matrix) +{ + myCurrentStates->projection = matrix; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::ApplyProjection(const Matrix3& matrix) +{ + myCurrentStates->projection *= matrix; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::SetColor(const Color& color) +{ + myCurrentStates->color = color; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::ApplyColor(const Color& color) +{ + myCurrentStates->color *= color; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::SetViewport(const IntRect& viewport) +{ + myCurrentViewport = viewport; + myCurrentViewportSize.x = viewport.GetSize().x / 2.f; + myCurrentViewportSize.y = viewport.GetSize().y / 2.f; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::SetBlendMode(Blend::Mode mode) +{ + myCurrentBlendMode = mode; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::SetTexture(const Image* texture) +{ + myCurrentTexture = texture; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::BeginBatch() +{ + // Check if the current batch differs from the new render states + if (!myCurrentBatch || !myCurrentBatch->Matches(myCurrentTexture, myCurrentBlendMode, myCurrentViewport)) + { + // Close the current batch + if (myCurrentBatch) + myCurrentBatch->End(myCurrentIndexCount); + + // Create a new one + priv::Batch batch(myCurrentTexture, myCurrentBlendMode, myCurrentViewport); + myBatches.push_back(batch); + myCurrentBatch = &myBatches.back(); + myCurrentBatch->Begin(myCurrentIndexCount); + } + + // Update the combined transform matrix + myCurrentTransform = myCurrentStates->projection * myCurrentStates->modelView; + + // Update the current base index + myBaseIndex = myCurrentVertexCount / 8; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::AddVertex(float x, float y) +{ + AddVertex(x, y, 0.f, 0.f, Color::White); +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::AddVertex(float x, float y, float u, float v) +{ + AddVertex(x, y, u, v, Color::White); +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::AddVertex(float x, float y, const Color& color) +{ + AddVertex(x, y, 0.f, 0.f, color); +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::AddVertex(float x, float y, float u, float v, const Color& color) +{ + // Apply the current transform matrix to the vertex position + sf::Vector2f transformedPoint = myCurrentTransform.Transform(sf::Vector2f(x, y)); + + // Apply the current global color + sf::Color combinedColor = myCurrentStates->color * color; + + // Round the vertex position so that it matches the + // viewport's pixels, and thus avoid rendering artifacts + int i1 = Round((transformedPoint.x + 1.f) * myCurrentViewportSize.x); + int i2 = Round((transformedPoint.y + 1.f) * myCurrentViewportSize.y); + transformedPoint.x = i1 / myCurrentViewportSize.x - 1.f; + transformedPoint.y = i2 / myCurrentViewportSize.y - 1.f; + + // Here we choose not to rely on vector::clear and vector::push_back, + // and to handle resizing and appending manually, for performances reasons + + // Resize the vertex buffer if it is too small + std::size_t size = myVertices.size(); + if (myCurrentVertexCount + 8 > size) + myVertices.resize(size + size / 2); + + // Copy the vertex data + float* ptr = &myVertices[myCurrentVertexCount]; + *ptr++ = transformedPoint.x; + *ptr++ = transformedPoint.y; + *ptr++ = combinedColor.r / 255.f; + *ptr++ = combinedColor.g / 255.f; + *ptr++ = combinedColor.b / 255.f; + *ptr++ = combinedColor.a / 255.f; + *ptr++ = u; + *ptr++ = v; + + // Increase the vertex count + myCurrentVertexCount += 8; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::AddTriangle(unsigned int index0, unsigned int index1, unsigned int index2) +{ + // Here we choose not to rely on vector::clear and vector::push_back, + // and to handle resizing and appending manually, for performances reasons + + // Resize the index buffer if it is too small + std::size_t size = myIndices.size(); + if (myCurrentIndexCount + 3 > size) + myIndices.resize(size + size / 2); + + // Copy the index data + myIndices[myCurrentIndexCount + 0] = index0 + myBaseIndex; + myIndices[myCurrentIndexCount + 1] = index1 + myBaseIndex; + myIndices[myCurrentIndexCount + 2] = index2 + myBaseIndex; + + // Increase the index count + myCurrentIndexCount += 3; +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::Render() +{ + if (myCurrentVertexCount && myCurrentIndexCount) + { + // Save the current OpenGL states + GLCheck(glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_VIEWPORT_BIT)); + GLCheck(glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)); + GLCheck(glDisable(GL_LIGHTING)); + GLCheck(glDisable(GL_DEPTH_TEST)); + GLCheck(glEnable(GL_ALPHA_TEST)); + GLCheck(glAlphaFunc(GL_GREATER, 0)); + GLCheck(glMatrixMode(GL_MODELVIEW)); + GLCheck(glPushMatrix()); + GLCheck(glLoadIdentity()); + GLCheck(glMatrixMode(GL_PROJECTION)); + GLCheck(glPushMatrix()); + GLCheck(glLoadIdentity()); + + // Close the last batch + if (myCurrentBatch) + myCurrentBatch->End(myCurrentIndexCount); + + // Prepare the geometry renderer + myRenderer->Begin(&myVertices[0], myCurrentVertexCount, &myIndices[0], myCurrentIndexCount); + + // Render the batches in order + for (BatchArray::const_iterator it = myBatches.begin(); it != myBatches.end(); ++it) + { + it->ApplyStates(); + myRenderer->RenderTriangles(it->GetStartIndex(), it->GetIndexCount()); + } + + // Stop rendering + myRenderer->End(); + + // Restore the previous OpenGL states + GLCheck(glMatrixMode(GL_PROJECTION)); + GLCheck(glPopMatrix()); + GLCheck(glMatrixMode(GL_MODELVIEW)); + GLCheck(glPopMatrix()); + GLCheck(glPopAttrib()); + GLCheck(glPopClientAttrib()); + } + + // Clear everything + Clear(); +} + + +//////////////////////////////////////////////////////////// +void RenderQueue::Clear() +{ + // Reset the vertex and index counts + myCurrentVertexCount = 0; + myCurrentIndexCount = 0; + + // Clear the batches + myBatches.clear(); + myCurrentBatch = NULL; +} + +} // namespace sf diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 2f181509e..cfc729605 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -37,9 +37,7 @@ namespace sf /// Default constructor //////////////////////////////////////////////////////////// RenderTarget::RenderTarget() : -myCurrentView (&myDefaultView), -myPreserveStates(false), -myIsDrawing (false) +myCurrentView(&myDefaultView) { } @@ -61,10 +59,13 @@ void RenderTarget::Clear(const Color& color) { if (Activate(true)) { - // Clear the frame buffer + // Clear the color buffer GLCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f)); GLCheck(glClear(GL_COLOR_BUFFER_BIT)); + // Clear the render queue + myRenderQueue.Clear(); + Activate(false); } } @@ -75,59 +76,34 @@ void RenderTarget::Clear(const Color& color) //////////////////////////////////////////////////////////// void RenderTarget::Draw(const Drawable& object) { - // Check whether we are called from the outside or from a previous call to Draw - if (!myIsDrawing) + // Save the current render states + myRenderQueue.PushStates(); + + // Setup the viewport + myRenderQueue.SetViewport(GetViewport(*myCurrentView)); + + // Setup the projection matrix + myRenderQueue.SetProjection(myCurrentView->GetMatrix()); + + // Let the object draw itself + object.Draw(*this, myRenderQueue); + + // Restore the previous render states + myRenderQueue.PopStates(); +} + + +//////////////////////////////////////////////////////////// +/// Make sure that what has been drawn so far is rendered +//////////////////////////////////////////////////////////// +void RenderTarget::Flush() +{ + if (Activate(true)) { - myIsDrawing = true; + // Draw the whole render queue + myRenderQueue.Render(); - // Set our target as the current target for rendering - if (Activate(true)) - { - // Save the current render states and set the SFML ones - if (myPreserveStates) - { - GLCheck(glMatrixMode(GL_MODELVIEW)); GLCheck(glPushMatrix()); - GLCheck(glMatrixMode(GL_PROJECTION)); GLCheck(glPushMatrix()); - GLCheck(glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | - GL_TEXTURE_BIT | GL_TRANSFORM_BIT | GL_VIEWPORT_BIT)); - SetRenderStates(); - } - - // Setup the viewport - const FloatRect& viewport = myCurrentView->GetViewport(); - int left = static_cast(0.5f + GetWidth() * viewport.Left); - int top = static_cast(0.5f + GetHeight() * (1.f - viewport.Bottom)); - int width = static_cast(0.5f + GetWidth() * viewport.GetSize().x); - int height = static_cast(0.5f + GetHeight() * viewport.GetSize().y); - GLCheck(glViewport(left, top, width, height)); - - // Setup the transform matrices - GLCheck(glMatrixMode(GL_PROJECTION)); - GLCheck(glLoadMatrixf(myCurrentView->GetMatrix().Get4x4Elements())); - GLCheck(glMatrixMode(GL_MODELVIEW)); - GLCheck(glLoadIdentity()); - - // Let the object draw itself - object.Draw(*this); - - // Restore render states - if (myPreserveStates) - { - GLCheck(glMatrixMode(GL_PROJECTION)); GLCheck(glPopMatrix()); - GLCheck(glMatrixMode(GL_MODELVIEW)); GLCheck(glPopMatrix()); - GLCheck(glPopAttrib()); - } - - // Deactivate rendering on this target - Activate(false); - } - - myIsDrawing = false; - } - else - { - // We are already called from a previous Draw : we don't need to set the states again, just draw the object - object.Draw(*this); + Activate(false); } } @@ -160,16 +136,48 @@ View& RenderTarget::GetDefaultView() //////////////////////////////////////////////////////////// -/// Tell SFML to preserve external OpenGL states, at the expense of -/// more CPU charge. Use this function if you don't want SFML -/// to mess up your own OpenGL states (if any). -/// Don't enable state preservation if not needed, as it will allow -/// SFML to do internal optimizations and improve performances. -/// This parameter is false by default +/// Get the viewport of a view applied to this target //////////////////////////////////////////////////////////// -void RenderTarget::PreserveOpenGLStates(bool preserve) +IntRect RenderTarget::GetViewport(const View& view) const { - myPreserveStates = preserve; + float width = static_cast(GetWidth()); + float height = static_cast(GetHeight()); + const FloatRect& viewport = view.GetViewport(); + + IntRect rect; + rect.Left = static_cast(0.5f + width * viewport.Left); + rect.Top = static_cast(0.5f + height * (1.f - viewport.Bottom)); + rect.Right = static_cast(0.5f + width * viewport.Right); + rect.Bottom = static_cast(0.5f + height * (1.f - viewport.Top)); + + return rect; +} + + +//////////////////////////////////////////////////////////// +/// Convert a point in window coordinates into view coordinates +/// This version uses the current view of the window +//////////////////////////////////////////////////////////// +sf::Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y) const +{ + return ConvertCoords(x, y, GetView()); +} + + +//////////////////////////////////////////////////////////// +/// Convert a point in window coordinates into view coordinates +/// This version uses the given view +//////////////////////////////////////////////////////////// +sf::Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y, const View& view) const +{ + // First, convert from viewport coordinates to homogeneous coordinates + Vector2f coords; + IntRect viewport = GetViewport(view); + coords.x = -1.f + 2.f * (static_cast(x) - viewport.Left) / viewport.GetSize().x; + coords.y = 1.f - 2.f * (static_cast(y) - viewport.Top) / viewport.GetSize().y; + + // Then transform by the inverse of the view matrix + return view.GetInverseMatrix().Transform(coords); } @@ -178,28 +186,12 @@ void RenderTarget::PreserveOpenGLStates(bool preserve) //////////////////////////////////////////////////////////// void RenderTarget::Initialize() { - if (Activate(true)) - { - // Set the default rendering states - SetRenderStates(); + // Setup the default view + myDefaultView.Reset(FloatRect(0, 0, static_cast(GetWidth()), static_cast(GetHeight()))); + SetView(myDefaultView); - // Setup the default view - myDefaultView.Reset(FloatRect(0, 0, static_cast(GetWidth()), static_cast(GetHeight()))); - SetView(myDefaultView); - - Activate(false); - } -} - - -//////////////////////////////////////////////////////////// -/// Set the OpenGL render states needed for the SFML rendering -//////////////////////////////////////////////////////////// -void RenderTarget::SetRenderStates() -{ - GLCheck(glDisable(GL_ALPHA_TEST)); - GLCheck(glDisable(GL_DEPTH_TEST)); - GLCheck(glDisable(GL_LIGHTING)); + // Clear the render queue + myRenderQueue.Clear(); } } // namespace sf diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp index a4179277e..8cfb19dd4 100644 --- a/src/SFML/Graphics/RenderWindow.cpp +++ b/src/SFML/Graphics/RenderWindow.cpp @@ -75,11 +75,7 @@ RenderWindow::~RenderWindow() //////////////////////////////////////////////////////////// bool RenderWindow::Activate(bool active) { - // For performances and consistency reasons, we only handle activation - if (active) - return SetActive(); - else - return true; + return SetActive(active); } @@ -101,70 +97,6 @@ unsigned int RenderWindow::GetHeight() const } -//////////////////////////////////////////////////////////// -/// Save the content of the window to an image -//////////////////////////////////////////////////////////// -Image RenderWindow::Capture() const -{ - // Get the window dimensions - const unsigned int width = GetWidth(); - const unsigned int height = GetHeight(); - - // Set our window as the current target for rendering - if (SetActive()) - { - // Get pixels from the backbuffer - std::vector pixels(width * height * 4); - Uint8* ptr = &pixels[0]; - GLCheck(glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptr)); - - // Flip the pixels - unsigned int pitch = width * 4; - for (unsigned int y = 0; y < height / 2; ++y) - std::swap_ranges(ptr + y * pitch, ptr + (y + 1) * pitch, ptr + (height - y - 1) * pitch); - - // Create an image from the pixel buffer and return it - return Image(width, height, ptr); - } - else - { - return Image(width, height, Color::White); - } -} - - -//////////////////////////////////////////////////////////// -/// Convert a point in window coordinates into view coordinates -/// This version uses the current view of the window -//////////////////////////////////////////////////////////// -sf::Vector2f RenderWindow::ConvertCoords(unsigned int x, unsigned int y) const -{ - return ConvertCoords(x, y, GetView()); -} - - -//////////////////////////////////////////////////////////// -/// Convert a point in window coordinates into view coordinates -/// This version uses the given view -//////////////////////////////////////////////////////////// -sf::Vector2f RenderWindow::ConvertCoords(unsigned int x, unsigned int y, const View& view) const -{ - // First, convert from viewport coordinates to homogeneous coordinates - const FloatRect& viewport = view.GetViewport(); - int left = static_cast(0.5f + GetWidth() * viewport.Left); - int top = static_cast(0.5f + GetHeight() * viewport.Top); - int width = static_cast(0.5f + GetWidth() * viewport.GetSize().x); - int height = static_cast(0.5f + GetHeight() * viewport.GetSize().y); - - Vector2f coords; - coords.x = -1.f + 2.f * (static_cast(x) - left) / width; - coords.y = 1.f - 2.f * (static_cast(y) - top) / height; - - // Then transform by the inverse of the view matrix - return view.GetInverseMatrix().Transform(coords); -} - - //////////////////////////////////////////////////////////// /// Called after the window has been created //////////////////////////////////////////////////////////// @@ -174,4 +106,14 @@ void RenderWindow::OnCreate() RenderTarget::Initialize(); } + +//////////////////////////////////////////////////////////// +/// Called before the window has been displayed +//////////////////////////////////////////////////////////// +void RenderWindow::OnDisplay() +{ + // Render the drawables drawn so far + Flush(); +} + } // namespace sf diff --git a/src/SFML/Graphics/Shape.cpp b/src/SFML/Graphics/Shape.cpp index 866f0316a..b7b8e6bf7 100644 --- a/src/SFML/Graphics/Shape.cpp +++ b/src/SFML/Graphics/Shape.cpp @@ -26,7 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include @@ -281,7 +281,7 @@ Shape Shape::Circle(const Vector2f& center, float radius, const Color& color, fl //////////////////////////////////////////////////////////// /// /see Drawable::Render //////////////////////////////////////////////////////////// -void Shape::Render(RenderTarget&) const +void Shape::Render(RenderTarget&, RenderQueue& queue) const { // Make sure the shape has at least 3 points (4 if we count the center) if (myPoints.size() < 4) @@ -292,50 +292,69 @@ void Shape::Render(RenderTarget&) const const_cast(this)->Compile(); // Shapes only use color, no texture - GLCheck(glDisable(GL_TEXTURE_2D)); + queue.SetTexture(NULL); // Draw the shape if (myIsFillEnabled) { - glBegin(GL_TRIANGLE_FAN); + if (myPoints.size() == 4) { + // Special case of a triangle + queue.BeginBatch(); + queue.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col); + queue.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col); + queue.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col); + queue.AddTriangle(0, 1, 2); + } + else if (myPoints.size() == 5) + { + // Special case of a quad + queue.BeginBatch(); + queue.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col); + queue.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col); + queue.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col); + queue.AddVertex(myPoints[4].Position.x, myPoints[4].Position.y, myPoints[4].Col); + queue.AddTriangle(0, 1, 3); + queue.AddTriangle(3, 1, 2); + } + else + { + // General case of a convex polygon + queue.BeginBatch(); for (std::vector::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i) - { - Color color = i->Col * GetColor(); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(i->Position.x, i->Position.y); - } + queue.AddVertex(i->Position.x, i->Position.y, i->Col); + + for (std::size_t i = 1; i < myPoints.size() - 1; ++i) + queue.AddTriangle(0, i, i + 1); // Close the shape by duplicating the first point at the end - Color color = myPoints[1].Col * GetColor(); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y); + queue.AddTriangle(0, myPoints.size() - 1, 1); } - glEnd(); } // Draw the outline - if (myIsOutlineEnabled) + if (myIsOutlineEnabled && (myOutline != 0)) { - glBegin(GL_TRIANGLE_STRIP); + queue.BeginBatch(); + for (std::vector::const_iterator i = myPoints.begin() + 1; i != myPoints.end(); ++i) { - for (std::size_t i = 1; i < myPoints.size(); ++i) - { - Color color = myPoints[i].OutlineCol * GetColor(); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(myPoints[i].Position.x, myPoints[i].Position.y); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(myPoints[i].Position.x + myPoints[i].Normal.x * myOutline, myPoints[i].Position.y + myPoints[i].Normal.y * myOutline); - } - - // Close the shape by duplicating the first point at the end - Color color = myPoints[1].OutlineCol * GetColor(); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(myPoints[1].Position.x + myPoints[1].Normal.x * myOutline, myPoints[1].Position.y + myPoints[1].Normal.y * myOutline); + Vector2f point1 = i->Position; + Vector2f point2 = i->Position + i->Normal * myOutline; + queue.AddVertex(point1.x, point1.y, i->OutlineCol); + queue.AddVertex(point2.x, point2.y, i->OutlineCol); } - glEnd(); + + for (std::size_t i = 0; i < myPoints.size() - 2; ++i) + { + queue.AddTriangle(i * 2 + 0, i * 2 + 1, i * 2 + 2); + queue.AddTriangle(i * 2 + 2, i * 2 + 1, i * 2 + 3); + } + + // Close the shape by duplicating the first point at the end + unsigned int begin = 0; + unsigned int last = (myPoints.size() - 2) * 2; + queue.AddTriangle(last, last + 1, begin); + queue.AddTriangle(begin, last + 1, begin + 1); } } @@ -351,16 +370,17 @@ void Shape::Compile() Point center(Vector2f(0, 0), Color(0, 0, 0, 0)); for (std::size_t i = 1; i < myPoints.size(); ++i) { - center.Position += myPoints[i].Position / nbPoints; - r += myPoints[i].Col.r / nbPoints; - g += myPoints[i].Col.g / nbPoints; - b += myPoints[i].Col.b / nbPoints; - a += myPoints[i].Col.a / nbPoints; + center.Position += myPoints[i].Position; + r += myPoints[i].Col.r; + g += myPoints[i].Col.g; + b += myPoints[i].Col.b; + a += myPoints[i].Col.a; } - center.Col.r = static_cast(r); - center.Col.g = static_cast(g); - center.Col.b = static_cast(b); - center.Col.a = static_cast(a); + center.Position /= nbPoints; + center.Col.r = static_cast(r / nbPoints); + center.Col.g = static_cast(g / nbPoints); + center.Col.b = static_cast(b / nbPoints); + center.Col.a = static_cast(a / nbPoints); myPoints[0] = center; // Compute the outline diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp index 52fb60b57..99ee50f2e 100644 --- a/src/SFML/Graphics/Sprite.cpp +++ b/src/SFML/Graphics/Sprite.cpp @@ -27,7 +27,8 @@ //////////////////////////////////////////////////////////// #include #include -#include +#include +#include namespace sf @@ -181,50 +182,32 @@ Color Sprite::GetPixel(unsigned int x, unsigned int y) const //////////////////////////////////////////////////////////// /// /see Drawable::Render //////////////////////////////////////////////////////////// -void Sprite::Render(RenderTarget&) const +void Sprite::Render(RenderTarget&, RenderQueue& queue) const { // Get the sprite size float width = static_cast(mySubRect.GetSize().x); float height = static_cast(mySubRect.GetSize().y); - // Check if the image is valid + // Check if the image is valid, and calculate the texture coordinates + FloatRect coords; if (myImage && (myImage->GetWidth() > 0) && (myImage->GetHeight() > 0)) { - // Use the "offset trick" to get pixel-perfect rendering - // see http://www.opengl.org/resources/faq/technical/transformations.htm#tran0030 - GLCheck(glTranslatef(0.375f, 0.375f, 0.f)); - - // Bind the texture - myImage->Bind(); - - // Calculate the texture coordinates - FloatRect texCoords = myImage->GetTexCoords(mySubRect); - FloatRect rect(myIsFlippedX ? texCoords.Right : texCoords.Left, - myIsFlippedY ? texCoords.Bottom : texCoords.Top, - myIsFlippedX ? texCoords.Left : texCoords.Right, - myIsFlippedY ? texCoords.Top : texCoords.Bottom); - - // Draw the sprite's triangles - glBegin(GL_QUADS); - glTexCoord2f(rect.Left, rect.Top); glVertex2f(0, 0); - glTexCoord2f(rect.Left, rect.Bottom); glVertex2f(0, height); - glTexCoord2f(rect.Right, rect.Bottom); glVertex2f(width, height); - glTexCoord2f(rect.Right, rect.Top); glVertex2f(width, 0) ; - glEnd(); + coords = myImage->GetTexCoords(mySubRect); + if (myIsFlippedX) std::swap(coords.Left, coords.Right); + if (myIsFlippedY) std::swap(coords.Top, coords.Bottom); } - else - { - // Disable texturing - GLCheck(glDisable(GL_TEXTURE_2D)); - // Draw the sprite's triangles - glBegin(GL_QUADS); - glVertex2f(0, 0); - glVertex2f(0, height); - glVertex2f(width, height); - glVertex2f(width, 0); - glEnd(); - } + // Bind the texture + queue.SetTexture(myImage); + + // Draw the sprite's geometry + queue.BeginBatch(); + queue.AddVertex(0, 0, coords.Left, coords.Top); + queue.AddVertex(0, height, coords.Left, coords.Bottom); + queue.AddVertex(width, height, coords.Right, coords.Bottom); + queue.AddVertex(width, 0, coords.Right, coords.Top); + queue.AddTriangle(0, 1, 3); + queue.AddTriangle(3, 1, 2); } } // namespace sf diff --git a/src/SFML/Graphics/String.cpp b/src/SFML/Graphics/String.cpp index d07d0f580..60b3f23d4 100644 --- a/src/SFML/Graphics/String.cpp +++ b/src/SFML/Graphics/String.cpp @@ -27,8 +27,7 @@ //////////////////////////////////////////////////////////// #include #include -#include -#include +#include namespace sf @@ -210,7 +209,7 @@ FloatRect String::GetRect() const //////////////////////////////////////////////////////////// /// /see sfDrawable::Render //////////////////////////////////////////////////////////// -void String::Render(RenderTarget&) const +void String::Render(RenderTarget&, RenderQueue& queue) const { // First get the internal UTF-32 string of the text const Unicode::UTF32String& text = myText; @@ -222,10 +221,9 @@ void String::Render(RenderTarget&) const // Set the scaling factor to get the actual size float charSize = static_cast(myFont->GetCharacterSize()); float factor = mySize / charSize; - GLCheck(glScalef(factor, factor, 1.f)); // Bind the font texture - myFont->GetImage().Bind(); + queue.SetTexture(&myFont->GetImage()); // Initialize the rendering coordinates float x = 0.f; @@ -239,7 +237,8 @@ void String::Render(RenderTarget&) const float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees // Draw one quad for each character - glBegin(GL_QUADS); + unsigned int index = 0; + queue.BeginBatch(); for (std::size_t i = 0; i < text.size(); ++i) { // Get the current character and its corresponding glyph @@ -267,31 +266,67 @@ void String::Render(RenderTarget&) const } // Draw a textured quad for the current character - glTexCoord2f(coord.Left, coord.Top); glVertex2f(x + rect.Left - italicCoeff * rect.Top, y + rect.Top); - glTexCoord2f(coord.Left, coord.Bottom); glVertex2f(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom); - glTexCoord2f(coord.Right, coord.Bottom); glVertex2f(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom); - glTexCoord2f(coord.Right, coord.Top); glVertex2f(x + rect.Right - italicCoeff * rect.Top, y + rect.Top); + queue.AddVertex(factor * (x + rect.Left - italicCoeff * rect.Top), factor * (y + rect.Top), coord.Left, coord.Top); + queue.AddVertex(factor * (x + rect.Left - italicCoeff * rect.Bottom), factor * (y + rect.Bottom), coord.Left, coord.Bottom); + queue.AddVertex(factor * (x + rect.Right - italicCoeff * rect.Bottom), factor * (y + rect.Bottom), coord.Right, coord.Bottom); + queue.AddVertex(factor * (x + rect.Right - italicCoeff * rect.Top), factor * (y + rect.Top), coord.Right, coord.Top); - // If we're using the bold style, we must render the character 4 more times, - // slightly offseted, to simulate a higher weight - if (myStyle & Bold) - { - static const float offsetsX[] = {-0.5f, 0.5f, 0.f, 0.f}; - static const float offsetsY[] = {0.f, 0.f, -0.5f, 0.5f}; - - for (int j = 0; j < 4; ++j) - { - glTexCoord2f(coord.Left, coord.Top); glVertex2f(x + offsetsX[j] + rect.Left - italicCoeff * rect.Top, y + offsetsY[j] + rect.Top); - glTexCoord2f(coord.Left, coord.Bottom); glVertex2f(x + offsetsX[j] + rect.Left - italicCoeff * rect.Bottom, y + offsetsY[j] + rect.Bottom); - glTexCoord2f(coord.Right, coord.Bottom); glVertex2f(x + offsetsX[j] + rect.Right - italicCoeff * rect.Bottom, y + offsetsY[j] + rect.Bottom); - glTexCoord2f(coord.Right, coord.Top); glVertex2f(x + offsetsX[j] + rect.Right - italicCoeff * rect.Top, y + offsetsY[j] + rect.Top); - } - } + queue.AddTriangle(index + 0, index + 1, index + 3); + queue.AddTriangle(index + 3, index + 1, index + 2); + index += 4; // Advance to the next character x += advance; } - glEnd(); + + // If we're using the bold style, we must render the string 4 more times, + // slightly offseted, to simulate a higher weight + if (myStyle & Bold) + { + float offset = mySize * 0.02f; + static const float offsetsX[] = {-offset, offset, 0.f, 0.f}; + static const float offsetsY[] = {0.f, 0.f, -offset, offset}; + + for (int j = 0; j < 4; ++j) + { + index = 0; + x = 0.f; + y = charSize; + + queue.BeginBatch(); + for (std::size_t i = 0; i < text.size(); ++i) + { + // Get the current character and its corresponding glyph + Uint32 curChar = text[i]; + const Glyph& curGlyph = myFont->GetGlyph(curChar); + int advance = curGlyph.Advance; + const IntRect& rect = curGlyph.Rectangle; + const FloatRect& coord = curGlyph.TexCoords; + + // Handle special characters + switch (curChar) + { + case L' ' : x += advance; continue; + case L'\n' : y += charSize; x = 0; continue; + case L'\t' : x += advance * 4; continue; + case L'\v' : y += charSize * 4; continue; + } + + // Draw a textured quad for the current character + queue.AddVertex(factor * (x + offsetsX[j] + rect.Left - italicCoeff * rect.Top), factor * (y + offsetsY[j] + rect.Top), coord.Left, coord.Top); + queue.AddVertex(factor * (x + offsetsX[j] + rect.Left - italicCoeff * rect.Bottom), factor * (y + offsetsY[j] + rect.Bottom), coord.Left, coord.Bottom); + queue.AddVertex(factor * (x + offsetsX[j] + rect.Right - italicCoeff * rect.Bottom), factor * (y + offsetsY[j] + rect.Bottom), coord.Right, coord.Bottom); + queue.AddVertex(factor * (x + offsetsX[j] + rect.Right - italicCoeff * rect.Top), factor * (y + offsetsY[j] + rect.Top), coord.Right, coord.Top); + + queue.AddTriangle(index + 0, index + 1, index + 3); + queue.AddTriangle(index + 3, index + 1, index + 2); + index += 4; + + // Advance to the next character + x += advance; + } + } + } // Draw the underlines if needed if (myStyle & Underlined) @@ -304,16 +339,20 @@ void String::Render(RenderTarget&) const underlineCoords.push_back(y + 2); // Draw the underlines as quads - GLCheck(glDisable(GL_TEXTURE_2D)); - glBegin(GL_QUADS); + index = 0; + queue.SetTexture(NULL); + queue.BeginBatch(); for (std::size_t i = 0; i < underlineCoords.size(); i += 2) { - glVertex2f(0, underlineCoords[i + 1]); - glVertex2f(0, underlineCoords[i + 1] + thickness); - glVertex2f(underlineCoords[i], underlineCoords[i + 1] + thickness); - glVertex2f(underlineCoords[i], underlineCoords[i + 1]); + queue.AddVertex(factor * (0), factor * (underlineCoords[i + 1])); + queue.AddVertex(factor * (0), factor * (underlineCoords[i + 1] + thickness)); + queue.AddVertex(factor * (underlineCoords[i]), factor * (underlineCoords[i + 1] + thickness)); + queue.AddVertex(factor * (underlineCoords[i]), factor * (underlineCoords[i + 1])); + + queue.AddTriangle(index + 0, index + 1, index + 3); + queue.AddTriangle(index + 3, index + 1, index + 2); + index += 4; } - glEnd(); } } diff --git a/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp b/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp index c1d914f56..de54c01d1 100644 --- a/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp +++ b/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp @@ -179,7 +179,8 @@ bool RenderImageImplPBuffer::Activate(bool active) } else { - // We don't actually unbind the P-Buffer, for performances reasons + // We don't actually unbind the P-Buffer, + // for performances and consistency reasons } return true; diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index 40666e6fa..31122efee 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -140,21 +140,17 @@ void Window::Create(VideoMode mode, const std::string& title, unsigned long styl delete myWindow; myWindow = priv::WindowImpl::New(mode, title, style); - { - // Make sure another context is bound, so that: - // - the context creation can request OpenGL extensions if necessary - // - myContext can safely be destroyed (it's no longer bound) - Context context; + // Make sure another context is bound, so that: + // - the context creation can request OpenGL extensions if necessary + // - myContext can safely be destroyed (it's no longer bound) + Context context; - // Recreate the context - delete myContext; - myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings); + // Recreate the context + delete myContext; + myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings); - Initialize(); - } - - // Activate the window's context - SetActive(); + // Perform common initializations + Initialize(); } @@ -167,21 +163,17 @@ void Window::Create(WindowHandle handle, const ContextSettings& settings) Close(); myWindow = priv::WindowImpl::New(handle); - { - // Make sure another context is bound, so that: - // - the context creation can request OpenGL extensions if necessary - // - myContext can safely be destroyed (it's no longer bound) - Context context; + // Make sure another context is bound, so that: + // - the context creation can request OpenGL extensions if necessary + // - myContext can safely be destroyed (it's no longer bound) + Context context; - // Recreate the context - delete myContext; - myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings); + // Recreate the context + delete myContext; + myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings); - Initialize(); - } - - // Activate the window's context - SetActive(); + // Perform common initializations + Initialize(); } @@ -391,6 +383,9 @@ bool Window::SetActive(bool active) const //////////////////////////////////////////////////////////// void Window::Display() { + // Notify the derived class + OnDisplay(); + // Limit the framerate if needed if (myFramerateLimit > 0) { @@ -404,8 +399,11 @@ void Window::Display() myClock.Reset(); // Display the backbuffer on screen - if (SetActive()) + if (SetActive(true)) + { myContext->Display(); + SetActive(false); + } } @@ -456,6 +454,15 @@ void Window::OnCreate() } +//////////////////////////////////////////////////////////// +/// Called before the window has been displayed +//////////////////////////////////////////////////////////// +void Window::OnDisplay() +{ + // Nothing by default +} + + //////////////////////////////////////////////////////////// /// Receive an event from window ////////////////////////////////////////////////////////////